2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % PPPP OOO L IIIII CCCC Y Y %
9 % P OOO LLLLL IIIII CCCC Y %
12 % MagickCore Policy Methods %
19 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
25 % http://www.imagemagick.org/script/license.php %
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. %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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).
43 #include "MagickCore/studio.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/configure-private.h"
47 #include "MagickCore/exception.h"
48 #include "MagickCore/exception-private.h"
49 #include "MagickCore/memory_.h"
50 #include "MagickCore/monitor.h"
51 #include "MagickCore/monitor-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/policy.h"
54 #include "MagickCore/policy-private.h"
55 #include "MagickCore/semaphore.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/token.h"
58 #include "MagickCore/utility.h"
59 #include "MagickCore/utility-private.h"
60 #include "MagickCore/xml-tree.h"
61 #include "MagickCore/xml-tree-private.h"
66 #define PolicyFilename "policy.xml"
99 typedef struct _PolicyMapInfo
116 static const PolicyMapInfo
119 { UndefinedPolicyDomain, UndefinedPolicyRights, (const char *) NULL,
120 (const char *) NULL, (const char *) NULL }
123 static LinkedListInfo
124 *policy_cache = (LinkedListInfo *) NULL;
127 *policy_semaphore = (SemaphoreInfo *) NULL;
130 Forward declarations.
132 static MagickBooleanType
133 IsPolicyCacheInstantiated(ExceptionInfo *),
134 LoadPolicyCache(LinkedListInfo *,const char *,const char *,const size_t,
138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 % A c q u i r e P o l i c y C a c h e %
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 % AcquirePolicyCache() caches one or more policy configurations which provides
149 % a mapping between policy attributes and a policy name.
151 % The format of the AcquirePolicyCache method is:
153 % LinkedListInfo *AcquirePolicyCache(const char *filename,
154 % ExceptionInfo *exception)
156 % A description of each parameter follows:
158 % o filename: the font file name.
160 % o exception: return any errors or warnings in this structure.
163 static LinkedListInfo *AcquirePolicyCache(const char *filename,
164 ExceptionInfo *exception)
180 Load external policy map.
182 policy_cache=NewLinkedList(0);
183 if (policy_cache == (LinkedListInfo *) NULL)
184 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
186 options=GetConfigureOptions(filename,exception);
187 option=(const StringInfo *) GetNextValueInLinkedList(options);
188 while (option != (const StringInfo *) NULL)
190 status&=LoadPolicyCache(policy_cache,(const char *)
191 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
192 option=(const StringInfo *) GetNextValueInLinkedList(options);
194 options=DestroyConfigureOptions(options);
196 Load built-in policy map.
198 for (i=0; i < (ssize_t) (sizeof(PolicyMap)/sizeof(*PolicyMap)); i++)
203 register const PolicyMapInfo
207 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
208 if (policy_info == (PolicyInfo *) NULL)
210 (void) ThrowMagickException(exception,GetMagickModule(),
211 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
214 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
215 policy_info->path=(char *) "[built-in]";
216 policy_info->domain=p->domain;
217 policy_info->rights=p->rights;
218 policy_info->name=(char *) p->name;
219 policy_info->pattern=(char *) p->pattern;
220 policy_info->value=(char *) p->value;
221 policy_info->exempt=MagickTrue;
222 policy_info->signature=MagickSignature;
223 status&=AppendValueToLinkedList(policy_cache,policy_info);
224 if (status == MagickFalse)
225 (void) ThrowMagickException(exception,GetMagickModule(),
226 ResourceLimitError,"MemoryAllocationFailed","`%s'",policy_info->name);
228 return(policy_cache);
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236 + G e t P o l i c y I n f o %
240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 % GetPolicyInfo() searches the policy list for the specified name and if found
243 % returns attributes for that policy.
245 % The format of the GetPolicyInfo method is:
247 % PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
249 % A description of each parameter follows:
251 % o name: the policy name.
253 % o exception: return any errors or warnings in this structure.
256 static PolicyInfo *GetPolicyInfo(const char *name,ExceptionInfo *exception)
259 policyname[MaxTextExtent];
267 assert(exception != (ExceptionInfo *) NULL);
268 if (IsPolicyCacheInstantiated(exception) == MagickFalse)
269 return((PolicyInfo *) NULL);
271 Strip names of whitespace.
274 if (name != (const char *) NULL)
275 (void) CopyMagickString(policyname,name,MaxTextExtent);
276 for (q=policyname; *q != '\0'; q++)
278 if (isspace((int) ((unsigned char) *q)) == 0)
280 (void) CopyMagickString(q,q+1,MaxTextExtent);
284 Search for policy tag.
286 LockSemaphoreInfo(policy_semaphore);
287 ResetLinkedListIterator(policy_cache);
288 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
289 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
291 UnlockSemaphoreInfo(policy_semaphore);
294 while (p != (PolicyInfo *) NULL)
296 if (LocaleCompare(policyname,p->name) == 0)
298 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
300 if (p != (PolicyInfo *) NULL)
301 (void) InsertValueInLinkedList(policy_cache,0,
302 RemoveElementByValueFromLinkedList(policy_cache,p));
303 UnlockSemaphoreInfo(policy_semaphore);
308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312 % G e t P o l i c y I n f o L i s t %
316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 % GetPolicyInfoList() returns any policies that match the specified pattern.
320 % The format of the GetPolicyInfoList function is:
322 % const PolicyInfo **GetPolicyInfoList(const char *pattern,
323 % size_t *number_policies,ExceptionInfo *exception)
325 % A description of each parameter follows:
327 % o pattern: Specifies a pointer to a text string containing a pattern.
329 % o number_policies: returns the number of policies in the list.
331 % o exception: return any errors or warnings in this structure.
334 MagickExport const PolicyInfo **GetPolicyInfoList(const char *pattern,
335 size_t *number_policies,ExceptionInfo *exception)
340 register const PolicyInfo
347 Allocate policy list.
349 assert(pattern != (char *) NULL);
350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
351 assert(number_policies != (size_t *) NULL);
353 p=GetPolicyInfo("*",exception);
354 if (p == (const PolicyInfo *) NULL)
355 return((const PolicyInfo **) NULL);
356 policies=(const PolicyInfo **) AcquireQuantumMemory((size_t)
357 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
358 if (policies == (const PolicyInfo **) NULL)
359 return((const PolicyInfo **) NULL);
361 Generate policy list.
363 LockSemaphoreInfo(policy_semaphore);
364 ResetLinkedListIterator(policy_cache);
365 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
366 for (i=0; p != (const PolicyInfo *) NULL; )
368 if ((p->stealth == MagickFalse) &&
369 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
371 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
373 UnlockSemaphoreInfo(policy_semaphore);
374 policies[i]=(PolicyInfo *) NULL;
375 *number_policies=(size_t) i;
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384 % G e t P o l i c y L i s t %
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 % GetPolicyList() returns any policies that match the specified pattern.
392 % The format of the GetPolicyList function is:
394 % char **GetPolicyList(const char *pattern,size_t *number_policies,
395 % ExceptionInfo *exception)
397 % A description of each parameter follows:
399 % o pattern: a pointer to a text string containing a pattern.
401 % o number_policies: returns the number of policies in the list.
403 % o exception: return any errors or warnings in this structure.
406 MagickExport char **GetPolicyList(const char *pattern,
407 size_t *number_policies,ExceptionInfo *exception)
412 register const PolicyInfo
419 Allocate policy list.
421 assert(pattern != (char *) NULL);
422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
423 assert(number_policies != (size_t *) NULL);
425 p=GetPolicyInfo("*",exception);
426 if (p == (const PolicyInfo *) NULL)
427 return((char **) NULL);
428 policies=(char **) AcquireQuantumMemory((size_t)
429 GetNumberOfElementsInLinkedList(policy_cache)+1UL,sizeof(*policies));
430 if (policies == (char **) NULL)
431 return((char **) NULL);
433 Generate policy list.
435 LockSemaphoreInfo(policy_semaphore);
436 ResetLinkedListIterator(policy_cache);
437 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
438 for (i=0; p != (const PolicyInfo *) NULL; )
440 if ((p->stealth == MagickFalse) &&
441 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
442 policies[i++]=ConstantString(p->name);
443 p=(const PolicyInfo *) GetNextValueInLinkedList(policy_cache);
445 UnlockSemaphoreInfo(policy_semaphore);
446 policies[i]=(char *) NULL;
447 *number_policies=(size_t) i;
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 % G e t P o l i c y V a l u e %
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 % GetPolicyValue() returns the value associated with the named policy.
464 % The format of the GetPolicyValue method is:
466 % char *GetPolicyValue(const char *name)
468 % A description of each parameter follows:
470 % o policy_info: The policy info.
473 MagickExport char *GetPolicyValue(const char *name)
484 assert(name != (const char *) NULL);
485 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",name);
486 exception=AcquireExceptionInfo();
487 policy_info=GetPolicyInfo(name,exception);
488 exception=DestroyExceptionInfo(exception);
489 if (policy_info == (PolicyInfo *) NULL)
490 return((char *) NULL);
491 value=policy_info->value;
492 if ((value == (const char *) NULL) || (*value == '\0'))
493 return((char *) NULL);
494 return(ConstantString(value));
498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
502 + I s P o l i c y C a c h e I n s t a n t i a t e d %
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 % IsPolicyCacheInstantiated() determines if the policy list is instantiated.
509 % If not, it instantiates the list and returns it.
511 % The format of the IsPolicyInstantiated method is:
513 % MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
515 % A description of each parameter follows.
517 % o exception: return any errors or warnings in this structure.
520 static MagickBooleanType IsPolicyCacheInstantiated(ExceptionInfo *exception)
522 if (policy_cache == (LinkedListInfo *) NULL)
524 if (policy_semaphore == (SemaphoreInfo *) NULL)
525 ActivateSemaphoreInfo(&policy_semaphore);
526 LockSemaphoreInfo(policy_semaphore);
527 if (policy_cache == (LinkedListInfo *) NULL)
528 policy_cache=AcquirePolicyCache(PolicyFilename,exception);
529 UnlockSemaphoreInfo(policy_semaphore);
531 return(policy_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
539 % I s R i g h t s A u t h o r i z e d %
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
545 % IsRightsAuthorized() returns MagickTrue if the policy authorizes the
546 % requested rights for the specified domain.
548 % The format of the IsRightsAuthorized method is:
550 % MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
551 % const PolicyRights rights,const char *pattern)
553 % A description of each parameter follows:
555 % o domain: the policy domain.
557 % o rights: the policy rights.
559 % o pattern: the coder, delegate, filter, or path pattern.
562 MagickExport MagickBooleanType IsRightsAuthorized(const PolicyDomain domain,
563 const PolicyRights rights,const char *pattern)
577 (void) LogMagickEvent(PolicyEvent,GetMagickModule(),
578 "Domain: %s; rights=%s; pattern=\"%s\" ...",
579 CommandOptionToMnemonic(MagickPolicyDomainOptions,domain),
580 CommandOptionToMnemonic(MagickPolicyRightsOptions,rights),pattern);
581 exception=AcquireExceptionInfo();
582 policy_info=GetPolicyInfo("*",exception);
583 exception=DestroyExceptionInfo(exception);
584 if (policy_info == (PolicyInfo *) NULL)
586 authorized=MagickTrue;
587 LockSemaphoreInfo(policy_semaphore);
588 ResetLinkedListIterator(policy_cache);
589 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
590 while ((p != (PolicyInfo *) NULL) && (authorized != MagickFalse))
592 if ((p->domain == domain) &&
593 (GlobExpression(pattern,p->pattern,MagickFalse) != MagickFalse))
595 if (((rights & ReadPolicyRights) != 0) &&
596 ((p->rights & ReadPolicyRights) == 0))
597 authorized=MagickFalse;
598 if (((rights & WritePolicyRights) != 0) &&
599 ((p->rights & WritePolicyRights) == 0))
600 authorized=MagickFalse;
601 if (((rights & ExecutePolicyRights) != 0) &&
602 ((p->rights & ExecutePolicyRights) == 0))
603 authorized=MagickFalse;
605 p=(PolicyInfo *) GetNextValueInLinkedList(policy_cache);
607 UnlockSemaphoreInfo(policy_semaphore);
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 % L i s t P o l i c y I n f o %
620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622 % ListPolicyInfo() lists policies to the specified file.
624 % The format of the ListPolicyInfo method is:
626 % MagickBooleanType ListPolicyInfo(FILE *file,ExceptionInfo *exception)
628 % A description of each parameter follows.
630 % o file: List policy names to this file handle.
632 % o exception: return any errors or warnings in this structure.
635 MagickExport MagickBooleanType ListPolicyInfo(FILE *file,
636 ExceptionInfo *exception)
652 List name and attributes of each policy in the list.
654 if (file == (const FILE *) NULL)
656 policy_info=GetPolicyInfoList("*",&number_policies,exception);
657 if (policy_info == (const PolicyInfo **) NULL)
659 path=(const char *) NULL;
660 for (i=0; i < (ssize_t) number_policies; i++)
662 if (policy_info[i]->stealth != MagickFalse)
664 if (((path == (const char *) NULL) ||
665 (LocaleCompare(path,policy_info[i]->path) != 0)) &&
666 (policy_info[i]->path != (char *) NULL))
667 (void) FormatLocaleFile(file,"\nPath: %s\n",policy_info[i]->path);
668 path=policy_info[i]->path;
669 domain=CommandOptionToMnemonic(MagickPolicyDomainOptions,
670 policy_info[i]->domain);
671 (void) FormatLocaleFile(file," Policy: %s\n",domain);
672 if ((policy_info[i]->domain == ResourcePolicyDomain) ||
673 (policy_info[i]->domain == SystemPolicyDomain))
675 if (policy_info[i]->name != (char *) NULL)
676 (void) FormatLocaleFile(file," name: %s\n",policy_info[i]->name);
677 if (policy_info[i]->value != (char *) NULL)
678 (void) FormatLocaleFile(file," value: %s\n",policy_info[i]->value);
682 (void) FormatLocaleFile(file," rights: ");
683 if (policy_info[i]->rights == NoPolicyRights)
684 (void) FormatLocaleFile(file,"None ");
685 if ((policy_info[i]->rights & ReadPolicyRights) != 0)
686 (void) FormatLocaleFile(file,"Read ");
687 if ((policy_info[i]->rights & WritePolicyRights) != 0)
688 (void) FormatLocaleFile(file,"Write ");
689 if ((policy_info[i]->rights & ExecutePolicyRights) != 0)
690 (void) FormatLocaleFile(file,"Execute ");
691 (void) FormatLocaleFile(file,"\n");
692 if (policy_info[i]->pattern != (char *) NULL)
693 (void) FormatLocaleFile(file," pattern: %s\n",
694 policy_info[i]->pattern);
697 policy_info=(const PolicyInfo **) RelinquishMagickMemory((void *)
704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708 + L o a d P o l i c y L i s t %
712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714 % LoadPolicyCache() loads the policy configurations which provides a mapping
715 % between policy attributes and a policy domain.
717 % The format of the LoadPolicyCache method is:
719 % MagickBooleanType LoadPolicyCache(LinkedListInfo *policy_cache,
720 % const char *xml,const char *filename,const size_t depth,
721 % ExceptionInfo *exception)
723 % A description of each parameter follows:
725 % o xml: The policy list in XML format.
727 % o filename: The policy list filename.
729 % o depth: depth of <include /> statements.
731 % o exception: return any errors or warnings in this structure.
734 static MagickBooleanType LoadPolicyCache(LinkedListInfo *policy_cache,
735 const char *xml,const char *filename,const size_t depth,
736 ExceptionInfo *exception)
739 keyword[MaxTextExtent],
752 Load the policy map file.
754 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
755 "Loading policy file \"%s\" ...",filename);
756 if (xml == (char *) NULL)
759 policy_info=(PolicyInfo *) NULL;
760 token=AcquireString(xml);
761 for (q=(const char *) xml; *q != '\0'; )
766 GetMagickToken(q,&q,token);
769 (void) CopyMagickString(keyword,token,MaxTextExtent);
770 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
775 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
776 GetMagickToken(q,&q,token);
779 if (LocaleNCompare(keyword,"<!--",4) == 0)
784 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
785 GetMagickToken(q,&q,token);
788 if (LocaleCompare(keyword,"<include") == 0)
793 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
795 (void) CopyMagickString(keyword,token,MaxTextExtent);
796 GetMagickToken(q,&q,token);
799 GetMagickToken(q,&q,token);
800 if (LocaleCompare(keyword,"file") == 0)
803 (void) ThrowMagickException(exception,GetMagickModule(),
804 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
811 GetPathComponent(filename,HeadPath,path);
813 (void) ConcatenateMagickString(path,DirectorySeparator,
815 if (*token == *DirectorySeparator)
816 (void) CopyMagickString(path,token,MaxTextExtent);
818 (void) ConcatenateMagickString(path,token,MaxTextExtent);
819 xml=FileToXML(path,~0UL);
820 if (xml != (char *) NULL)
822 status&=LoadPolicyCache(policy_cache,xml,path,depth+1,
824 xml=(char *) RelinquishMagickMemory(xml);
831 if (LocaleCompare(keyword,"<policy") == 0)
836 policy_info=(PolicyInfo *) AcquireMagickMemory(sizeof(*policy_info));
837 if (policy_info == (PolicyInfo *) NULL)
838 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
839 (void) ResetMagickMemory(policy_info,0,sizeof(*policy_info));
840 policy_info->path=ConstantString(filename);
841 policy_info->exempt=MagickFalse;
842 policy_info->signature=MagickSignature;
845 if (policy_info == (PolicyInfo *) NULL)
847 if (LocaleCompare(keyword,"/>") == 0)
849 status=AppendValueToLinkedList(policy_cache,policy_info);
850 if (status == MagickFalse)
851 (void) ThrowMagickException(exception,GetMagickModule(),
852 ResourceLimitError,"MemoryAllocationFailed","`%s'",
854 policy_info=(PolicyInfo *) NULL;
857 GetMagickToken(q,(const char **) NULL,token);
860 GetMagickToken(q,&q,token);
861 GetMagickToken(q,&q,token);
867 if (LocaleCompare((char *) keyword,"domain") == 0)
869 policy_info->domain=(PolicyDomain) ParseCommandOption(
870 MagickPolicyDomainOptions,MagickTrue,token);
878 if (LocaleCompare((char *) keyword,"name") == 0)
880 policy_info->name=ConstantString(token);
888 if (LocaleCompare((char *) keyword,"pattern") == 0)
890 policy_info->pattern=ConstantString(token);
898 if (LocaleCompare((char *) keyword,"rights") == 0)
900 policy_info->rights=(PolicyRights) ParseCommandOption(
901 MagickPolicyRightsOptions,MagickTrue,token);
909 if (LocaleCompare((char *) keyword,"stealth") == 0)
911 policy_info->stealth=IsStringTrue(token);
919 if (LocaleCompare((char *) keyword,"value") == 0)
921 policy_info->value=ConstantString(token);
930 token=(char *) RelinquishMagickMemory(token);
935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939 + P o l i c y C o m p o n e n t G e n e s i s %
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 % PolicyComponentGenesis() instantiates the policy component.
947 % The format of the PolicyComponentGenesis method is:
949 % MagickBooleanType PolicyComponentGenesis(void)
952 MagickPrivate MagickBooleanType PolicyComponentGenesis(void)
954 if (policy_semaphore == (SemaphoreInfo *) NULL)
955 policy_semaphore=AcquireSemaphoreInfo();
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 + P o l i c y C o m p o n e n t T e r m i n u s %
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970 % PolicyComponentTerminus() destroys the policy component.
972 % The format of the PolicyComponentTerminus method is:
974 % PolicyComponentTerminus(void)
978 static void *DestroyPolicyElement(void *policy_info)
983 p=(PolicyInfo *) policy_info;
984 if (p->exempt == MagickFalse)
986 if (p->value != (char *) NULL)
987 p->value=DestroyString(p->value);
988 if (p->pattern != (char *) NULL)
989 p->pattern=DestroyString(p->pattern);
990 if (p->name != (char *) NULL)
991 p->name=DestroyString(p->name);
992 if (p->path != (char *) NULL)
993 p->path=DestroyString(p->path);
995 p=(PolicyInfo *) RelinquishMagickMemory(p);
996 return((void *) NULL);
999 MagickPrivate void PolicyComponentTerminus(void)
1001 if (policy_semaphore == (SemaphoreInfo *) NULL)
1002 ActivateSemaphoreInfo(&policy_semaphore);
1003 LockSemaphoreInfo(policy_semaphore);
1004 if (policy_cache != (LinkedListInfo *) NULL)
1005 policy_cache=DestroyLinkedList(policy_cache,DestroyPolicyElement);
1006 UnlockSemaphoreInfo(policy_semaphore);
1007 RelinquishSemaphoreInfo(&policy_semaphore);