blob: e4cc4d8b167d446325e808131b193f54614b124b [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% PPPP OOO L IIIII CCCC Y Y %
6% P P O O L I C Y Y %
7% PPPP O O L I C Y %
8% P O O L I C Y %
9% P OOO LLLLL IIIII CCCC Y %
10% %
11% %
12% MagickCore Policy Methods %
13% %
14% Software Design %
15% John Cristy %
16% July 1992 %
17% %
18% %
19% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35% We use linked-lists because splay-trees do not currently support duplicate
36% key / value pairs (.e.g X11 green compliance and SVG green compliance).
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/client.h"
45#include "magick/configure.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/memory_.h"
49#include "magick/monitor.h"
50#include "magick/monitor-private.h"
51#include "magick/option.h"
52#include "magick/policy.h"
53#include "magick/semaphore.h"
54#include "magick/string_.h"
55#include "magick/token.h"
56#include "magick/utility.h"
57#include "magick/xml-tree.h"
58
59/*
60 Define declarations.
61*/
62#define PolicyFilename "policy.xml"
63
64/*
65 Declare policy map.
66*/
67static const char
68 *PolicyMap = (const char *)
69 "<?xml version=\"1.0\"?>"
70 "<policymap>"
71 "</policymap>";
72
73/*
74 Domaindef declarations.
75*/
76struct _PolicyInfo
77{
78 char
79 *path,
80 *name;
81
82 PolicyDomain
83 domain;
84
85 PolicyRights
86 rights;
87
88 char
89 *pattern,
90 *value;
91
92 MagickBooleanType
93 stealth,
94 debug;
95
96 SemaphoreInfo
97 *semaphore;
98
99 unsigned long
100 signature;
101};
102
103/*
104 Static declarations.
105*/
106static LinkedListInfo
107 *policy_list = (LinkedListInfo *) NULL;
108
109static SemaphoreInfo
110 *policy_semaphore = (SemaphoreInfo *) NULL;
111
112static volatile MagickBooleanType
113 instantiate_policy = MagickFalse;
114
115/*
116 Forward declarations.
117*/
118static MagickBooleanType
119 InitializePolicyList(ExceptionInfo *),
120 LoadPolicyLists(const char *,ExceptionInfo *);
121
122/*
123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124% %
125% %
126% %
127+ D e s t r o y P o l i c y L i s t %
128% %
129% %
130% %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
133% DestroyPolicyList() deallocates memory associated with the policy list.
134%
135% The format of the DestroyPolicyList method is:
136%
137% DestroyPolicyList(void)
138%
139*/
140
141static void *DestroyPolicyElement(void *policy_info)
142{
143 register PolicyInfo
144 *p;
145
146 p=(PolicyInfo *) policy_info;
147 if (p->value != (char *) NULL)
148 p->value=DestroyString(p->value);
149 if (p->pattern != (char *) NULL)
150 p->pattern=DestroyString(p->pattern);
151 if (p->name != (char *) NULL)
152 p->name=DestroyString(p->name);
153 if (p->path != (char *) NULL)
154 p->path=DestroyString(p->path);
155 p=(PolicyInfo *) RelinquishMagickMemory(p);
156 return((void *) NULL);
157}
158
159MagickExport void DestroyPolicyList(void)
160{
161 AcquireSemaphoreInfo(&policy_semaphore);
162 if (policy_list != (LinkedListInfo *) NULL)
163 policy_list=DestroyLinkedList(policy_list,DestroyPolicyElement);
164 instantiate_policy=MagickFalse;
165 RelinquishSemaphoreInfo(policy_semaphore);
166 DestroySemaphoreInfo(&policy_semaphore);
167}
168
169/*
170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171% %
172% %
173% %
174+ G e t P o l i c y I n f o %
175% %
176% %
177% %
178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179%
180% GetPolicyInfo() searches the policy list for the specified name and if found
181% returns attributes for that policy.
182%
183% The format of the GetPolicyInfo method is:
184%
185% PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
186%
187% A description of each parameter follows:
188%
189% o name: the policy name.
190%
191% o exception: return any errors or warnings in this structure.
192%
193*/
194static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
195{
196 char
197 policyname[MaxTextExtent];
198
199 register PolicyInfo
200 *p;
201
202 register char
203 *q;
204
205 assert(exception != (ExceptionInfo *) NULL);
206 if ((policy_list == (LinkedListInfo *) NULL) ||
207 (instantiate_policy == MagickFalse))
208 if (InitializePolicyList(exception) == MagickFalse)
209 return((PolicyInfo *) NULL);
210 if ((policy_list == (LinkedListInfo *) NULL) ||
211 (IsLinkedListEmpty(policy_list) != MagickFalse))
212 return((PolicyInfo *) NULL);
213 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
214 return((PolicyInfo *) GetValueFromLinkedList(policy_list,0));
215 /*
216 Strip names of whitespace.
217 */
218 (void) CopyMagickString(policyname,name,MaxTextExtent);
219 for (q=policyname; *q != '\0'; q++)
220 {
221 if (isspace((int) ((unsigned char) *q)) == 0)
222 continue;
223 (void) CopyMagickString(q,q+1,MaxTextExtent);
224 q--;
225 }
226 /*
227 Search for policy tag.
228 */
229 AcquireSemaphoreInfo(&policy_semaphore);
230 ResetLinkedListIterator(policy_list);
231 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
232 while (p != (PolicyInfo *) NULL)
233 {
234 if (LocaleCompare(policyname,p->name) == 0)
235 break;
236 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
237 }
238 if (p == (PolicyInfo *) NULL)
239 (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
240 "UnrecognizedPolicy","`%s'",name);
241 else
242 (void) InsertValueInLinkedList(policy_list,0,
243 RemoveElementByValueFromLinkedList(policy_list,p));
244 RelinquishSemaphoreInfo(policy_semaphore);
245 return(p);
246}
247
248/*
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250% %
251% %
252% %
253% G e t P o l i c y I n f o L i s t %
254% %
255% %
256% %
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258%
259% GetPolicyInfoList() returns any policies that match the specified pattern.
260%
261% The format of the GetPolicyInfoList function is:
262%
263% const PolicyInfo **GetPolicyInfoList(const char *pattern,
264% unsigned long *number_policies,ExceptionInfo *exception)
265%
266% A description of each parameter follows:
267%
268% o pattern: Specifies a pointer to a text string containing a pattern.
269%
270% o number_policies: returns the number of policies in the list.
271%
272% o exception: return any errors or warnings in this structure.
273%
274*/
275MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
276 unsigned long *number_policies,ExceptionInfo *exception)
277{
278 const PolicyInfo
279 **policies;
280
281 register const PolicyInfo
282 *p;
283
284 register long
285 i;
286
287 /*
288 Allocate policy list.
289 */
290 assert(pattern != (char *) NULL);
291 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
292 assert(number_policies != (unsigned long *) NULL);
293 *number_policies=0;
294 p=GetPolicyInfo("*",exception);
295 if (p == (const PolicyInfo *) NULL)
296 return((const PolicyInfo **) NULL);
297 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
298 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
299 if (policies == (const PolicyInfo **) NULL)
300 return((const PolicyInfo **) NULL);
301 /*
302 Generate policy list.
303 */
304 AcquireSemaphoreInfo(&policy_semaphore);
305 ResetLinkedListIterator(policy_list);
306 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
307 for (i=0; p != (const PolicyInfo *) NULL; )
308 {
309 if ((p->stealth == MagickFalse) &&
310 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
311 policies[i++]=p;
312 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
313 }
314 RelinquishSemaphoreInfo(policy_semaphore);
315 policies[i]=(PolicyInfo *) NULL;
316 *number_policies=(unsigned long) i;
317 return(policies);
318}
319
320/*
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322% %
323% %
324% %
325% G e t P o l i c y L i s t %
326% %
327% %
328% %
329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330%
331% GetPolicyList() returns any policies that match the specified pattern.
332%
333% The format of the GetPolicyList function is:
334%
335% char **GetPolicyList(const char *pattern,unsigned long *number_policies,
336% ExceptionInfo *exception)
337%
338% A description of each parameter follows:
339%
340% o pattern: a pointer to a text string containing a pattern.
341%
342% o number_policies: returns the number of policies in the list.
343%
344% o exception: return any errors or warnings in this structure.
345%
346*/
347MagickExport char **GetPolicyList(const char *pattern,
348 unsigned long *number_policies,ExceptionInfo *exception)
349{
350 char
351 **policies;
352
353 register const PolicyInfo
354 *p;
355
356 register long
357 i;
358
359 /*
360 Allocate policy list.
361 */
362 assert(pattern != (char *) NULL);
363 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
364 assert(number_policies != (unsigned long *) NULL);
365 *number_policies=0;
366 p=GetPolicyInfo("*",exception);
367 if (p == (const PolicyInfo *) NULL)
368 return((char **) NULL);
369 policies=(char **) AcquireQuantumMemory((size_t)
370 GetNumberOfElementsInLinkedList(policy_list)+1UL,sizeof(*policies));
371 if (policies == (char **) NULL)
372 return((char **) NULL);
373 /*
374 Generate policy list.
375 */
376 AcquireSemaphoreInfo(&policy_semaphore);
377 ResetLinkedListIterator(policy_list);
378 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
379 for (i=0; p != (const PolicyInfo *) NULL; )
380 {
381 if ((p->stealth == MagickFalse) &&
382 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
383 policies[i++]=ConstantString(p->name);
384 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_list);
385 }
386 RelinquishSemaphoreInfo(policy_semaphore);
387 policies[i]=(char *) NULL;
388 *number_policies=(unsigned long) i;
389 return(policies);
390}
391
392/*
393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394% %
395% %
396% %
397% G e t P o l i c y V a l u e %
398% %
399% %
400% %
401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402%
403% GetPolicyValue() returns the value associated with the named policy.
404%
405% The format of the GetPolicyValue method is:
406%
407% char *GetPolicyValue(const char *name)
408%
409% A description of each parameter follows:
410%
411% o policy_info: The policy info.
412%
413*/
414MagickExport char *GetPolicyValue(const char *name)
415{
416 const char
417 *value;
418
419 const PolicyInfo
420 *policy_info;
421
422 ExceptionInfo
423 *exception;
424
425 assert(name != (const char *) NULL);
426 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
427 exception=AcquireExceptionInfo();
428 policy_info=GetPolicyInfo(name,exception);
429 exception=DestroyExceptionInfo(exception);
430 if (policy_info == (PolicyInfo *) NULL)
431 return((char *) NULL);
432 value=policy_info->value;
433 if ((value == (const char *) NULL) || (*value == '\0'))
434 return((char *) NULL);
435 return(ConstantString(value));
436}
437
438/*
439%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440% %
441% %
442% %
443+ I n i t i a l i z e P o l i c y L i s t %
444% %
445% %
446% %
447%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448%
449% InitializePolicyList() initializes the policy list.
450%
451% The format of the InitializePolicyList method is:
452%
453% MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
454%
455% A description of each parameter follows.
456%
457% o exception: return any errors or warnings in this structure.
458%
459*/
460static MagickBooleanType InitializePolicyList(ExceptionInfo *exception)
461{
462 if ((policy_list == (LinkedListInfo *) NULL) &&
463 (instantiate_policy == MagickFalse))
464 {
465 AcquireSemaphoreInfo(&policy_semaphore);
466 if ((policy_list == (LinkedListInfo *) NULL) &&
467 (instantiate_policy == MagickFalse))
468 {
469 (void) LoadPolicyLists(PolicyFilename,exception);
470 instantiate_policy=MagickTrue;
471 }
472 RelinquishSemaphoreInfo(policy_semaphore);
473 }
474 return(policy_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
475}
476
477/*
478%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479% %
480% %
481% %
482% I s R i g h t s A u t h o r i z e d %
483% %
484% %
485% %
486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487%
488% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
489% requested rights for the specified domain.
490%
491% The format of the IsRightsAuthorized method is:
492%
493% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
494% const PolicyRights rights,const char *pattern)
495%
496% A description of each parameter follows:
497%
498% o domain: the policy domain.
499%
500% o rights: the policy rights.
501%
502% o pattern: the coder, delegate, filter, or path pattern.
503%
504*/
505MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
506 const PolicyRights rights,const char *pattern)
507{
508 const PolicyInfo
509 *policy_info;
510
511 ExceptionInfo
512 *exception;
513
514 MagickBooleanType
515 authorized;
516
517 register PolicyInfo
518 *p;
519
520 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
521 "Domain: %s; rights=%s; pattern=\"%s\" ...",
522 MagickOptionToMnemonic(MagickPolicyDomainOptions,domain),
523 MagickOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
524 exception=AcquireExceptionInfo();
525 policy_info=GetPolicyInfo("*",exception);
526 exception=DestroyExceptionInfo(exception);
527 if (policy_info == (PolicyInfo *) NULL)
528 return(MagickTrue);
529 authorized=MagickTrue;
530 AcquireSemaphoreInfo(&policy_semaphore);
531 ResetLinkedListIterator(policy_list);
532 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
533 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
534 {
535 if ((p->domain == domain) &&
536 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
537 {
538 if (((rights & ReadPolicyRights) != 0) &&
539 ((p->rights & ReadPolicyRights) == 0))
540 authorized=MagickFalse;
541 if (((rights & WritePolicyRights) != 0) &&
542 ((p->rights & WritePolicyRights) == 0))
543 authorized=MagickFalse;
544 if (((rights & ExecutePolicyRights) != 0) &&
545 ((p->rights & ExecutePolicyRights) == 0))
546 authorized=MagickFalse;
547 }
548 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
549 }
550 RelinquishSemaphoreInfo(policy_semaphore);
551 return(authorized);
552}
553
554/*
555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556% %
557% %
558% %
559% L i s t P o l i c y I n f o %
560% %
561% %
562% %
563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564%
565% ListPolicyInfo() lists policies to the specified file.
566%
567% The format of the ListPolicyInfo method is:
568%
569% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
570%
571% A description of each parameter follows.
572%
573% o file: List policy names to this file handle.
574%
575% o exception: return any errors or warnings in this structure.
576%
577*/
578MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
579 ExceptionInfo *exception)
580{
581 const char
582 *path,
583 *domain;
584
585 const PolicyInfo
586 **policy_info;
587
588 register long
589 i;
590
591 unsigned long
592 number_policies;
593
594 /*
595 List name and attributes of each policy in the list.
596 */
597 if (file == (const FILE *) NULL)
598 file=stdout;
599 policy_info=GetPolicyInfoList("*",&number_policies,exception);
600 if (policy_info == (const PolicyInfo **) NULL)
601 return(MagickFalse);
602 path=(const char *) NULL;
603 for (i=0; i < (long) number_policies; i++)
604 {
605 if (policy_info[i]->stealth != MagickFalse)
606 continue;
607 if (((path == (const char *) NULL) ||
608 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
609 (policy_info[i]->path != (char *) NULL))
610 (void) fprintf(file,"\nPath: %s\n",policy_info[i]->path);
611 path=policy_info[i]->path;
612 domain=MagickOptionToMnemonic(MagickPolicyDomainOptions,
613 policy_info[i]->domain);
614 (void) fprintf(file," Policy: %s\n",domain);
615 if (policy_info[i]->domain == ResourcePolicyDomain)
616 {
617 if (policy_info[i]->name != (char *) NULL)
618 (void) fprintf(file," name: %s\n",policy_info[i]->name);
619 if (policy_info[i]->value != (char *) NULL)
620 (void) fprintf(file," value: %s\n",policy_info[i]->value);
621 }
622 else
623 {
624 (void) fprintf(file," rights: ");
625 if (policy_info[i]->rights == NoPolicyRights)
626 (void) fprintf(file,"None ");
627 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
628 (void) fprintf(file,"Read ");
629 if ((policy_info[i]->rights & WritePolicyRights) != 0)
630 (void) fprintf(file,"Write ");
631 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
632 (void) fprintf(file,"Execute ");
633 (void) fprintf(file,"\n");
634 if (policy_info[i]->pattern != (char *) NULL)
635 (void) fprintf(file," pattern: %s\n",policy_info[i]->pattern);
636 }
637 }
638 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
639 policy_info);
640 (void) fflush(file);
641 return(MagickTrue);
642}
643
644/*
645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646% %
647% %
648% %
649+ L o a d P o l i c y L i s t %
650% %
651% %
652% %
653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654%
655% LoadPolicyList() loads the policy configuration file which provides a mapping
656% between policy attributes and a policy domain.
657%
658% The format of the LoadPolicyList method is:
659%
660% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
661% const unsigned long depth,ExceptionInfo *exception)
662%
663% A description of each parameter follows:
664%
665% o xml: The policy list in XML format.
666%
667% o filename: The policy list filename.
668%
669% o depth: depth of <include /> statements.
670%
671% o exception: return any errors or warnings in this structure.
672%
673*/
674static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
675 const unsigned long depth,ExceptionInfo *exception)
676{
677 char
678 keyword[MaxTextExtent],
679 *token;
680
681 PolicyInfo
682 *policy_info;
683
684 const char
685 *q;
686
687 MagickBooleanType
688 status;
689
690 /*
691 Load the policy map file.
692 */
693 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
694 "Loading policy file \"%s\" ...",filename);
695 if (xml == (char *) NULL)
696 return(MagickFalse);
697 if (policy_list == (LinkedListInfo *) NULL)
698 {
699 policy_list=NewLinkedList(0);
700 if (policy_list == (LinkedListInfo *) NULL)
701 {
702 ThrowFileException(exception,ResourceLimitError,
703 "MemoryAllocationFailed",filename);
704 return(MagickFalse);
705 }
706 }
707 status=MagickTrue;
708 policy_info=(PolicyInfo *) NULL;
709 token=AcquireString(xml);
710 for (q=(const char *) xml; *q != '\0'; )
711 {
712 /*
713 Interpret XML.
714 */
715 GetMagickToken(q,&q,token);
716 if (*token == '\0')
717 break;
718 (void) CopyMagickString(keyword,token,MaxTextExtent);
719 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
720 {
721 /*
722 Docdomain element.
723 */
724 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
725 GetMagickToken(q,&q,token);
726 continue;
727 }
728 if (LocaleNCompare(keyword,"<!--",4) == 0)
729 {
730 /*
731 Comment element.
732 */
733 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
734 GetMagickToken(q,&q,token);
735 continue;
736 }
737 if (LocaleCompare(keyword,"<include") == 0)
738 {
739 /*
740 Include element.
741 */
742 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
743 {
744 (void) CopyMagickString(keyword,token,MaxTextExtent);
745 GetMagickToken(q,&q,token);
746 if (*token != '=')
747 continue;
748 GetMagickToken(q,&q,token);
749 if (LocaleCompare(keyword,"file") == 0)
750 {
751 if (depth > 200)
752 (void) ThrowMagickException(exception,GetMagickModule(),
753 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
754 else
755 {
756 char
757 path[MaxTextExtent],
758 *xml;
759
760 GetPathComponent(filename,HeadPath,path);
761 if (*path != '\0')
762 (void) ConcatenateMagickString(path,DirectorySeparator,
763 MaxTextExtent);
764 if (*token == *DirectorySeparator)
765 (void) CopyMagickString(path,token,MaxTextExtent);
766 else
767 (void) ConcatenateMagickString(path,token,MaxTextExtent);
768 xml=FileToString(path,~0,exception);
769 if (xml != (char *) NULL)
770 {
771 status=LoadPolicyList(xml,path,depth+1,exception);
772 xml=(char *) RelinquishMagickMemory(xml);
773 }
774 }
775 }
776 }
777 continue;
778 }
779 if (LocaleCompare(keyword,"<policy") == 0)
780 {
781 /*
782 Policy element.
783 */
784 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
785 if (policy_info == (PolicyInfo *) NULL)
786 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
787 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
788 policy_info->path=ConstantString(filename);
789 policy_info->signature=MagickSignature;
790 continue;
791 }
792 if (policy_info == (PolicyInfo *) NULL)
793 continue;
794 if (LocaleCompare(keyword,"/>") == 0)
795 {
796 status=AppendValueToLinkedList(policy_list,policy_info);
797 if (status == MagickFalse)
798 (void) ThrowMagickException(exception,GetMagickModule(),
799 ResourceLimitError,"MemoryAllocationFailed","`%s'",
800 policy_info->name);
801 policy_info=(PolicyInfo *) NULL;
802 }
803 GetMagickToken(q,(const char **) NULL,token);
804 if (*token != '=')
805 continue;
806 GetMagickToken(q,&q,token);
807 GetMagickToken(q,&q,token);
808 switch (*keyword)
809 {
810 case 'D':
811 case 'd':
812 {
813 if (LocaleCompare((char *) keyword,"domain") == 0)
814 {
815 policy_info->domain=(PolicyDomain) ParseMagickOption(
816 MagickPolicyDomainOptions,MagickTrue,token);
817 break;
818 }
819 break;
820 }
821 case 'N':
822 case 'n':
823 {
824 if (LocaleCompare((char *) keyword,"name") == 0)
825 {
826 policy_info->name=ConstantString(token);
827 break;
828 }
829 break;
830 }
831 case 'P':
832 case 'p':
833 {
834 if (LocaleCompare((char *) keyword,"pattern") == 0)
835 {
836 policy_info->pattern=ConstantString(token);
837 break;
838 }
839 break;
840 }
841 case 'R':
842 case 'r':
843 {
844 if (LocaleCompare((char *) keyword,"rights") == 0)
845 {
846 policy_info->rights=(PolicyRights) ParseMagickOption(
847 MagickPolicyRightsOptions,MagickTrue,token);
848 break;
849 }
850 break;
851 }
852 case 'S':
853 case 's':
854 {
855 if (LocaleCompare((char *) keyword,"stealth") == 0)
856 {
857 policy_info->stealth=IsMagickTrue(token);
858 break;
859 }
860 break;
861 }
862 case 'V':
863 case 'v':
864 {
865 if (LocaleCompare((char *) keyword,"value") == 0)
866 {
867 policy_info->value=ConstantString(token);
868 break;
869 }
870 break;
871 }
872 default:
873 break;
874 }
875 }
876 token=(char *) RelinquishMagickMemory(token);
877 return(status);
878}
879
880/*
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882% %
883% %
884% %
885% L o a d P o l i c y L i s t s %
886% %
887% %
888% %
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890%
891% LoadPolicyList() loads one or more policy configuration file which provides a
892% mapping between policy attributes and a policy name.
893%
894% The format of the LoadPolicyLists method is:
895%
896% MagickBooleanType LoadPolicyLists(const char *filename,
897% ExceptionInfo *exception)
898%
899% A description of each parameter follows:
900%
901% o filename: the font file name.
902%
903% o exception: return any errors or warnings in this structure.
904%
905*/
906static MagickBooleanType LoadPolicyLists(const char *filename,
907 ExceptionInfo *exception)
908{
909#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
910 return(LoadPolicyList(PolicyMap,"built-in",0,exception));
911#else
912 const StringInfo
913 *option;
914
915 LinkedListInfo
916 *options;
917
918 MagickStatusType
919 status;
920
921 status=MagickFalse;
922 options=GetConfigureOptions(filename,exception);
923 option=(const StringInfo *) GetNextValueInLinkedList(options);
924 while (option != (const StringInfo *) NULL)
925 {
926 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
927 GetStringInfoPath(option),0,exception);
928 option=(const StringInfo *) GetNextValueInLinkedList(options);
929 }
930 options=DestroyConfigureOptions(options);
931 if ((policy_list == (LinkedListInfo *) NULL) ||
932 (IsLinkedListEmpty(policy_list) != MagickFalse))
933 status|=LoadPolicyList(PolicyMap,"built-in",0,exception);
934 return(status != 0 ? MagickTrue : MagickFalse);
935#endif
936}