2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % DDDD EEEEE L EEEEE GGGG AAA TTTTT EEEEE %
6 % D D E L E G A A T E %
7 % D D EEE L EEE G GG AAAAA T EEE %
8 % D D E L E G G A A T E %
9 % DDDD EEEEE LLLLL EEEEE GGG A A T EEEEE %
12 % MagickCore Methods to Read/Write/Invoke Delegates %
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 % The Delegates methods associate a set of commands with a particular
36 % image format. ImageMagick uses delegates for formats it does not handle
39 % Thanks to Bob Friesenhahn for the initial inspiration and design of the
48 #include "MagickCore/studio.h"
49 #include "MagickCore/property.h"
50 #include "MagickCore/blob.h"
51 #include "MagickCore/client.h"
52 #include "MagickCore/configure.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/delegate.h"
55 #include "MagickCore/delegate-private.h"
56 #include "MagickCore/exception.h"
57 #include "MagickCore/exception-private.h"
58 #include "MagickCore/hashmap.h"
59 #include "MagickCore/list.h"
60 #include "MagickCore/memory_.h"
61 #include "MagickCore/nt-base-private.h"
62 #include "MagickCore/policy.h"
63 #include "MagickCore/resource_.h"
64 #include "MagickCore/semaphore.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/token.h"
67 #include "MagickCore/utility.h"
68 #include "MagickCore/utility-private.h"
69 #include "MagickCore/xml-tree.h"
70 #include "MagickCore/xml-tree-private.h"
75 #define DelegateFilename "delegates.xml"
81 *DelegateMap = (const char *)
82 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
84 " <delegate decode=\"autotrace\" stealth=\"True\" command=\""autotrace" -output-format svg -output-file "%o" "%i"\"/>"
85 " <delegate decode=\"avi:decode\" stealth=\"True\" command=\""mplayer" "%i" -really-quiet -ao null -vo png:z=3\"/>"
86 " <delegate decode=\"browse\" stealth=\"True\" spawn=\"True\" command=\""xdg-open" http://www.imagemagick.org/; rm "%i"\"/>"
87 " <delegate decode=\"cgm\" thread-support=\"False\" command=\""ralcgm" -d ps -oC < "%i" > "%o" 2> "%u"\"/>"
88 " <delegate decode=\"dng:decode\" command=\""/usr/bin/ufraw-batch" --silent --wb=camera --black-point=auto --exposure=auto --create-id=also --out-type=ppm16 "--output=%u.pnm" "%i"\"/>"
89 " <delegate decode=\"edit\" stealth=\"True\" command=\""xterm" -title "Edit Image Comment" -e vi "%o"\"/>"
90 " <delegate decode=\"eps\" encode=\"pdf\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pdfwrite" "-sOutputFile=%o" "-f%i"\"/>"
91 " <delegate decode=\"eps\" encode=\"ps\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pswrite" "-sOutputFile=%o" "-f%i"\"/>"
92 " <delegate decode=\"fig\" command=\""fig2dev" -L ps "%i" "%o"\"/>"
93 " <delegate decode=\"gplt\" command=\""echo" "set size 1.25,0.62 set terminal postscript portrait color solid; set output "%o"; load "%i"" > "%u";"gnuplot" "%u"\"/>"
94 " <delegate decode=\"hpg\" command=\""hp2xx" -q -m eps -f `basename "%o"` "%i" mv -f `basename "%o"` "%o"\"/>"
95 " <delegate decode=\"hpgl\" command=\""hp2xx" -q -m eps -f `basename "%o"` "%i" mv -f `basename "%o"` "%o"\"/>"
96 " <delegate decode=\"htm\" command=\""html2ps" -U -o "%o" "%i"\"/>"
97 " <delegate decode=\"html\" command=\""html2ps" -U -o "%o" "%i"\"/>"
98 " <delegate decode=\"https\" command=\""wget" -q -O "%o" "https:%M"\"/>"
99 " <delegate decode=\"ilbm\" command=\""ilbmtoppm" "%i" > "%o"\"/>"
100 " <delegate decode=\"man\" command=\""groff" -man -Tps "%i" > "%o"\"/>"
101 " <delegate decode=\"mpeg:decode\" stealth=\"True\" command=\""ffmpeg" -v -1 -vframes %S -i "%i" -vcodec pam -an -f rawvideo -y "%u.pam" 2> "%Z"\"/>"
102 " <delegate decode=\"null\" encode=\"mpeg:encode\" stealth=\"True\" command=\""ffmpeg" -v -1 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 300 -i "%M%%d.jpg" "%u.%m" 2> "%Z"\"/>"
103 " <delegate decode=\"pcl:color\" stealth=\"True\" command=\""pcl6" -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=ppmraw" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "%s"\"/>"
104 " <delegate decode=\"pcl:cmyk\" stealth=\"True\" command=\""pcl6" -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=bmpsep8" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "%s"\"/>"
105 " <delegate decode=\"pcl:mono\" stealth=\"True\" command=\""pcl6" -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pbmraw" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "%s"\"/>"
106 " <delegate decode=\"pdf\" encode=\"eps\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=epswrite" "-sOutputFile=%o" "-f%i"\"/>"
107 " <delegate decode=\"pdf\" encode=\"ps\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pswrite" "-sOutputFile=%o" "-f%i"\"/>"
108 " <delegate decode=\"pnm\" encode=\"ilbm\" mode=\"encode\" command=\""ppmtoilbm" -24if "%i" > "%o"\"/>"
109 " <delegate decode=\"pnm\" encode=\"launch\" mode=\"encode\" command=\""gimp" "%i"\"/>"
110 " <delegate decode=\"pov\" command=\""povray" "+i"%i"" -D0 +o"%o" +fn%q +w%w +h%h +a -q9 -kfi"%s" -kff"%n" "convert" -concatenate "%o*.png" "%o"\"/>"
111 " <delegate decode=\"ps\" encode=\"eps\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=epswrite" "-sOutputFile=%o" "-f%i"\"/>"
112 " <delegate decode=\"ps\" encode=\"pdf\" mode=\"bi\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pdfwrite" "-sOutputFile=%o" "-f%i"\"/>"
113 " <delegate decode=\"ps\" encode=\"print\" mode=\"encode\" command=\"lpr "%i"\"/>"
114 " <delegate decode=\"ps:alpha\" stealth=\"True\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "-f%s" "-f%s"\"/>"
115 " <delegate decode=\"ps:bbox\" stealth=\"True\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=bbox" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "-f%s" "-f%s"\"/>"
116 " <delegate decode=\"ps:cmyk\" stealth=\"True\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=bmpsep8" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "-f%s" "-f%s"\"/>"
117 " <delegate decode=\"ps:color\" stealth=\"True\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pnmraw" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "-f%s" "-f%s"\"/>"
118 " <delegate decode=\"ps:mono\" stealth=\"True\" command=\""gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pnmraw" -dTextAlphaBits=%u -dGraphicsAlphaBits=%u "-r%s" %s "-sOutputFile=%s" "-f%s" "-f%s"\"/>"
119 " <delegate decode=\"rgba\" encode=\"rle\" mode=\"encode\" command=\""rawtorle" -o "%o" -v "%i"\"/>"
120 " <delegate decode=\"scan\" command=\""scanimage" -d "%i" > "%o"\"/>"
121 " <delegate encode=\"show\" spawn=\"True\" command=\""display" -immutable -delay 0 -window-group %g -title "%l of %f" "temporary:%i"\"/>"
122 " <delegate decode=\"shtml\" command=\""html2ps" -U -o "%o" "%i"\"/>"
123 " <delegate decode=\"svg\" command=\""rsvg" "%i" "%o"\"/>"
124 " <delegate decode=\"txt\" encode=\"ps\" mode=\"bi\" command=\""enscript" -o "%o" "%i"\"/>"
125 " <delegate encode=\"win\" stealth=\"True\" spawn=\"True\" command=\""display" -immutable -delay 0 -window-group %g -title "%l of %f" "temporary:%i"\"/>"
126 " <delegate decode=\"wmf\" command=\""wmf2eps" -o "%o" "%i"\"/>"
130 Global declaractions.
132 static LinkedListInfo
133 *delegate_cache = (LinkedListInfo *) NULL;
136 *delegate_semaphore = (SemaphoreInfo *) NULL;
139 Forward declaractions.
141 static MagickBooleanType
142 IsDelegateCacheInstantiated(ExceptionInfo *),
143 LoadDelegateCache(const char *,const char *,const size_t,ExceptionInfo *);
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 % A c q u i r e D e l e g a t e C a c h e %
154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156 % AcquireDelegateCache() caches one or more delegate configurations which
157 % provides a mapping between delegate attributes and a delegate name.
159 % The format of the AcquireDelegateCache method is:
161 % LinkedListInfo *AcquireDelegateCache(const char *filename,
162 % ExceptionInfo *exception)
164 % A description of each parameter follows:
166 % o filename: the font file name.
168 % o exception: return any errors or warnings in this structure.
171 static LinkedListInfo *AcquireDelegateCache(const char *filename,
172 ExceptionInfo *exception)
184 delegate_cache=NewLinkedList(0);
185 if (delegate_cache == (LinkedListInfo *) NULL)
186 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
188 options=GetConfigureOptions(filename,exception);
189 option=(const StringInfo *) GetNextValueInLinkedList(options);
190 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
191 while (option != (const StringInfo *) NULL)
193 status&=LoadDelegateCache((const char *) GetStringInfoDatum(option),
194 GetStringInfoPath(option),0,exception);
195 option=(const StringInfo *) GetNextValueInLinkedList(options);
198 options=DestroyConfigureOptions(options);
199 if (IfMagickTrue(IsLinkedListEmpty(delegate_cache)))
200 status&=LoadDelegateCache(DelegateMap,"built-in",0,exception);
201 return(delegate_cache);
205 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 + D e l e g a t e C o m p o n e n t T e r m i n u s %
213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 % DelegateComponentGenesis() instantiates the delegate component.
217 % The format of the DelegateComponentGenesis method is:
219 % MagickBooleanType DelegateComponentGenesis(void)
222 MagickPrivate MagickBooleanType DelegateComponentGenesis(void)
224 delegate_semaphore=AcquireSemaphoreInfo();
229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 % D e l e g a t e C o m p o n e n t T e r m i n u s %
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239 % DelegateComponentTerminus() destroys the delegate component.
241 % The format of the DelegateComponentTerminus method is:
243 % DelegateComponentTerminus(void)
247 static void *DestroyDelegate(void *delegate_info)
249 register DelegateInfo
252 p=(DelegateInfo *) delegate_info;
253 if (p->path != (char *) NULL)
254 p->path=DestroyString(p->path);
255 if (p->decode != (char *) NULL)
256 p->decode=DestroyString(p->decode);
257 if (p->encode != (char *) NULL)
258 p->encode=DestroyString(p->encode);
259 if (p->commands != (char *) NULL)
260 p->commands=DestroyString(p->commands);
261 if (p->semaphore != (SemaphoreInfo *) NULL)
262 p->semaphore=RelinquishSemaphoreInfo(&p->semaphore);
263 p=(DelegateInfo *) RelinquishMagickMemory(p);
264 return((void *) NULL);
267 MagickPrivate void DelegateComponentTerminus(void)
269 if (delegate_semaphore == (SemaphoreInfo *) NULL)
270 ActivateSemaphoreInfo(&delegate_semaphore);
271 LockSemaphoreInfo(delegate_semaphore);
272 if (delegate_cache != (LinkedListInfo *) NULL)
273 delegate_cache=DestroyLinkedList(delegate_cache,DestroyDelegate);
274 UnlockSemaphoreInfo(delegate_semaphore);
275 RelinquishSemaphoreInfo(&delegate_semaphore);
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283 % G e t D e l e g a t e C o m m a n d %
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 % GetDelegateCommand() replaces any embedded formatting characters with the
290 % appropriate image attribute and returns the resulting command.
292 % The format of the GetDelegateCommand method is:
294 % char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
295 % const char *decode,const char *encode,ExceptionInfo *exception)
297 % A description of each parameter follows:
299 % o command: Method GetDelegateCommand returns the command associated
300 % with specified delegate tag.
302 % o image_info: the image info.
304 % o image: the image.
306 % o decode: Specifies the decode delegate we are searching for as a
309 % o encode: Specifies the encode delegate we are searching for as a
312 % o exception: return any errors or warnings in this structure.
315 MagickExport char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
316 const char *decode,const char *encode,ExceptionInfo *exception)
328 assert(image_info != (ImageInfo *) NULL);
329 assert(image_info->signature == MagickSignature);
330 assert(image != (Image *) NULL);
331 assert(image->signature == MagickSignature);
332 if( IfMagickTrue(image->debug) )
333 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
335 delegate_info=GetDelegateInfo(decode,encode,exception);
336 if (delegate_info == (const DelegateInfo *) NULL)
338 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
339 "NoTagFound","`%s'",decode ? decode : encode);
340 return((char *) NULL);
342 commands=StringToList(delegate_info->commands);
343 if (commands == (char **) NULL)
345 (void) ThrowMagickException(exception,GetMagickModule(),
346 ResourceLimitError,"MemoryAllocationFailed","`%s'",decode ? decode :
348 return((char *) NULL);
350 command=InterpretImageProperties((ImageInfo *) image_info,image,commands[0],
352 if (command == (char *) NULL)
353 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
354 "MemoryAllocationFailed","`%s'",commands[0]);
356 Relinquish resources.
358 for (i=0; commands[i] != (char *) NULL; i++)
359 commands[i]=DestroyString(commands[i]);
360 commands=(char **) RelinquishMagickMemory(commands);
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % G e t D e l e g a t e C o m m a n d s %
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 % GetDelegateCommands() returns the commands associated with a delegate.
377 % The format of the GetDelegateCommands method is:
379 % const char *GetDelegateCommands(const DelegateInfo *delegate_info)
381 % A description of each parameter follows:
383 % o delegate_info: The delegate info.
386 MagickExport const char *GetDelegateCommands(const DelegateInfo *delegate_info)
388 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
390 assert(delegate_info != (DelegateInfo *) NULL);
391 assert(delegate_info->signature == MagickSignature);
392 return(delegate_info->commands);
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
400 % G e t D e l e g a t e I n f o %
404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 % GetDelegateInfo() returns any delegates associated with the specified tag.
408 % The format of the GetDelegateInfo method is:
410 % const DelegateInfo *GetDelegateInfo(const char *decode,
411 % const char *encode,ExceptionInfo *exception)
413 % A description of each parameter follows:
415 % o decode: Specifies the decode delegate we are searching for as a
418 % o encode: Specifies the encode delegate we are searching for as a
421 % o exception: return any errors or warnings in this structure.
424 MagickExport const DelegateInfo *GetDelegateInfo(const char *decode,
425 const char *encode,ExceptionInfo *exception)
427 register const DelegateInfo
430 assert(exception != (ExceptionInfo *) NULL);
431 if (delegate_cache == (LinkedListInfo *) NULL)
432 if( IfMagickFalse(IsDelegateCacheInstantiated(exception)) )
433 return((const DelegateInfo *) NULL);
435 Search for named delegate.
437 LockSemaphoreInfo(delegate_semaphore);
438 ResetLinkedListIterator(delegate_cache);
439 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
440 if ((LocaleCompare(decode,"*") == 0) && (LocaleCompare(encode,"*") == 0))
442 UnlockSemaphoreInfo(delegate_semaphore);
445 while (p != (const DelegateInfo *) NULL)
449 if (LocaleCompare(p->decode,decode) == 0)
451 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
456 if (LocaleCompare(p->encode,encode) == 0)
458 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
461 if (LocaleCompare(decode,p->decode) == 0)
462 if (LocaleCompare(encode,p->encode) == 0)
464 if (LocaleCompare(decode,"*") == 0)
465 if (LocaleCompare(encode,p->encode) == 0)
467 if (LocaleCompare(decode,p->decode) == 0)
468 if (LocaleCompare(encode,"*") == 0)
470 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
472 if (p != (const DelegateInfo *) NULL)
473 (void) InsertValueInLinkedList(delegate_cache,0,
474 RemoveElementByValueFromLinkedList(delegate_cache,p));
475 UnlockSemaphoreInfo(delegate_semaphore);
480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 % G e t D e l e g a t e I n f o L i s t %
488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 % GetDelegateInfoList() returns any delegates that match the specified pattern.
492 % The delegate of the GetDelegateInfoList function is:
494 % const DelegateInfo **GetDelegateInfoList(const char *pattern,
495 % size_t *number_delegates,ExceptionInfo *exception)
497 % A description of each parameter follows:
499 % o pattern: Specifies a pointer to a text string containing a pattern.
501 % o number_delegates: This integer returns the number of delegates in the
504 % o exception: return any errors or warnings in this structure.
508 #if defined(__cplusplus) || defined(c_plusplus)
512 static int DelegateInfoCompare(const void *x,const void *y)
518 p=(const DelegateInfo **) x,
519 q=(const DelegateInfo **) y;
520 if (LocaleCompare((*p)->path,(*q)->path) == 0)
522 if ((*p)->decode == (char *) NULL)
523 if (((*p)->encode != (char *) NULL) &&
524 ((*q)->encode != (char *) NULL))
525 return(strcmp((*p)->encode,(*q)->encode));
526 if (((*p)->decode != (char *) NULL) &&
527 ((*q)->decode != (char *) NULL))
528 return(strcmp((*p)->decode,(*q)->decode));
530 return(LocaleCompare((*p)->path,(*q)->path));
533 #if defined(__cplusplus) || defined(c_plusplus)
537 MagickExport const DelegateInfo **GetDelegateInfoList(const char *pattern,
538 size_t *number_delegates,ExceptionInfo *exception)
543 register const DelegateInfo
550 Allocate delegate list.
552 assert(number_delegates != (size_t *) NULL);
553 assert(pattern != (char *) NULL);
554 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
557 p=GetDelegateInfo("*","*",exception);
558 if (p == (const DelegateInfo *) NULL)
559 return((const DelegateInfo **) NULL);
560 delegates=(const DelegateInfo **) AcquireQuantumMemory((size_t)
561 GetNumberOfElementsInLinkedList(delegate_cache)+1UL,sizeof(*delegates));
562 if (delegates == (const DelegateInfo **) NULL)
563 return((const DelegateInfo **) NULL);
565 Generate delegate list.
567 LockSemaphoreInfo(delegate_semaphore);
568 ResetLinkedListIterator(delegate_cache);
569 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
570 for (i=0; p != (const DelegateInfo *) NULL; )
572 if( IfMagickFalse(p->stealth) &&
573 ( IfMagickTrue(GlobExpression(p->decode,pattern,MagickFalse)) ||
574 IfMagickTrue(GlobExpression(p->encode,pattern,MagickFalse))) )
576 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
578 UnlockSemaphoreInfo(delegate_semaphore);
579 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateInfoCompare);
580 delegates[i]=(DelegateInfo *) NULL;
581 *number_delegates=(size_t) i;
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 % G e t D e l e g a t e L i s t %
594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 % GetDelegateList() returns any image format delegates that match the
599 % The format of the GetDelegateList function is:
601 % char **GetDelegateList(const char *pattern,
602 % size_t *number_delegates,ExceptionInfo *exception)
604 % A description of each parameter follows:
606 % o pattern: Specifies a pointer to a text string containing a pattern.
608 % o number_delegates: This integer returns the number of delegates
611 % o exception: return any errors or warnings in this structure.
615 #if defined(__cplusplus) || defined(c_plusplus)
619 static int DelegateCompare(const void *x,const void *y)
627 return(LocaleCompare(*p,*q));
630 #if defined(__cplusplus) || defined(c_plusplus)
634 MagickExport char **GetDelegateList(const char *pattern,
635 size_t *number_delegates,ExceptionInfo *exception)
640 register const DelegateInfo
647 Allocate delegate list.
649 assert(pattern != (char *) NULL);
650 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
652 assert(number_delegates != (size_t *) NULL);
654 p=GetDelegateInfo("*","*",exception);
655 if (p == (const DelegateInfo *) NULL)
656 return((char **) NULL);
657 delegates=(char **) AcquireQuantumMemory((size_t)
658 GetNumberOfElementsInLinkedList(delegate_cache)+1UL,sizeof(*delegates));
659 if (delegates == (char **) NULL)
660 return((char **) NULL);
661 LockSemaphoreInfo(delegate_semaphore);
662 ResetLinkedListIterator(delegate_cache);
663 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
664 for (i=0; p != (const DelegateInfo *) NULL; )
666 if( IfMagickFalse(p->stealth) &&
667 IfMagickTrue(GlobExpression(p->decode,pattern,MagickFalse)) )
668 delegates[i++]=ConstantString(p->decode);
669 if( IfMagickFalse(p->stealth) &&
670 IfMagickTrue(GlobExpression(p->encode,pattern,MagickFalse)) )
671 delegates[i++]=ConstantString(p->encode);
672 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_cache);
674 UnlockSemaphoreInfo(delegate_semaphore);
675 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateCompare);
676 delegates[i]=(char *) NULL;
677 *number_delegates=(size_t) i;
682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686 % G e t D e l e g a t e M o d e %
690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 % GetDelegateMode() returns the mode of the delegate.
694 % The format of the GetDelegateMode method is:
696 % ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
698 % A description of each parameter follows:
700 % o delegate_info: The delegate info.
703 MagickExport ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
707 assert(delegate_info != (DelegateInfo *) NULL);
708 assert(delegate_info->signature == MagickSignature);
709 return(delegate_info->mode);
713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
717 + G e t D e l e g a t e T h r e a d S u p p o r t %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % GetDelegateThreadSupport() returns MagickTrue if the delegate supports
726 % The format of the GetDelegateThreadSupport method is:
728 % MagickBooleanType GetDelegateThreadSupport(
729 % const DelegateInfo *delegate_info)
731 % A description of each parameter follows:
733 % o delegate_info: The delegate info.
736 MagickExport MagickBooleanType GetDelegateThreadSupport(
737 const DelegateInfo *delegate_info)
739 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
741 assert(delegate_info != (DelegateInfo *) NULL);
742 assert(delegate_info->signature == MagickSignature);
743 return(delegate_info->thread_support);
747 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
751 + I s D e l e g a t e C a c h e I n s t a n t i a t e d %
755 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
757 % IsDelegateCacheInstantiated() determines if the delegate list is instantiated.
758 % If not, it instantiates the list and returns it.
760 % The format of the IsDelegateInstantiated method is:
762 % MagickBooleanType IsDelegateCacheInstantiated(ExceptionInfo *exception)
764 % A description of each parameter follows.
766 % o exception: return any errors or warnings in this structure.
769 static MagickBooleanType IsDelegateCacheInstantiated(ExceptionInfo *exception)
771 if (delegate_cache == (LinkedListInfo *) NULL)
773 if (delegate_semaphore == (SemaphoreInfo *) NULL)
774 ActivateSemaphoreInfo(&delegate_semaphore);
775 LockSemaphoreInfo(delegate_semaphore);
776 if (delegate_cache == (LinkedListInfo *) NULL)
777 delegate_cache=AcquireDelegateCache(DelegateFilename,exception);
778 UnlockSemaphoreInfo(delegate_semaphore);
780 return(IsMagickNotNULL(delegate_cache));
784 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788 % I n v o k e D e l e g a t e %
792 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794 % InvokeDelegate replaces any embedded formatting characters with the
795 % appropriate image attribute and executes the resulting command. MagickFalse
796 % is returned if the commands execute with success otherwise MagickTrue.
798 % The format of the InvokeDelegate method is:
800 % MagickBooleanType InvokeDelegate(ImageInfo *image_info,Image *image,
801 % const char *decode,const char *encode,ExceptionInfo *exception)
803 % A description of each parameter follows:
805 % o image_info: the imageInfo.
807 % o image: the image.
809 % o exception: return any errors or warnings in this structure.
813 static inline size_t MagickMin(const size_t x,const size_t y)
820 static MagickBooleanType CopyDelegateFile(const char *source,
821 const char *destination)
847 Copy source file to destination.
849 assert(source != (const char *) NULL);
850 assert(destination != (char *) NULL);
851 status=GetPathAttributes(destination,&attributes);
852 if( IfMagickTrue(status) && (attributes.st_size != 0))
854 destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE);
855 if (destination_file == -1)
857 source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
858 if (source_file == -1)
860 (void) close(destination_file);
863 quantum=(size_t) MagickMaxBufferExtent;
864 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
865 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
866 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
867 if (buffer == (unsigned char *) NULL)
869 (void) close(source_file);
870 (void) close(destination_file);
874 for (i=0; ; i+=count)
876 count=(ssize_t) read(source_file,buffer,quantum);
879 length=(size_t) count;
880 count=(ssize_t) write(destination_file,buffer,length);
881 if ((size_t) count != length)
884 (void) close(destination_file);
885 (void) close(source_file);
886 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
887 return(IsMagickTrue(i!=0));
890 MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info,
891 Image *image,const char *decode,const char *encode,ExceptionInfo *exception)
896 input_filename[MaxTextExtent],
897 output_filename[MaxTextExtent];
915 assert(image_info != (ImageInfo *) NULL);
916 assert(image_info->signature == MagickSignature);
917 assert(image != (Image *) NULL);
918 assert(image->signature == MagickSignature);
919 if( IfMagickTrue(image->debug) )
920 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
922 rights=ExecutePolicyRights;
923 if( IfMagickFalse(IsRightsAuthorized(DelegatePolicyDomain,rights,decode)) )
926 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
927 "NotAuthorized","`%s'",decode);
930 if( IfMagickFalse(IsRightsAuthorized(DelegatePolicyDomain,rights,encode)) )
933 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
934 "NotAuthorized","`%s'",encode);
937 temporary=IsMagickTrue(*image->filename == '\0');
938 if( IfMagickTrue(temporary) )
939 if( IfMagickFalse(AcquireUniqueFilename(image->filename)) )
941 ThrowFileException(exception,FileOpenError,
942 "UnableToCreateTemporaryFile",image->filename);
945 delegate_info=GetDelegateInfo(decode,encode,exception);
946 if (delegate_info == (DelegateInfo *) NULL)
948 if( IfMagickTrue(temporary) )
949 (void) RelinquishUniqueFileResource(image->filename);
950 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
951 "NoTagFound","`%s'",decode ? decode : encode);
954 if (*image_info->filename == '\0')
956 if( IfMagickFalse(AcquireUniqueFilename(image_info->filename)) )
958 if( IfMagickTrue(temporary) )
959 (void) RelinquishUniqueFileResource(image->filename);
960 ThrowFileException(exception,FileOpenError,
961 "UnableToCreateTemporaryFile",image_info->filename);
964 image_info->temporary=MagickTrue;
966 if ((delegate_info->mode != 0) && (((decode != (const char *) NULL) &&
967 (delegate_info->encode != (char *) NULL)) ||
968 ((encode != (const char *) NULL) &&
969 (delegate_info->decode != (char *) NULL))))
981 Delegate requires a particular image format.
983 if( IfMagickFalse(AcquireUniqueFilename(image_info->unique)) )
985 ThrowFileException(exception,FileOpenError,
986 "UnableToCreateTemporaryFile",image_info->unique);
989 if( IfMagickFalse(AcquireUniqueFilename(image_info->zero)) )
991 (void) RelinquishUniqueFileResource(image_info->unique);
992 ThrowFileException(exception,FileOpenError,
993 "UnableToCreateTemporaryFile",image_info->zero);
996 magick=InterpretImageProperties(image_info,image,decode != (char *) NULL ?
997 delegate_info->encode : delegate_info->decode,exception);
998 if (magick == (char *) NULL)
1000 (void) RelinquishUniqueFileResource(image_info->unique);
1001 (void) RelinquishUniqueFileResource(image_info->zero);
1002 if( IfMagickTrue(temporary) )
1003 (void) RelinquishUniqueFileResource(image->filename);
1004 (void) ThrowMagickException(exception,GetMagickModule(),
1005 DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
1006 return(MagickFalse);
1008 LocaleUpper(magick);
1009 clone_info=CloneImageInfo(image_info);
1010 (void) CopyMagickString((char *) clone_info->magick,magick,
1012 if (LocaleCompare(magick,"NULL") != 0)
1013 (void) CopyMagickString(image->magick,magick,MaxTextExtent);
1014 magick=DestroyString(magick);
1015 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:",
1016 delegate_info->decode);
1017 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(image),
1019 (void) CopyMagickString(clone_info->filename,image_info->filename,
1021 (void) CopyMagickString(image_info->filename,image->filename,
1023 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1025 (void) FormatLocaleString(p->filename,MaxTextExtent,"%s:%s",
1026 delegate_info->decode,clone_info->filename);
1027 status=WriteImage(clone_info,p,exception);
1028 if( IfMagickFalse(status) )
1030 (void) RelinquishUniqueFileResource(image_info->unique);
1031 (void) RelinquishUniqueFileResource(image_info->zero);
1032 if( IfMagickTrue(temporary) )
1033 (void) RelinquishUniqueFileResource(image->filename);
1034 clone_info=DestroyImageInfo(clone_info);
1035 (void) ThrowMagickException(exception,GetMagickModule(),
1036 DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
1037 return(MagickFalse);
1039 if( IfMagickTrue(clone_info->adjoin) )
1042 (void) RelinquishUniqueFileResource(image_info->unique);
1043 (void) RelinquishUniqueFileResource(image_info->zero);
1044 clone_info=DestroyImageInfo(clone_info);
1049 commands=StringToList(delegate_info->commands);
1050 if (commands == (char **) NULL)
1052 if( IfMagickTrue(temporary) )
1053 (void) RelinquishUniqueFileResource(image->filename);
1054 (void) ThrowMagickException(exception,GetMagickModule(),
1055 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1056 decode ? decode : encode);
1057 return(MagickFalse);
1059 command=(char *) NULL;
1061 (void) CopyMagickString(output_filename,image_info->filename,MaxTextExtent);
1062 (void) CopyMagickString(input_filename,image->filename,MaxTextExtent);
1063 for (i=0; commands[i] != (char *) NULL; i++)
1065 status=AcquireUniqueSymbolicLink(output_filename,image_info->filename);
1066 if( IfMagickFalse(AcquireUniqueFilename(image_info->unique)) )
1068 ThrowFileException(exception,FileOpenError,
1069 "UnableToCreateTemporaryFile",image_info->unique);
1072 if( IfMagickFalse(AcquireUniqueFilename(image_info->zero)) )
1074 (void) RelinquishUniqueFileResource(image_info->unique);
1075 ThrowFileException(exception,FileOpenError,
1076 "UnableToCreateTemporaryFile",image_info->zero);
1079 if (LocaleCompare(decode,"SCAN") != 0)
1081 status=AcquireUniqueSymbolicLink(input_filename,image->filename);
1082 if( IfMagickFalse(status) )
1084 ThrowFileException(exception,FileOpenError,
1085 "UnableToCreateTemporaryFile",input_filename);
1090 command=InterpretImageProperties(image_info,image,commands[i],exception);
1091 if (command != (char *) NULL)
1096 status=IsMagickTrue(SystemCommand(delegate_info->spawn,
1097 image_info->verbose,command,exception) != 0);
1098 if (IfMagickTrue(delegate_info->spawn))
1104 Wait for input file to 'disappear', or maximum 10 seconds.
1107 while ((count-- > 0) && (access_utf8(image->filename,F_OK) == 0))
1108 (void) MagickDelay(100); /* sleep 0.1 seconds */
1110 command=DestroyString(command);
1112 if (LocaleCompare(decode,"SCAN") != 0)
1114 if( IfMagickFalse(CopyDelegateFile(image->filename,input_filename)) )
1115 (void) RelinquishUniqueFileResource(input_filename);
1117 if( IfMagickFalse(CopyDelegateFile(image_info->filename,output_filename)) )
1118 (void) RelinquishUniqueFileResource(output_filename);
1119 if( IfMagickTrue(image_info->temporary) )
1120 (void) RelinquishUniqueFileResource(image_info->filename);
1121 (void) RelinquishUniqueFileResource(image_info->unique);
1122 (void) RelinquishUniqueFileResource(image_info->zero);
1123 (void) RelinquishUniqueFileResource(image_info->filename);
1124 (void) RelinquishUniqueFileResource(image->filename);
1125 if( IfMagickTrue(status) )
1127 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1128 "DelegateFailed","`%s'",commands[i]);
1131 commands[i]=DestroyString(commands[i]);
1133 (void) CopyMagickString(image_info->filename,output_filename,MaxTextExtent);
1134 (void) CopyMagickString(image->filename,input_filename,MaxTextExtent);
1136 Relinquish resources.
1138 for ( ; commands[i] != (char *) NULL; i++)
1139 commands[i]=DestroyString(commands[i]);
1140 commands=(char **) RelinquishMagickMemory(commands);
1141 if( IfMagickTrue(temporary) )
1142 (void) RelinquishUniqueFileResource(image->filename);
1143 return(IsMagickFalse(status));
1147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 % L i s t D e l e g a t e I n f o %
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 % ListDelegateInfo() lists the image formats to a file.
1159 % The format of the ListDelegateInfo method is:
1161 % MagickBooleanType ListDelegateInfo(FILE *file,ExceptionInfo *exception)
1163 % A description of each parameter follows.
1165 % o file: An pointer to a FILE.
1167 % o exception: return any errors or warnings in this structure.
1170 MagickExport MagickBooleanType ListDelegateInfo(FILE *file,
1171 ExceptionInfo *exception)
1178 delegate[MaxTextExtent];
1192 if (file == (const FILE *) NULL)
1194 delegate_info=GetDelegateInfoList("*",&number_delegates,exception);
1195 if (delegate_info == (const DelegateInfo **) NULL)
1196 return(MagickFalse);
1197 path=(const char *) NULL;
1198 for (i=0; i < (ssize_t) number_delegates; i++)
1200 if( IfMagickTrue(delegate_info[i]->stealth) )
1202 if ((path == (const char *) NULL) ||
1203 (LocaleCompare(path,delegate_info[i]->path) != 0))
1205 if (delegate_info[i]->path != (char *) NULL)
1206 (void) FormatLocaleFile(file,"\nPath: %s\n\n",delegate_info[i]->path);
1207 (void) FormatLocaleFile(file,"Delegate Command\n");
1208 (void) FormatLocaleFile(file,
1209 "-------------------------------------------------"
1210 "------------------------------\n");
1212 path=delegate_info[i]->path;
1214 if (delegate_info[i]->encode != (char *) NULL)
1215 (void) CopyMagickString(delegate,delegate_info[i]->encode,MaxTextExtent);
1216 (void) ConcatenateMagickString(delegate," ",MaxTextExtent);
1218 commands=StringToList(delegate_info[i]->commands);
1219 if (commands == (char **) NULL)
1221 (void) FormatLocaleFile(file,"%11s%c=%c%s ",delegate_info[i]->decode ?
1222 delegate_info[i]->decode : "",delegate_info[i]->mode <= 0 ? '<' : ' ',
1223 delegate_info[i]->mode >= 0 ? '>' : ' ',delegate);
1224 StripString(commands[0]);
1225 (void) FormatLocaleFile(file,"\"%s\"\n",commands[0]);
1226 for (j=1; commands[j] != (char *) NULL; j++)
1228 StripString(commands[j]);
1229 (void) FormatLocaleFile(file," \"%s\"\n",commands[j]);
1231 for (j=0; commands[j] != (char *) NULL; j++)
1232 commands[j]=DestroyString(commands[j]);
1233 commands=(char **) RelinquishMagickMemory(commands);
1235 (void) fflush(file);
1236 delegate_info=(const DelegateInfo **)
1237 RelinquishMagickMemory((void *) delegate_info);
1242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1246 + L o a d D e l e g a t e L i s t %
1250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1252 % LoadDelegateCache() loads the delegate configurations which provides a
1253 % mapping between delegate attributes and a delegate name.
1255 % The format of the LoadDelegateCache method is:
1257 % MagickBooleanType LoadDelegateCache(const char *xml,const char *filename,
1258 % const size_t depth,ExceptionInfo *exception)
1260 % A description of each parameter follows:
1262 % o xml: The delegate list in XML format.
1264 % o filename: The delegate list filename.
1266 % o depth: depth of <include /> statements.
1268 % o exception: return any errors or warnings in this structure.
1271 static MagickBooleanType LoadDelegateCache(const char *xml,const char *filename,
1272 const size_t depth,ExceptionInfo *exception)
1275 keyword[MaxTextExtent],
1288 Load the delegate map file.
1290 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1291 "Loading delegate configuration file \"%s\" ...",filename);
1292 if (xml == (const char *) NULL)
1293 return(MagickFalse);
1294 if (delegate_cache == (LinkedListInfo *) NULL)
1296 delegate_cache=NewLinkedList(0);
1297 if (delegate_cache == (LinkedListInfo *) NULL)
1299 ThrowFileException(exception,ResourceLimitError,
1300 "MemoryAllocationFailed",filename);
1301 return(MagickFalse);
1305 delegate_info=(DelegateInfo *) NULL;
1306 token=AcquireString(xml);
1307 for (q=(const char *) xml; *q != '\0'; )
1312 GetMagickToken(q,&q,token);
1315 (void) CopyMagickString(keyword,token,MaxTextExtent);
1316 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1321 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1322 GetMagickToken(q,&q,token);
1325 if (LocaleNCompare(keyword,"<!--",4) == 0)
1330 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1331 GetMagickToken(q,&q,token);
1334 if (LocaleCompare(keyword,"<include") == 0)
1339 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1341 (void) CopyMagickString(keyword,token,MaxTextExtent);
1342 GetMagickToken(q,&q,token);
1345 GetMagickToken(q,&q,token);
1346 if (LocaleCompare(keyword,"file") == 0)
1349 (void) ThrowMagickException(exception,GetMagickModule(),
1350 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1354 path[MaxTextExtent],
1357 GetPathComponent(filename,HeadPath,path);
1359 (void) ConcatenateMagickString(path,DirectorySeparator,
1361 if (*token == *DirectorySeparator)
1362 (void) CopyMagickString(path,token,MaxTextExtent);
1364 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1365 xml=FileToXML(path,~0UL);
1366 if (xml != (char *) NULL)
1368 status=LoadDelegateCache(xml,path,depth+1,exception);
1369 xml=(char *) RelinquishMagickMemory(xml);
1376 if (LocaleCompare(keyword,"<delegate") == 0)
1381 delegate_info=(DelegateInfo *) AcquireMagickMemory(
1382 sizeof(*delegate_info));
1383 if (delegate_info == (DelegateInfo *) NULL)
1384 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1385 (void) ResetMagickMemory(delegate_info,0,sizeof(*delegate_info));
1386 delegate_info->path=ConstantString(filename);
1387 delegate_info->signature=MagickSignature;
1390 if (delegate_info == (DelegateInfo *) NULL)
1392 if (LocaleCompare(keyword,"/>") == 0)
1394 status=AppendValueToLinkedList(delegate_cache,delegate_info);
1395 if( IfMagickFalse(status) )
1396 (void) ThrowMagickException(exception,GetMagickModule(),
1397 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1398 delegate_info->commands);
1399 delegate_info=(DelegateInfo *) NULL;
1402 GetMagickToken(q,(const char **) NULL,token);
1405 GetMagickToken(q,&q,token);
1406 GetMagickToken(q,&q,token);
1412 if (LocaleCompare((char *) keyword,"command") == 0)
1417 commands=AcquireString(token);
1418 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1419 if (strchr(commands,'@') != (char *) NULL)
1422 path[MaxTextExtent];
1424 NTGhostscriptEXE(path,MaxTextExtent);
1425 (void) SubstituteString((char **) &commands,"@PSDelegate@",
1427 (void) SubstituteString((char **) &commands,"\\","/");
1430 (void) SubstituteString((char **) &commands,"&","&");
1431 (void) SubstituteString((char **) &commands,""","\"");
1432 (void) SubstituteString((char **) &commands,">",">");
1433 (void) SubstituteString((char **) &commands,"<","<");
1434 delegate_info->commands=commands;
1442 if (LocaleCompare((char *) keyword,"decode") == 0)
1444 delegate_info->decode=ConstantString(token);
1445 delegate_info->mode=1;
1453 if (LocaleCompare((char *) keyword,"encode") == 0)
1455 delegate_info->encode=ConstantString(token);
1456 delegate_info->mode=(-1);
1464 if (LocaleCompare((char *) keyword,"mode") == 0)
1466 delegate_info->mode=1;
1467 if (LocaleCompare(token,"bi") == 0)
1468 delegate_info->mode=0;
1470 if (LocaleCompare(token,"encode") == 0)
1471 delegate_info->mode=(-1);
1479 if (LocaleCompare((char *) keyword,"spawn") == 0)
1481 delegate_info->spawn=IsStringTrue(token);
1484 if (LocaleCompare((char *) keyword,"stealth") == 0)
1486 delegate_info->stealth=IsStringTrue(token);
1494 if (LocaleCompare((char *) keyword,"thread-support") == 0)
1496 delegate_info->thread_support=IsStringTrue(token);
1497 if (delegate_info->thread_support != MagickFalse)
1498 delegate_info->semaphore=AcquireSemaphoreInfo();
1507 token=(char *) RelinquishMagickMemory(token);