blob: d5cc002f88ffbd32a83809378538ce85a8b3d478 [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% %
cristydf1cc5f2009-10-19 16:02:33 +0000127+ D e s t r o y P o l i c y C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000128% %
129% %
130% %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
cristydf1cc5f2009-10-19 16:02:33 +0000133% DestroyPolicyComponent() destroys the policy component.
cristy3ed852e2009-09-05 21:47:34 +0000134%
cristydf1cc5f2009-10-19 16:02:33 +0000135% The format of the DestroyPolicyComponent method is:
cristy3ed852e2009-09-05 21:47:34 +0000136%
cristydf1cc5f2009-10-19 16:02:33 +0000137% DestroyPolicyComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000138%
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
cristydf1cc5f2009-10-19 16:02:33 +0000159MagickExport void DestroyPolicyComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000160{
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% %
cristydf1cc5f2009-10-19 16:02:33 +0000482+ I n s t a n t i a t e P o l i c y C o m p o n e n t %
cristy41c3c772009-10-19 02:17:37 +0000483% %
484% %
485% %
486%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
487%
cristydf1cc5f2009-10-19 16:02:33 +0000488% InstantiatePolicyComponent() instantiates the policy component.
cristy41c3c772009-10-19 02:17:37 +0000489%
cristydf1cc5f2009-10-19 16:02:33 +0000490% The format of the InstantiatePolicyComponent method is:
cristy41c3c772009-10-19 02:17:37 +0000491%
cristydf1cc5f2009-10-19 16:02:33 +0000492% MagickBooleanType InstantiatePolicyComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000493%
494*/
cristydf1cc5f2009-10-19 16:02:33 +0000495MagickExport MagickBooleanType InstantiatePolicyComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000496{
497 AcquireSemaphoreInfo(&policy_semaphore);
498 RelinquishSemaphoreInfo(policy_semaphore);
499 return(MagickTrue);
500}
501
502/*
503%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
504% %
505% %
506% %
cristy3ed852e2009-09-05 21:47:34 +0000507% I s R i g h t s A u t h o r i z e d %
508% %
509% %
510% %
511%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512%
513% IsRightsAuthorized() returns MagickTrue if the policy authorizes the
514% requested rights for the specified domain.
515%
516% The format of the IsRightsAuthorized method is:
517%
518% MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
519% const PolicyRights rights,const char *pattern)
520%
521% A description of each parameter follows:
522%
523% o domain: the policy domain.
524%
525% o rights: the policy rights.
526%
527% o pattern: the coder, delegate, filter, or path pattern.
528%
529*/
530MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
531 const PolicyRights rights,const char *pattern)
532{
533 const PolicyInfo
534 *policy_info;
535
536 ExceptionInfo
537 *exception;
538
539 MagickBooleanType
540 authorized;
541
542 register PolicyInfo
543 *p;
544
545 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
546 "Domain: %s; rights=%s; pattern=\"%s\" ...",
547 MagickOptionToMnemonic(MagickPolicyDomainOptions,domain),
548 MagickOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
549 exception=AcquireExceptionInfo();
550 policy_info=GetPolicyInfo("*",exception);
551 exception=DestroyExceptionInfo(exception);
552 if (policy_info == (PolicyInfo *) NULL)
553 return(MagickTrue);
554 authorized=MagickTrue;
555 AcquireSemaphoreInfo(&policy_semaphore);
556 ResetLinkedListIterator(policy_list);
557 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
558 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
559 {
560 if ((p->domain == domain) &&
561 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
562 {
563 if (((rights & ReadPolicyRights) != 0) &&
564 ((p->rights & ReadPolicyRights) == 0))
565 authorized=MagickFalse;
566 if (((rights & WritePolicyRights) != 0) &&
567 ((p->rights & WritePolicyRights) == 0))
568 authorized=MagickFalse;
569 if (((rights & ExecutePolicyRights) != 0) &&
570 ((p->rights & ExecutePolicyRights) == 0))
571 authorized=MagickFalse;
572 }
573 p=(PolicyInfo *) GetNextValueInLinkedList(policy_list);
574 }
575 RelinquishSemaphoreInfo(policy_semaphore);
576 return(authorized);
577}
578
579/*
580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581% %
582% %
583% %
584% L i s t P o l i c y I n f o %
585% %
586% %
587% %
588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589%
590% ListPolicyInfo() lists policies to the specified file.
591%
592% The format of the ListPolicyInfo method is:
593%
594% MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
595%
596% A description of each parameter follows.
597%
598% o file: List policy names to this file handle.
599%
600% o exception: return any errors or warnings in this structure.
601%
602*/
603MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
604 ExceptionInfo *exception)
605{
606 const char
607 *path,
608 *domain;
609
610 const PolicyInfo
611 **policy_info;
612
613 register long
614 i;
615
616 unsigned long
617 number_policies;
618
619 /*
620 List name and attributes of each policy in the list.
621 */
622 if (file == (const FILE *) NULL)
623 file=stdout;
624 policy_info=GetPolicyInfoList("*",&number_policies,exception);
625 if (policy_info == (const PolicyInfo **) NULL)
626 return(MagickFalse);
627 path=(const char *) NULL;
628 for (i=0; i < (long) number_policies; i++)
629 {
630 if (policy_info[i]->stealth != MagickFalse)
631 continue;
632 if (((path == (const char *) NULL) ||
633 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
634 (policy_info[i]->path != (char *) NULL))
635 (void) fprintf(file,"\nPath: %s\n",policy_info[i]->path);
636 path=policy_info[i]->path;
637 domain=MagickOptionToMnemonic(MagickPolicyDomainOptions,
638 policy_info[i]->domain);
639 (void) fprintf(file," Policy: %s\n",domain);
640 if (policy_info[i]->domain == ResourcePolicyDomain)
641 {
642 if (policy_info[i]->name != (char *) NULL)
643 (void) fprintf(file," name: %s\n",policy_info[i]->name);
644 if (policy_info[i]->value != (char *) NULL)
645 (void) fprintf(file," value: %s\n",policy_info[i]->value);
646 }
647 else
648 {
649 (void) fprintf(file," rights: ");
650 if (policy_info[i]->rights == NoPolicyRights)
651 (void) fprintf(file,"None ");
652 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
653 (void) fprintf(file,"Read ");
654 if ((policy_info[i]->rights & WritePolicyRights) != 0)
655 (void) fprintf(file,"Write ");
656 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
657 (void) fprintf(file,"Execute ");
658 (void) fprintf(file,"\n");
659 if (policy_info[i]->pattern != (char *) NULL)
660 (void) fprintf(file," pattern: %s\n",policy_info[i]->pattern);
661 }
662 }
663 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
664 policy_info);
665 (void) fflush(file);
666 return(MagickTrue);
667}
668
669/*
670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671% %
672% %
673% %
674+ L o a d P o l i c y L i s t %
675% %
676% %
677% %
678%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679%
680% LoadPolicyList() loads the policy configuration file which provides a mapping
681% between policy attributes and a policy domain.
682%
683% The format of the LoadPolicyList method is:
684%
685% MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
686% const unsigned long depth,ExceptionInfo *exception)
687%
688% A description of each parameter follows:
689%
690% o xml: The policy list in XML format.
691%
692% o filename: The policy list filename.
693%
694% o depth: depth of <include /> statements.
695%
696% o exception: return any errors or warnings in this structure.
697%
698*/
699static MagickBooleanType LoadPolicyList(const char *xml,const char *filename,
700 const unsigned long depth,ExceptionInfo *exception)
701{
702 char
703 keyword[MaxTextExtent],
704 *token;
705
706 PolicyInfo
707 *policy_info;
708
709 const char
710 *q;
711
712 MagickBooleanType
713 status;
714
715 /*
716 Load the policy map file.
717 */
718 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
719 "Loading policy file \"%s\" ...",filename);
720 if (xml == (char *) NULL)
721 return(MagickFalse);
722 if (policy_list == (LinkedListInfo *) NULL)
723 {
724 policy_list=NewLinkedList(0);
725 if (policy_list == (LinkedListInfo *) NULL)
726 {
727 ThrowFileException(exception,ResourceLimitError,
728 "MemoryAllocationFailed",filename);
729 return(MagickFalse);
730 }
731 }
732 status=MagickTrue;
733 policy_info=(PolicyInfo *) NULL;
734 token=AcquireString(xml);
735 for (q=(const char *) xml; *q != '\0'; )
736 {
737 /*
738 Interpret XML.
739 */
740 GetMagickToken(q,&q,token);
741 if (*token == '\0')
742 break;
743 (void) CopyMagickString(keyword,token,MaxTextExtent);
744 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
745 {
746 /*
747 Docdomain element.
748 */
749 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
750 GetMagickToken(q,&q,token);
751 continue;
752 }
753 if (LocaleNCompare(keyword,"<!--",4) == 0)
754 {
755 /*
756 Comment element.
757 */
758 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
759 GetMagickToken(q,&q,token);
760 continue;
761 }
762 if (LocaleCompare(keyword,"<include") == 0)
763 {
764 /*
765 Include element.
766 */
767 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
768 {
769 (void) CopyMagickString(keyword,token,MaxTextExtent);
770 GetMagickToken(q,&q,token);
771 if (*token != '=')
772 continue;
773 GetMagickToken(q,&q,token);
774 if (LocaleCompare(keyword,"file") == 0)
775 {
776 if (depth > 200)
777 (void) ThrowMagickException(exception,GetMagickModule(),
778 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
779 else
780 {
781 char
782 path[MaxTextExtent],
783 *xml;
784
785 GetPathComponent(filename,HeadPath,path);
786 if (*path != '\0')
787 (void) ConcatenateMagickString(path,DirectorySeparator,
788 MaxTextExtent);
789 if (*token == *DirectorySeparator)
790 (void) CopyMagickString(path,token,MaxTextExtent);
791 else
792 (void) ConcatenateMagickString(path,token,MaxTextExtent);
793 xml=FileToString(path,~0,exception);
794 if (xml != (char *) NULL)
795 {
796 status=LoadPolicyList(xml,path,depth+1,exception);
797 xml=(char *) RelinquishMagickMemory(xml);
798 }
799 }
800 }
801 }
802 continue;
803 }
804 if (LocaleCompare(keyword,"<policy") == 0)
805 {
806 /*
807 Policy element.
808 */
809 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
810 if (policy_info == (PolicyInfo *) NULL)
811 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
812 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
813 policy_info->path=ConstantString(filename);
814 policy_info->signature=MagickSignature;
815 continue;
816 }
817 if (policy_info == (PolicyInfo *) NULL)
818 continue;
819 if (LocaleCompare(keyword,"/>") == 0)
820 {
821 status=AppendValueToLinkedList(policy_list,policy_info);
822 if (status == MagickFalse)
823 (void) ThrowMagickException(exception,GetMagickModule(),
824 ResourceLimitError,"MemoryAllocationFailed","`%s'",
825 policy_info->name);
826 policy_info=(PolicyInfo *) NULL;
827 }
828 GetMagickToken(q,(const char **) NULL,token);
829 if (*token != '=')
830 continue;
831 GetMagickToken(q,&q,token);
832 GetMagickToken(q,&q,token);
833 switch (*keyword)
834 {
835 case 'D':
836 case 'd':
837 {
838 if (LocaleCompare((char *) keyword,"domain") == 0)
839 {
840 policy_info->domain=(PolicyDomain) ParseMagickOption(
841 MagickPolicyDomainOptions,MagickTrue,token);
842 break;
843 }
844 break;
845 }
846 case 'N':
847 case 'n':
848 {
849 if (LocaleCompare((char *) keyword,"name") == 0)
850 {
851 policy_info->name=ConstantString(token);
852 break;
853 }
854 break;
855 }
856 case 'P':
857 case 'p':
858 {
859 if (LocaleCompare((char *) keyword,"pattern") == 0)
860 {
861 policy_info->pattern=ConstantString(token);
862 break;
863 }
864 break;
865 }
866 case 'R':
867 case 'r':
868 {
869 if (LocaleCompare((char *) keyword,"rights") == 0)
870 {
871 policy_info->rights=(PolicyRights) ParseMagickOption(
872 MagickPolicyRightsOptions,MagickTrue,token);
873 break;
874 }
875 break;
876 }
877 case 'S':
878 case 's':
879 {
880 if (LocaleCompare((char *) keyword,"stealth") == 0)
881 {
882 policy_info->stealth=IsMagickTrue(token);
883 break;
884 }
885 break;
886 }
887 case 'V':
888 case 'v':
889 {
890 if (LocaleCompare((char *) keyword,"value") == 0)
891 {
892 policy_info->value=ConstantString(token);
893 break;
894 }
895 break;
896 }
897 default:
898 break;
899 }
900 }
901 token=(char *) RelinquishMagickMemory(token);
902 return(status);
903}
904
905/*
906%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907% %
908% %
909% %
910% L o a d P o l i c y L i s t s %
911% %
912% %
913% %
914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
915%
916% LoadPolicyList() loads one or more policy configuration file which provides a
917% mapping between policy attributes and a policy name.
918%
919% The format of the LoadPolicyLists method is:
920%
921% MagickBooleanType LoadPolicyLists(const char *filename,
922% ExceptionInfo *exception)
923%
924% A description of each parameter follows:
925%
926% o filename: the font file name.
927%
928% o exception: return any errors or warnings in this structure.
929%
930*/
931static MagickBooleanType LoadPolicyLists(const char *filename,
932 ExceptionInfo *exception)
933{
934#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
935 return(LoadPolicyList(PolicyMap,"built-in",0,exception));
936#else
937 const StringInfo
938 *option;
939
940 LinkedListInfo
941 *options;
942
943 MagickStatusType
944 status;
945
946 status=MagickFalse;
947 options=GetConfigureOptions(filename,exception);
948 option=(const StringInfo *) GetNextValueInLinkedList(options);
949 while (option != (const StringInfo *) NULL)
950 {
951 status|=LoadPolicyList((const char *) GetStringInfoDatum(option),
952 GetStringInfoPath(option),0,exception);
953 option=(const StringInfo *) GetNextValueInLinkedList(options);
954 }
955 options=DestroyConfigureOptions(options);
956 if ((policy_list == (LinkedListInfo *) NULL) ||
957 (IsLinkedListEmpty(policy_list) != MagickFalse))
958 status|=LoadPolicyList(PolicyMap,"built-in",0,exception);
959 return(status != 0 ? MagickTrue : MagickFalse);
960#endif
961}