blob: ec0fdd4947785b9fdf6f2ff359bc1a6710c6fad6 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
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 %
10% %
11% %
12% MagickCore Methods to Read/Write/Invoke Delegates %
13% %
14% Software Design %
15% John Cristy %
16% October 1998 %
17% %
18% %
cristy1454be72011-12-19 01:52:48 +000019% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000020% 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% The Delegates methods associate a set of commands with a particular
36% image format. ImageMagick uses delegates for formats it does not handle
37% directly.
38%
39% Thanks to Bob Friesenhahn for the initial inspiration and design of the
40% delegates methods.
41%
42%
43*/
44
45/*
46 Include declarations.
47*/
cristy4c08aed2011-07-01 19:47:50 +000048#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"
cristy5ff4eaf2011-09-03 01:38:02 +000055#include "MagickCore/delegate-private.h"
cristy4c08aed2011-07-01 19:47:50 +000056#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/policy.h"
62#include "MagickCore/resource_.h"
63#include "MagickCore/semaphore.h"
64#include "MagickCore/string_.h"
65#include "MagickCore/token.h"
66#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000067#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000068#include "MagickCore/xml-tree.h"
cristy3ed852e2009-09-05 21:47:34 +000069
70/*
71 Define declarations.
72*/
73#define DelegateFilename "delegates.xml"
74
75/*
76 Declare delegate map.
77*/
78static const char
79 *DelegateMap = (const char *)
80 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
81 "<delegatemap>"
82 " <delegate decode=\"autotrace\" stealth=\"True\" command=\"&quot;autotrace&quot; -output-format svg -output-file &quot;%o&quot; &quot;%i&quot;\"/>"
83 " <delegate decode=\"avi:decode\" stealth=\"True\" command=\"&quot;mplayer&quot; &quot;%i&quot; -really-quiet -ao null -vo png:z=3\"/>"
anthonyb8071362012-05-23 03:56:25 +000084 " <delegate decode=\"browse\" stealth=\"True\" spawn=\"True\" command=\"&quot;xdg-open&quot; http://www.imagemagick.org/; rm &quot;%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +000085 " <delegate decode=\"cgm\" thread-support=\"False\" command=\"&quot;ralcgm&quot; -d ps -oC &lt; &quot;%i&quot; &gt; &quot;%o&quot; 2&gt; &quot;%u&quot;\"/>"
86 " <delegate decode=\"dng:decode\" command=\"&quot;/usr/bin/ufraw-batch&quot; --silent --wb=camera --black-point=auto --exposure=auto --create-id=also --out-type=ppm16 &quot;--output=%u.pnm&quot; &quot;%i&quot;\"/>"
87 " <delegate decode=\"edit\" stealth=\"True\" command=\"&quot;xterm&quot; -title &quot;Edit Image Comment&quot; -e vi &quot;%o&quot;\"/>"
cristy0a759852011-11-24 15:07:52 +000088 " <delegate decode=\"eps\" encode=\"pdf\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
89 " <delegate decode=\"eps\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +000090 " <delegate decode=\"fig\" command=\"&quot;fig2dev&quot; -L ps &quot;%i&quot; &quot;%o&quot;\"/>"
91 " <delegate decode=\"gplt\" command=\"&quot;echo&quot; &quot;set size 1.25,0.62 set terminal postscript portrait color solid; set output &quot;%o&quot;; load &quot;%i&quot;&quot; &gt; &quot;%u&quot;;&quot;gnuplot&quot; &quot;%u&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +000092 " <delegate decode=\"hpg\" command=\"&quot;hp2xx&quot; -q -m eps -f `basename &quot;%o&quot;` &quot;%i&quot; mv -f `basename &quot;%o&quot;` &quot;%o&quot;\"/>"
93 " <delegate decode=\"hpgl\" command=\"if [ -e hp2xx -o -e /usr/bin/hp2xx ]; then hp2xx -q -m eps -f `basename &quot;%o&quot;` &quot;%i&quot; mv -f `basename &quot;%o&quot;` &quot;%o else echo &quot;You need to install hp2xx to use HPGL files with ImageMagick.&quot; exit 1 fi\"/>"
94 " <delegate decode=\"htm\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
95 " <delegate decode=\"html\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
96 " <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"
97 " <delegate decode=\"ilbm\" command=\"&quot;ilbmtoppm&quot; &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
98 " <delegate decode=\"man\" command=\"&quot;groff&quot; -man -Tps &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
anthony4e3d06f2012-05-23 03:58:38 +000099 " <delegate decode=\"mpeg:decode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; -v -1 -vframes %S -i &quot;%i&quot; -vcodec pam -an -f rawvideo -y &quot;%u.pam&quot; 2&gt; &quot;%Z&quot;\"/>"
100 " <delegate decode=\"null\" encode=\"mpeg:encode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; -v -1 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 300 -i &quot;%M%%d.jpg&quot; &quot;%u.%m&quot; 2&gt; &quot;%Z&quot;\"/>"
cristy0a759852011-11-24 15:07:52 +0000101 " <delegate decode=\"pcl:color\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=ppmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
102 " <delegate decode=\"pcl:cmyk\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bmpsep8&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
103 " <delegate decode=\"pcl:mono\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pbmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;%s&quot;\"/>"
104 " <delegate decode=\"pdf\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=epswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
105 " <delegate decode=\"pdf\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000106 " <delegate decode=\"pnm\" encode=\"ilbm\" mode=\"encode\" command=\"&quot;ppmtoilbm&quot; -24if &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
107 " <delegate decode=\"pnm\" encode=\"launch\" mode=\"encode\" command=\"&quot;gimp&quot; &quot;%i&quot;\"/>"
108 " <delegate decode=\"pov\" command=\"&quot;povray&quot; &quot;+i&quot;%i&quot;&quot; -D0 +o&quot;%o&quot; +fn%q +w%w +h%h +a -q9 -kfi&quot;%s&quot; -kff&quot;%n&quot; &quot;convert&quot; -concatenate &quot;%o*.png&quot; &quot;%o&quot;\"/>"
cristy0a759852011-11-24 15:07:52 +0000109 " <delegate decode=\"ps\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=epswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
110 " <delegate decode=\"ps\" encode=\"pdf\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000111 " <delegate decode=\"ps\" encode=\"print\" mode=\"encode\" command=\"lpr &quot;%i&quot;\"/>"
cristy0a759852011-11-24 15:07:52 +0000112 " <delegate decode=\"ps:alpha\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pngalpha&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
113 " <delegate decode=\"ps:bbox\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bbox&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
114 " <delegate decode=\"ps:cmyk\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=bmpsep8&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
115 " <delegate decode=\"ps:color\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pnmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
116 " <delegate decode=\"ps:mono\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pnmraw&quot; -dTextAlphaBits=%u -dGraphicsAlphaBits=%u &quot;-r%s&quot; %s &quot;-sOutputFile=%s&quot; &quot;-f%s&quot; &quot;-f%s&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000117 " <delegate decode=\"rgba\" encode=\"rle\" mode=\"encode\" command=\"&quot;rawtorle&quot; -o &quot;%o&quot; -v &quot;%i&quot;\"/>"
118 " <delegate decode=\"scan\" command=\"&quot;scanimage&quot; -d &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
anthonyb8071362012-05-23 03:56:25 +0000119 " <delegate encode=\"show\" spawn=\"True\" command=\"&quot;display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000120 " <delegate decode=\"shtml\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
cristy4689cf02010-02-17 21:15:45 +0000121 " <delegate decode=\"svg\" command=\"&quot;rsvg&quot; &quot;%i&quot; &quot;%o&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000122 " <delegate decode=\"txt\" encode=\"ps\" mode=\"bi\" command=\"&quot;enscript&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
anthonyb8071362012-05-23 03:56:25 +0000123 " <delegate encode=\"win\" stealth=\"True\" spawn=\"True\" command=\"&quot;display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
cristy3ed852e2009-09-05 21:47:34 +0000124 " <delegate decode=\"wmf\" command=\"&quot;wmf2eps&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
125 "</delegatemap>";
126
127/*
128 Global declaractions.
129*/
130static LinkedListInfo
131 *delegate_list = (LinkedListInfo *) NULL;
132
133static SemaphoreInfo
134 *delegate_semaphore = (SemaphoreInfo *) NULL;
135
136static volatile MagickBooleanType
137 instantiate_delegate = MagickFalse;
138
139/*
140 Forward declaractions.
141*/
142static MagickBooleanType
143 InitializeDelegateList(ExceptionInfo *),
144 LoadDelegateLists(const char *,ExceptionInfo *);
145
146/*
147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148% %
149% %
150% %
cristyf34a1452009-10-24 22:29:27 +0000151+ 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 %
cristy3ed852e2009-09-05 21:47:34 +0000152% %
153% %
154% %
155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156%
cristyf34a1452009-10-24 22:29:27 +0000157% DelegateComponentGenesis() instantiates the delegate component.
cristy3ed852e2009-09-05 21:47:34 +0000158%
cristyf34a1452009-10-24 22:29:27 +0000159% The format of the DelegateComponentGenesis method is:
cristy3ed852e2009-09-05 21:47:34 +0000160%
cristyf34a1452009-10-24 22:29:27 +0000161% MagickBooleanType DelegateComponentGenesis(void)
162%
163*/
cristy5ff4eaf2011-09-03 01:38:02 +0000164MagickPrivate MagickBooleanType DelegateComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000165{
cristy165b6092009-10-26 13:52:10 +0000166 AcquireSemaphoreInfo(&delegate_semaphore);
cristyf34a1452009-10-24 22:29:27 +0000167 return(MagickTrue);
168}
169
170/*
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172% %
173% %
174% %
175% 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 %
176% %
177% %
178% %
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180%
181% DelegateComponentTerminus() destroys the delegate component.
182%
183% The format of the DelegateComponentTerminus method is:
184%
185% DelegateComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000186%
187*/
188
189static void *DestroyDelegate(void *delegate_info)
190{
191 register DelegateInfo
192 *p;
193
194 p=(DelegateInfo *) delegate_info;
195 if (p->path != (char *) NULL)
196 p->path=DestroyString(p->path);
197 if (p->decode != (char *) NULL)
198 p->decode=DestroyString(p->decode);
199 if (p->encode != (char *) NULL)
200 p->encode=DestroyString(p->encode);
201 if (p->commands != (char *) NULL)
202 p->commands=DestroyString(p->commands);
203 p=(DelegateInfo *) RelinquishMagickMemory(p);
204 return((void *) NULL);
205}
206
cristy5ff4eaf2011-09-03 01:38:02 +0000207MagickPrivate void DelegateComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000208{
cristy18b17442009-10-25 18:36:48 +0000209 if (delegate_semaphore == (SemaphoreInfo *) NULL)
210 AcquireSemaphoreInfo(&delegate_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000211 LockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000212 if (delegate_list != (LinkedListInfo *) NULL)
213 delegate_list=DestroyLinkedList(delegate_list,DestroyDelegate);
214 instantiate_delegate=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +0000215 UnlockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000216 DestroySemaphoreInfo(&delegate_semaphore);
217}
218
219/*
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221% %
222% %
223% %
224% G e t D e l e g a t e C o m m a n d %
225% %
226% %
227% %
228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229%
230% GetDelegateCommand() replaces any embedded formatting characters with the
231% appropriate image attribute and returns the resulting command.
232%
233% The format of the GetDelegateCommand method is:
234%
235% char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
236% const char *decode,const char *encode,ExceptionInfo *exception)
237%
238% A description of each parameter follows:
239%
240% o command: Method GetDelegateCommand returns the command associated
241% with specified delegate tag.
242%
243% o image_info: the image info.
244%
245% o image: the image.
246%
247% o decode: Specifies the decode delegate we are searching for as a
248% character string.
249%
250% o encode: Specifies the encode delegate we are searching for as a
251% character string.
252%
253% o exception: return any errors or warnings in this structure.
254%
255*/
256MagickExport char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
257 const char *decode,const char *encode,ExceptionInfo *exception)
258{
259 char
260 *command,
261 **commands;
262
263 const DelegateInfo
264 *delegate_info;
265
cristybb503372010-05-27 20:51:26 +0000266 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000267 i;
268
269 assert(image_info != (ImageInfo *) NULL);
270 assert(image_info->signature == MagickSignature);
271 assert(image != (Image *) NULL);
272 assert(image->signature == MagickSignature);
anthony59c44432012-05-23 04:41:25 +0000273 if( IfMagickTrue(image->debug) )
cristy3ed852e2009-09-05 21:47:34 +0000274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
anthony59c44432012-05-23 04:41:25 +0000275
cristy3ed852e2009-09-05 21:47:34 +0000276 delegate_info=GetDelegateInfo(decode,encode,exception);
277 if (delegate_info == (const DelegateInfo *) NULL)
278 {
279 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
anthonye5b39652012-04-21 05:37:29 +0000280 "NoTagFound","'%s'",decode ? decode : encode);
cristy3ed852e2009-09-05 21:47:34 +0000281 return((char *) NULL);
282 }
283 commands=StringToList(delegate_info->commands);
284 if (commands == (char **) NULL)
285 {
286 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000287 ResourceLimitError,"MemoryAllocationFailed","'%s'",
cristy3ed852e2009-09-05 21:47:34 +0000288 decode ? decode : encode);
289 return((char *) NULL);
290 }
cristy018f07f2011-09-04 21:15:19 +0000291 command=InterpretImageProperties(image_info,image,commands[0],exception);
cristy3ed852e2009-09-05 21:47:34 +0000292 if (command == (char *) NULL)
293 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
anthonye5b39652012-04-21 05:37:29 +0000294 "MemoryAllocationFailed","'%s'",commands[0]);
cristy3ed852e2009-09-05 21:47:34 +0000295 /*
296 Relinquish resources.
297 */
298 for (i=0; commands[i] != (char *) NULL; i++)
299 commands[i]=DestroyString(commands[i]);
300 commands=(char **) RelinquishMagickMemory(commands);
301 return(command);
302}
303
304/*
305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306% %
307% %
308% %
309% G e t D e l e g a t e C o m m a n d s %
310% %
311% %
312% %
313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314%
315% GetDelegateCommands() returns the commands associated with a delegate.
316%
317% The format of the GetDelegateCommands method is:
318%
319% const char *GetDelegateCommands(const DelegateInfo *delegate_info)
320%
321% A description of each parameter follows:
322%
323% o delegate_info: The delegate info.
324%
325*/
326MagickExport const char *GetDelegateCommands(const DelegateInfo *delegate_info)
327{
328 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
anthony59c44432012-05-23 04:41:25 +0000329
cristy3ed852e2009-09-05 21:47:34 +0000330 assert(delegate_info != (DelegateInfo *) NULL);
331 assert(delegate_info->signature == MagickSignature);
332 return(delegate_info->commands);
333}
334
335/*
336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337% %
338% %
339% %
340% G e t D e l e g a t e I n f o %
341% %
342% %
343% %
344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345%
346% GetDelegateInfo() returns any delegates associated with the specified tag.
347%
348% The format of the GetDelegateInfo method is:
349%
350% const DelegateInfo *GetDelegateInfo(const char *decode,
351% const char *encode,ExceptionInfo *exception)
352%
353% A description of each parameter follows:
354%
355% o decode: Specifies the decode delegate we are searching for as a
356% character string.
357%
358% o encode: Specifies the encode delegate we are searching for as a
359% character string.
360%
361% o exception: return any errors or warnings in this structure.
362%
363*/
364MagickExport const DelegateInfo *GetDelegateInfo(const char *decode,
365 const char *encode,ExceptionInfo *exception)
366{
367 register const DelegateInfo
368 *p;
369
370 assert(exception != (ExceptionInfo *) NULL);
371 if ((delegate_list == (LinkedListInfo *) NULL) ||
anthony59c44432012-05-23 04:41:25 +0000372 (IfMagickFalse(instantiate_delegate)))
373 if( IfMagickFalse(InitializeDelegateList(exception)) )
cristy3ed852e2009-09-05 21:47:34 +0000374 return((const DelegateInfo *) NULL);
375 if ((delegate_list == (LinkedListInfo *) NULL) ||
anthony59c44432012-05-23 04:41:25 +0000376 (IfMagickTrue(IsLinkedListEmpty(delegate_list))))
cristy3ed852e2009-09-05 21:47:34 +0000377 return((const DelegateInfo *) NULL);
378 if ((LocaleCompare(decode,"*") == 0) && (LocaleCompare(encode,"*") == 0))
379 return((const DelegateInfo *) GetValueFromLinkedList(delegate_list,0));
380 /*
381 Search for named delegate.
382 */
cristyf84a1932010-01-03 18:00:18 +0000383 LockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000384 ResetLinkedListIterator(delegate_list);
385 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
386 while (p != (const DelegateInfo *) NULL)
387 {
388 if (p->mode > 0)
389 {
390 if (LocaleCompare(p->decode,decode) == 0)
391 break;
392 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
393 continue;
394 }
395 if (p->mode < 0)
396 {
397 if (LocaleCompare(p->encode,encode) == 0)
398 break;
399 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
400 continue;
401 }
402 if (LocaleCompare(decode,p->decode) == 0)
403 if (LocaleCompare(encode,p->encode) == 0)
404 break;
405 if (LocaleCompare(decode,"*") == 0)
406 if (LocaleCompare(encode,p->encode) == 0)
407 break;
408 if (LocaleCompare(decode,p->decode) == 0)
409 if (LocaleCompare(encode,"*") == 0)
410 break;
411 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
412 }
413 if (p != (const DelegateInfo *) NULL)
414 (void) InsertValueInLinkedList(delegate_list,0,
415 RemoveElementByValueFromLinkedList(delegate_list,p));
cristyf84a1932010-01-03 18:00:18 +0000416 UnlockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000417 return(p);
418}
419
420/*
421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422% %
423% %
424% %
425% G e t D e l e g a t e I n f o L i s t %
426% %
427% %
428% %
429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430%
431% GetDelegateInfoList() returns any delegates that match the specified pattern.
432%
433% The delegate of the GetDelegateInfoList function is:
434%
435% const DelegateInfo **GetDelegateInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000436% size_t *number_delegates,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000437%
438% A description of each parameter follows:
439%
440% o pattern: Specifies a pointer to a text string containing a pattern.
441%
442% o number_delegates: This integer returns the number of delegates in the
443% list.
444%
445% o exception: return any errors or warnings in this structure.
446%
447*/
448
449#if defined(__cplusplus) || defined(c_plusplus)
450extern "C" {
451#endif
452
453static int DelegateInfoCompare(const void *x,const void *y)
454{
455 const DelegateInfo
456 **p,
457 **q;
458
459 p=(const DelegateInfo **) x,
460 q=(const DelegateInfo **) y;
461 if (LocaleCompare((*p)->path,(*q)->path) == 0)
462 {
463 if ((*p)->decode == (char *) NULL)
464 if (((*p)->encode != (char *) NULL) &&
465 ((*q)->encode != (char *) NULL))
466 return(strcmp((*p)->encode,(*q)->encode));
467 if (((*p)->decode != (char *) NULL) &&
468 ((*q)->decode != (char *) NULL))
469 return(strcmp((*p)->decode,(*q)->decode));
470 }
471 return(LocaleCompare((*p)->path,(*q)->path));
472}
473
474#if defined(__cplusplus) || defined(c_plusplus)
475}
476#endif
477
478MagickExport const DelegateInfo **GetDelegateInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000479 size_t *number_delegates,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000480{
481 const DelegateInfo
482 **delegates;
483
484 register const DelegateInfo
485 *p;
486
cristybb503372010-05-27 20:51:26 +0000487 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000488 i;
489
490 /*
491 Allocate delegate list.
492 */
anthony59c44432012-05-23 04:41:25 +0000493 assert(number_delegates != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000494 assert(pattern != (char *) NULL);
495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
anthony59c44432012-05-23 04:41:25 +0000496
cristy3ed852e2009-09-05 21:47:34 +0000497 *number_delegates=0;
498 p=GetDelegateInfo("*","*",exception);
499 if (p == (const DelegateInfo *) NULL)
500 return((const DelegateInfo **) NULL);
501 delegates=(const DelegateInfo **) AcquireQuantumMemory((size_t)
502 GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
503 if (delegates == (const DelegateInfo **) NULL)
504 return((const DelegateInfo **) NULL);
505 /*
506 Generate delegate list.
507 */
cristyf84a1932010-01-03 18:00:18 +0000508 LockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000509 ResetLinkedListIterator(delegate_list);
510 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
511 for (i=0; p != (const DelegateInfo *) NULL; )
512 {
anthony59c44432012-05-23 04:41:25 +0000513 if( IfMagickFalse(p->stealth) &&
514 ( IfMagickTrue(GlobExpression(p->decode,pattern,MagickFalse)) ||
515 IfMagickTrue(GlobExpression(p->encode,pattern,MagickFalse))) )
cristy3ed852e2009-09-05 21:47:34 +0000516 delegates[i++]=p;
517 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
518 }
cristyf84a1932010-01-03 18:00:18 +0000519 UnlockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000520 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateInfoCompare);
521 delegates[i]=(DelegateInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000522 *number_delegates=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000523 return(delegates);
524}
525
526/*
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528% %
529% %
530% %
531% G e t D e l e g a t e L i s t %
532% %
533% %
534% %
535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536%
537% GetDelegateList() returns any image format delegates that match the
538% specified pattern.
539%
540% The format of the GetDelegateList function is:
541%
542% char **GetDelegateList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000543% size_t *number_delegates,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000544%
545% A description of each parameter follows:
546%
547% o pattern: Specifies a pointer to a text string containing a pattern.
548%
549% o number_delegates: This integer returns the number of delegates
550% in the list.
551%
552% o exception: return any errors or warnings in this structure.
553%
554*/
555
556#if defined(__cplusplus) || defined(c_plusplus)
557extern "C" {
558#endif
559
560static int DelegateCompare(const void *x,const void *y)
561{
562 register const char
563 **p,
564 **q;
565
566 p=(const char **) x;
567 q=(const char **) y;
568 return(LocaleCompare(*p,*q));
569}
570
571#if defined(__cplusplus) || defined(c_plusplus)
572}
573#endif
574
575MagickExport char **GetDelegateList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000576 size_t *number_delegates,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000577{
578 char
579 **delegates;
580
581 register const DelegateInfo
582 *p;
583
cristybb503372010-05-27 20:51:26 +0000584 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000585 i;
586
587 /*
588 Allocate delegate list.
589 */
590 assert(pattern != (char *) NULL);
591 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
anthony59c44432012-05-23 04:41:25 +0000592
cristybb503372010-05-27 20:51:26 +0000593 assert(number_delegates != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000594 *number_delegates=0;
595 p=GetDelegateInfo("*","*",exception);
596 if (p == (const DelegateInfo *) NULL)
597 return((char **) NULL);
598 delegates=(char **) AcquireQuantumMemory((size_t)
599 GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
600 if (delegates == (char **) NULL)
601 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000602 LockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000603 ResetLinkedListIterator(delegate_list);
604 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
605 for (i=0; p != (const DelegateInfo *) NULL; )
606 {
anthony59c44432012-05-23 04:41:25 +0000607 if( IfMagickFalse(p->stealth) &&
608 IfMagickTrue(GlobExpression(p->decode,pattern,MagickFalse)) )
cristy3ed852e2009-09-05 21:47:34 +0000609 delegates[i++]=ConstantString(p->decode);
anthony59c44432012-05-23 04:41:25 +0000610 if( IfMagickFalse(p->stealth) &&
611 IfMagickTrue(GlobExpression(p->encode,pattern,MagickFalse)) )
cristy3ed852e2009-09-05 21:47:34 +0000612 delegates[i++]=ConstantString(p->encode);
613 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
614 }
cristyf84a1932010-01-03 18:00:18 +0000615 UnlockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000616 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateCompare);
617 delegates[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000618 *number_delegates=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000619 return(delegates);
620}
621
622/*
623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624% %
625% %
626% %
627% G e t D e l e g a t e M o d e %
628% %
629% %
630% %
631%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632%
633% GetDelegateMode() returns the mode of the delegate.
634%
635% The format of the GetDelegateMode method is:
636%
cristybb503372010-05-27 20:51:26 +0000637% ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
cristy3ed852e2009-09-05 21:47:34 +0000638%
639% A description of each parameter follows:
640%
641% o delegate_info: The delegate info.
642%
643*/
cristybb503372010-05-27 20:51:26 +0000644MagickExport ssize_t GetDelegateMode(const DelegateInfo *delegate_info)
cristy3ed852e2009-09-05 21:47:34 +0000645{
646 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
anthony59c44432012-05-23 04:41:25 +0000647
cristy3ed852e2009-09-05 21:47:34 +0000648 assert(delegate_info != (DelegateInfo *) NULL);
649 assert(delegate_info->signature == MagickSignature);
650 return(delegate_info->mode);
651}
652
653/*
654%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655% %
656% %
657% %
658+ G e t D e l e g a t e T h r e a d S u p p o r t %
659% %
660% %
661% %
662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663%
664% GetDelegateThreadSupport() returns MagickTrue if the delegate supports
665% threads.
666%
667% The format of the GetDelegateThreadSupport method is:
668%
669% MagickBooleanType GetDelegateThreadSupport(
670% const DelegateInfo *delegate_info)
671%
672% A description of each parameter follows:
673%
674% o delegate_info: The delegate info.
675%
676*/
677MagickExport MagickBooleanType GetDelegateThreadSupport(
678 const DelegateInfo *delegate_info)
679{
680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
anthony59c44432012-05-23 04:41:25 +0000681
cristy3ed852e2009-09-05 21:47:34 +0000682 assert(delegate_info != (DelegateInfo *) NULL);
683 assert(delegate_info->signature == MagickSignature);
684 return(delegate_info->thread_support);
685}
686
687/*
688%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689% %
690% %
691% %
692+ I n i t i a l i z e D e l e g a t e L i s t %
693% %
694% %
695% %
696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697%
698% InitializeDelegateList() initializes the delegate list.
699%
700% The format of the InitializeDelegateList method is:
701%
702% MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
703%
704% A description of each parameter follows.
705%
706% o exception: return any errors or warnings in this structure.
707%
708*/
709static MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
710{
711 if ((delegate_list == (LinkedListInfo *) NULL) &&
anthony59c44432012-05-23 04:41:25 +0000712 IfMagickFalse(instantiate_delegate))
cristy3ed852e2009-09-05 21:47:34 +0000713 {
cristy4e1dff62009-10-25 20:36:03 +0000714 if (delegate_semaphore == (SemaphoreInfo *) NULL)
715 AcquireSemaphoreInfo(&delegate_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000716 LockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000717 if ((delegate_list == (LinkedListInfo *) NULL) &&
anthony59c44432012-05-23 04:41:25 +0000718 IfMagickFalse(instantiate_delegate))
cristy3ed852e2009-09-05 21:47:34 +0000719 {
720 (void) LoadDelegateLists(DelegateFilename,exception);
721 instantiate_delegate=MagickTrue;
722 }
cristyf84a1932010-01-03 18:00:18 +0000723 UnlockSemaphoreInfo(delegate_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000724 }
anthony59c44432012-05-23 04:41:25 +0000725 return(IsMagickNotNULL(delegate_list));
cristy3ed852e2009-09-05 21:47:34 +0000726}
727
728/*
729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
730% %
731% %
732% %
733% I n v o k e D e l e g a t e %
734% %
735% %
736% %
737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
738%
739% InvokeDelegate replaces any embedded formatting characters with the
740% appropriate image attribute and executes the resulting command. MagickFalse
741% is returned if the commands execute with success otherwise MagickTrue.
742%
743% The format of the InvokeDelegate method is:
744%
745% MagickBooleanType InvokeDelegate(ImageInfo *image_info,Image *image,
746% const char *decode,const char *encode,ExceptionInfo *exception)
747%
748% A description of each parameter follows:
749%
750% o image_info: the imageInfo.
751%
752% o image: the image.
753%
754% o exception: return any errors or warnings in this structure.
755%
756*/
757
758static inline size_t MagickMin(const size_t x,const size_t y)
759{
760 if (x < y)
761 return(x);
762 return(y);
763}
764
765static MagickBooleanType CopyDelegateFile(const char *source,
766 const char *destination)
767{
768 int
769 destination_file,
770 source_file;
771
cristy53ac66f2012-03-11 02:56:37 +0000772 MagickBooleanType
773 status;
774
cristy3ed852e2009-09-05 21:47:34 +0000775 register size_t
776 i;
777
778 size_t
779 length,
780 quantum;
781
782 ssize_t
783 count;
784
785 struct stat
786 attributes;
787
788 unsigned char
789 *buffer;
790
791 /*
cristy2dfb1df2012-02-25 14:16:09 +0000792 Copy source file to destination.
cristy3ed852e2009-09-05 21:47:34 +0000793 */
794 assert(source != (const char *) NULL);
795 assert(destination != (char *) NULL);
cristy53ac66f2012-03-11 02:56:37 +0000796 status=GetPathAttributes(destination,&attributes);
anthony59c44432012-05-23 04:41:25 +0000797 if( IfMagickTrue(status) && (attributes.st_size != 0))
cristy53ac66f2012-03-11 02:56:37 +0000798 return(MagickTrue);
cristy18c6c272011-09-23 14:40:37 +0000799 destination_file=open_utf8(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE);
cristy3ed852e2009-09-05 21:47:34 +0000800 if (destination_file == -1)
801 return(MagickFalse);
cristy18c6c272011-09-23 14:40:37 +0000802 source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
cristy3ed852e2009-09-05 21:47:34 +0000803 if (source_file == -1)
804 {
805 (void) close(destination_file);
806 return(MagickFalse);
807 }
808 quantum=(size_t) MagickMaxBufferExtent;
809 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
810 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
811 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
812 if (buffer == (unsigned char *) NULL)
813 {
814 (void) close(source_file);
815 (void) close(destination_file);
816 return(MagickFalse);
817 }
818 length=0;
819 for (i=0; ; i+=count)
820 {
821 count=(ssize_t) read(source_file,buffer,quantum);
822 if (count <= 0)
823 break;
824 length=(size_t) count;
825 count=(ssize_t) write(destination_file,buffer,length);
826 if ((size_t) count != length)
827 break;
828 }
829 (void) close(destination_file);
830 (void) close(source_file);
831 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
anthony59c44432012-05-23 04:41:25 +0000832 return(IsMagickTrue(i!=0));
cristy3ed852e2009-09-05 21:47:34 +0000833}
834
835MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info,
836 Image *image,const char *decode,const char *encode,ExceptionInfo *exception)
837{
838 char
839 *command,
840 **commands,
841 input_filename[MaxTextExtent],
842 output_filename[MaxTextExtent];
843
844 const DelegateInfo
845 *delegate_info;
846
847 MagickBooleanType
848 status,
849 temporary;
850
cristybb503372010-05-27 20:51:26 +0000851 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000852 i;
853
854 PolicyRights
855 rights;
856
857 /*
858 Get delegate.
859 */
860 assert(image_info != (ImageInfo *) NULL);
861 assert(image_info->signature == MagickSignature);
862 assert(image != (Image *) NULL);
863 assert(image->signature == MagickSignature);
anthony59c44432012-05-23 04:41:25 +0000864 if( IfMagickTrue(image->debug) )
cristy3ed852e2009-09-05 21:47:34 +0000865 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
anthony59c44432012-05-23 04:41:25 +0000866
cristy3ed852e2009-09-05 21:47:34 +0000867 rights=ExecutePolicyRights;
anthony59c44432012-05-23 04:41:25 +0000868 if( IfMagickFalse(IsRightsAuthorized(DelegatePolicyDomain,rights,decode)) )
cristy3ed852e2009-09-05 21:47:34 +0000869 {
cristya9197f62010-01-12 02:23:34 +0000870 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000871 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
anthonye5b39652012-04-21 05:37:29 +0000872 "NotAuthorized","'%s'",decode);
cristy3ed852e2009-09-05 21:47:34 +0000873 return(MagickFalse);
874 }
anthony59c44432012-05-23 04:41:25 +0000875 if( IfMagickFalse(IsRightsAuthorized(DelegatePolicyDomain,rights,encode)) )
cristy3ed852e2009-09-05 21:47:34 +0000876 {
cristya9197f62010-01-12 02:23:34 +0000877 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000878 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
anthonye5b39652012-04-21 05:37:29 +0000879 "NotAuthorized","'%s'",encode);
cristy3ed852e2009-09-05 21:47:34 +0000880 return(MagickFalse);
881 }
anthony59c44432012-05-23 04:41:25 +0000882 temporary=IsMagickTrue(*image->filename == '\0');
883 if( IfMagickTrue(temporary) )
884 if( IfMagickFalse(AcquireUniqueFilename(image->filename)) )
cristy3ed852e2009-09-05 21:47:34 +0000885 {
886 ThrowFileException(exception,FileOpenError,
887 "UnableToCreateTemporaryFile",image->filename);
888 return(MagickFalse);
889 }
890 delegate_info=GetDelegateInfo(decode,encode,exception);
891 if (delegate_info == (DelegateInfo *) NULL)
892 {
anthony59c44432012-05-23 04:41:25 +0000893 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +0000894 (void) RelinquishUniqueFileResource(image->filename);
895 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
anthonye5b39652012-04-21 05:37:29 +0000896 "NoTagFound","'%s'",decode ? decode : encode);
cristy3ed852e2009-09-05 21:47:34 +0000897 return(MagickFalse);
898 }
899 if (*image_info->filename == '\0')
900 {
anthony59c44432012-05-23 04:41:25 +0000901 if( IfMagickFalse(AcquireUniqueFilename(image_info->filename)) )
cristy3ed852e2009-09-05 21:47:34 +0000902 {
anthony59c44432012-05-23 04:41:25 +0000903 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +0000904 (void) RelinquishUniqueFileResource(image->filename);
905 ThrowFileException(exception,FileOpenError,
906 "UnableToCreateTemporaryFile",image_info->filename);
907 return(MagickFalse);
908 }
909 image_info->temporary=MagickTrue;
910 }
cristyfc7f59b2011-09-16 00:41:11 +0000911 if ((delegate_info->mode != 0) && (((decode != (const char *) NULL) &&
cristy3ed852e2009-09-05 21:47:34 +0000912 (delegate_info->encode != (char *) NULL)) ||
913 ((encode != (const char *) NULL) &&
914 (delegate_info->decode != (char *) NULL))))
915 {
916 char
917 *magick;
918
919 ImageInfo
920 *clone_info;
921
922 register Image
923 *p;
924
925 /*
926 Delegate requires a particular image format.
927 */
anthony59c44432012-05-23 04:41:25 +0000928 if( IfMagickFalse(AcquireUniqueFilename(image_info->unique)) )
cristy3ed852e2009-09-05 21:47:34 +0000929 {
930 ThrowFileException(exception,FileOpenError,
931 "UnableToCreateTemporaryFile",image_info->unique);
932 return(MagickFalse);
933 }
anthony59c44432012-05-23 04:41:25 +0000934 if( IfMagickFalse(AcquireUniqueFilename(image_info->zero)) )
cristy3ed852e2009-09-05 21:47:34 +0000935 {
anthony2ec9bd92012-05-20 05:43:24 +0000936 (void) RelinquishUniqueFileResource(image_info->unique);
cristy3ed852e2009-09-05 21:47:34 +0000937 ThrowFileException(exception,FileOpenError,
938 "UnableToCreateTemporaryFile",image_info->zero);
939 return(MagickFalse);
940 }
941 magick=InterpretImageProperties(image_info,image,decode != (char *) NULL ?
cristy018f07f2011-09-04 21:15:19 +0000942 delegate_info->encode : delegate_info->decode,exception);
cristy3ed852e2009-09-05 21:47:34 +0000943 if (magick == (char *) NULL)
944 {
945 (void) RelinquishUniqueFileResource(image_info->unique);
946 (void) RelinquishUniqueFileResource(image_info->zero);
anthony59c44432012-05-23 04:41:25 +0000947 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +0000948 (void) RelinquishUniqueFileResource(image->filename);
949 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000950 DelegateError,"DelegateFailed","'%s'",decode ? decode : encode);
cristy3ed852e2009-09-05 21:47:34 +0000951 return(MagickFalse);
952 }
953 LocaleUpper(magick);
954 clone_info=CloneImageInfo(image_info);
955 (void) CopyMagickString((char *) clone_info->magick,magick,
956 MaxTextExtent);
957 if (LocaleCompare(magick,"NULL") != 0)
958 (void) CopyMagickString(image->magick,magick,MaxTextExtent);
959 magick=DestroyString(magick);
cristyb51dff52011-05-19 16:55:47 +0000960 (void) FormatLocaleString(clone_info->filename,MaxTextExtent,"%s:",
cristy3ed852e2009-09-05 21:47:34 +0000961 delegate_info->decode);
cristyd965a422010-03-03 17:47:35 +0000962 (void) SetImageInfo(clone_info,(unsigned int) GetImageListLength(image),
963 exception);
cristy3ed852e2009-09-05 21:47:34 +0000964 (void) CopyMagickString(clone_info->filename,image_info->filename,
965 MaxTextExtent);
966 (void) CopyMagickString(image_info->filename,image->filename,
967 MaxTextExtent);
968 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
969 {
cristyb51dff52011-05-19 16:55:47 +0000970 (void) FormatLocaleString(p->filename,MaxTextExtent,"%s:%s",
cristy3ed852e2009-09-05 21:47:34 +0000971 delegate_info->decode,clone_info->filename);
cristy6f9e0d32011-08-28 16:32:09 +0000972 status=WriteImage(clone_info,p,exception);
anthony59c44432012-05-23 04:41:25 +0000973 if( IfMagickFalse(status) )
cristy3ed852e2009-09-05 21:47:34 +0000974 {
975 (void) RelinquishUniqueFileResource(image_info->unique);
976 (void) RelinquishUniqueFileResource(image_info->zero);
anthony59c44432012-05-23 04:41:25 +0000977 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +0000978 (void) RelinquishUniqueFileResource(image->filename);
979 clone_info=DestroyImageInfo(clone_info);
980 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +0000981 DelegateError,"DelegateFailed","'%s'",decode ? decode : encode);
cristy3ed852e2009-09-05 21:47:34 +0000982 return(MagickFalse);
983 }
anthony59c44432012-05-23 04:41:25 +0000984 if( IfMagickTrue(clone_info->adjoin) )
cristy3ed852e2009-09-05 21:47:34 +0000985 break;
986 }
987 (void) RelinquishUniqueFileResource(image_info->unique);
988 (void) RelinquishUniqueFileResource(image_info->zero);
989 clone_info=DestroyImageInfo(clone_info);
990 }
991 /*
992 Invoke delegate.
993 */
994 commands=StringToList(delegate_info->commands);
995 if (commands == (char **) NULL)
996 {
anthony59c44432012-05-23 04:41:25 +0000997 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +0000998 (void) RelinquishUniqueFileResource(image->filename);
999 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001000 ResourceLimitError,"MemoryAllocationFailed","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001001 decode ? decode : encode);
1002 return(MagickFalse);
1003 }
1004 command=(char *) NULL;
1005 status=MagickFalse;
1006 (void) CopyMagickString(output_filename,image_info->filename,MaxTextExtent);
1007 (void) CopyMagickString(input_filename,image->filename,MaxTextExtent);
1008 for (i=0; commands[i] != (char *) NULL; i++)
1009 {
1010 status=AcquireUniqueSymbolicLink(output_filename,image_info->filename);
anthony59c44432012-05-23 04:41:25 +00001011 if( IfMagickFalse(AcquireUniqueFilename(image_info->unique)) )
cristy3ed852e2009-09-05 21:47:34 +00001012 {
1013 ThrowFileException(exception,FileOpenError,
1014 "UnableToCreateTemporaryFile",image_info->unique);
1015 break;
1016 }
anthony59c44432012-05-23 04:41:25 +00001017 if( IfMagickFalse(AcquireUniqueFilename(image_info->zero)) )
cristy3ed852e2009-09-05 21:47:34 +00001018 {
1019 (void) RelinquishUniqueFileResource(image_info->unique);
1020 ThrowFileException(exception,FileOpenError,
1021 "UnableToCreateTemporaryFile",image_info->zero);
1022 break;
1023 }
1024 if (LocaleCompare(decode,"SCAN") != 0)
1025 {
1026 status=AcquireUniqueSymbolicLink(input_filename,image->filename);
anthony59c44432012-05-23 04:41:25 +00001027 if( IfMagickFalse(status) )
cristy3ed852e2009-09-05 21:47:34 +00001028 {
1029 ThrowFileException(exception,FileOpenError,
1030 "UnableToCreateTemporaryFile",input_filename);
1031 break;
1032 }
1033 }
1034 status=MagickFalse;
cristy018f07f2011-09-04 21:15:19 +00001035 command=InterpretImageProperties(image_info,image,commands[i],exception);
cristy3ed852e2009-09-05 21:47:34 +00001036 if (command != (char *) NULL)
1037 {
1038 /*
1039 Execute delegate.
1040 */
anthony59c44432012-05-23 04:41:25 +00001041 status=IsMagickTrue(SystemCommand(delegate_info->spawn,
cristy77f69392012-05-26 01:15:25 +00001042 image_info->verbose,command,exception) != 0);
1043 if (IfMagickTrue(delegate_info->spawn))
1044 {
1045 ssize_t
1046 count;
1047
1048 /*
1049 Wait for input file to 'disappear', or maximum 5 secs.
1050 */
1051 count=50;
cristy3fe49df2012-05-26 01:17:56 +00001052 while ((count-- > 0) && (access_utf8(image->filename,F_OK) == 0))
cristy58399382012-05-26 12:44:41 +00001053 (void) MagickDelay(100); /* sleep 0.1 seconds */
anthony2ec9bd92012-05-20 05:43:24 +00001054 }
cristy3ed852e2009-09-05 21:47:34 +00001055 command=DestroyString(command);
1056 }
1057 if (LocaleCompare(decode,"SCAN") != 0)
1058 {
anthony59c44432012-05-23 04:41:25 +00001059 if( IfMagickFalse(CopyDelegateFile(image->filename,input_filename)) )
cristy3ed852e2009-09-05 21:47:34 +00001060 (void) RelinquishUniqueFileResource(input_filename);
1061 }
anthony59c44432012-05-23 04:41:25 +00001062 if( IfMagickFalse(CopyDelegateFile(image_info->filename,output_filename)) )
cristy3ed852e2009-09-05 21:47:34 +00001063 (void) RelinquishUniqueFileResource(output_filename);
anthony59c44432012-05-23 04:41:25 +00001064 if( IfMagickTrue(image_info->temporary) )
cristy3ed852e2009-09-05 21:47:34 +00001065 (void) RelinquishUniqueFileResource(image_info->filename);
1066 (void) RelinquishUniqueFileResource(image_info->unique);
1067 (void) RelinquishUniqueFileResource(image_info->zero);
1068 (void) RelinquishUniqueFileResource(image_info->filename);
1069 (void) RelinquishUniqueFileResource(image->filename);
anthony59c44432012-05-23 04:41:25 +00001070 if( IfMagickTrue(status) )
cristy3ed852e2009-09-05 21:47:34 +00001071 {
1072 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
anthonye5b39652012-04-21 05:37:29 +00001073 "DelegateFailed","'%s'",commands[i]);
cristy3ed852e2009-09-05 21:47:34 +00001074 break;
1075 }
1076 commands[i]=DestroyString(commands[i]);
1077 }
1078 (void) CopyMagickString(image_info->filename,output_filename,MaxTextExtent);
1079 (void) CopyMagickString(image->filename,input_filename,MaxTextExtent);
1080 /*
1081 Relinquish resources.
1082 */
1083 for ( ; commands[i] != (char *) NULL; i++)
1084 commands[i]=DestroyString(commands[i]);
1085 commands=(char **) RelinquishMagickMemory(commands);
anthony59c44432012-05-23 04:41:25 +00001086 if( IfMagickTrue(temporary) )
cristy3ed852e2009-09-05 21:47:34 +00001087 (void) RelinquishUniqueFileResource(image->filename);
anthony59c44432012-05-23 04:41:25 +00001088 return(IsMagickFalse(status));
cristy3ed852e2009-09-05 21:47:34 +00001089}
1090
1091/*
1092%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093% %
1094% %
1095% %
1096% L i s t D e l e g a t e I n f o %
1097% %
1098% %
1099% %
1100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101%
1102% ListDelegateInfo() lists the image formats to a file.
1103%
1104% The format of the ListDelegateInfo method is:
1105%
1106% MagickBooleanType ListDelegateInfo(FILE *file,ExceptionInfo *exception)
1107%
1108% A description of each parameter follows.
1109%
1110% o file: An pointer to a FILE.
1111%
1112% o exception: return any errors or warnings in this structure.
1113%
1114*/
1115MagickExport MagickBooleanType ListDelegateInfo(FILE *file,
1116 ExceptionInfo *exception)
1117{
1118 const DelegateInfo
1119 **delegate_info;
1120
1121 char
1122 **commands,
1123 delegate[MaxTextExtent];
1124
1125 const char
1126 *path;
1127
cristybb503372010-05-27 20:51:26 +00001128 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001129 i;
1130
cristybb503372010-05-27 20:51:26 +00001131 size_t
cristy3ed852e2009-09-05 21:47:34 +00001132 number_delegates;
1133
cristy9d314ff2011-03-09 01:30:28 +00001134 ssize_t
1135 j;
1136
cristy3ed852e2009-09-05 21:47:34 +00001137 if (file == (const FILE *) NULL)
1138 file=stdout;
1139 delegate_info=GetDelegateInfoList("*",&number_delegates,exception);
1140 if (delegate_info == (const DelegateInfo **) NULL)
1141 return(MagickFalse);
1142 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +00001143 for (i=0; i < (ssize_t) number_delegates; i++)
cristy3ed852e2009-09-05 21:47:34 +00001144 {
anthony59c44432012-05-23 04:41:25 +00001145 if( IfMagickTrue(delegate_info[i]->stealth) )
cristy3ed852e2009-09-05 21:47:34 +00001146 continue;
1147 if ((path == (const char *) NULL) ||
1148 (LocaleCompare(path,delegate_info[i]->path) != 0))
1149 {
1150 if (delegate_info[i]->path != (char *) NULL)
cristyb51dff52011-05-19 16:55:47 +00001151 (void) FormatLocaleFile(file,"\nPath: %s\n\n",delegate_info[i]->path);
1152 (void) FormatLocaleFile(file,"Delegate Command\n");
cristy1e604812011-05-19 18:07:50 +00001153 (void) FormatLocaleFile(file,
1154 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +00001155 "------------------------------\n");
1156 }
1157 path=delegate_info[i]->path;
1158 *delegate='\0';
1159 if (delegate_info[i]->encode != (char *) NULL)
1160 (void) CopyMagickString(delegate,delegate_info[i]->encode,MaxTextExtent);
1161 (void) ConcatenateMagickString(delegate," ",MaxTextExtent);
1162 delegate[8]='\0';
1163 commands=StringToList(delegate_info[i]->commands);
1164 if (commands == (char **) NULL)
1165 continue;
cristyb51dff52011-05-19 16:55:47 +00001166 (void) FormatLocaleFile(file,"%11s%c=%c%s ",delegate_info[i]->decode ?
cristy3ed852e2009-09-05 21:47:34 +00001167 delegate_info[i]->decode : "",delegate_info[i]->mode <= 0 ? '<' : ' ',
1168 delegate_info[i]->mode >= 0 ? '>' : ' ',delegate);
1169 StripString(commands[0]);
cristyb51dff52011-05-19 16:55:47 +00001170 (void) FormatLocaleFile(file,"\"%s\"\n",commands[0]);
cristy3ed852e2009-09-05 21:47:34 +00001171 for (j=1; commands[j] != (char *) NULL; j++)
1172 {
1173 StripString(commands[j]);
cristyb51dff52011-05-19 16:55:47 +00001174 (void) FormatLocaleFile(file," \"%s\"\n",commands[j]);
cristy3ed852e2009-09-05 21:47:34 +00001175 }
1176 for (j=0; commands[j] != (char *) NULL; j++)
1177 commands[j]=DestroyString(commands[j]);
1178 commands=(char **) RelinquishMagickMemory(commands);
1179 }
1180 (void) fflush(file);
1181 delegate_info=(const DelegateInfo **)
1182 RelinquishMagickMemory((void *) delegate_info);
1183 return(MagickTrue);
1184}
1185
1186/*
1187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188% %
1189% %
1190% %
1191+ L o a d D e l e g a t e L i s t %
1192% %
1193% %
1194% %
1195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196%
1197% LoadDelegateList() loads the delegate configuration file which provides a
1198% mapping between delegate attributes and a delegate name.
1199%
1200% The format of the LoadDelegateList method is:
1201%
1202% MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +00001203% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001204%
1205% A description of each parameter follows:
1206%
1207% o xml: The delegate list in XML format.
1208%
1209% o filename: The delegate list filename.
1210%
1211% o depth: depth of <include /> statements.
1212%
1213% o exception: return any errors or warnings in this structure.
1214%
1215*/
1216static MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +00001217 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001218{
1219 char
1220 keyword[MaxTextExtent],
1221 *token;
1222
1223 const char
1224 *q;
1225
1226 DelegateInfo
1227 *delegate_info;
1228
1229 MagickBooleanType
1230 status;
1231
1232 /*
1233 Load the delegate map file.
1234 */
1235 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1236 "Loading delegate configuration file \"%s\" ...",filename);
1237 if (xml == (const char *) NULL)
1238 return(MagickFalse);
1239 if (delegate_list == (LinkedListInfo *) NULL)
1240 {
1241 delegate_list=NewLinkedList(0);
1242 if (delegate_list == (LinkedListInfo *) NULL)
1243 {
1244 ThrowFileException(exception,ResourceLimitError,
1245 "MemoryAllocationFailed",filename);
1246 return(MagickFalse);
1247 }
1248 }
1249 status=MagickTrue;
1250 delegate_info=(DelegateInfo *) NULL;
1251 token=AcquireString(xml);
1252 for (q=(const char *) xml; *q != '\0'; )
1253 {
1254 /*
1255 Interpret XML.
1256 */
1257 GetMagickToken(q,&q,token);
1258 if (*token == '\0')
1259 break;
1260 (void) CopyMagickString(keyword,token,MaxTextExtent);
1261 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1262 {
1263 /*
1264 Doctype element.
1265 */
1266 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1267 GetMagickToken(q,&q,token);
1268 continue;
1269 }
1270 if (LocaleNCompare(keyword,"<!--",4) == 0)
1271 {
1272 /*
1273 Comment element.
1274 */
1275 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1276 GetMagickToken(q,&q,token);
1277 continue;
1278 }
1279 if (LocaleCompare(keyword,"<include") == 0)
1280 {
1281 /*
1282 Include element.
1283 */
1284 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1285 {
1286 (void) CopyMagickString(keyword,token,MaxTextExtent);
1287 GetMagickToken(q,&q,token);
1288 if (*token != '=')
1289 continue;
1290 GetMagickToken(q,&q,token);
1291 if (LocaleCompare(keyword,"file") == 0)
1292 {
1293 if (depth > 200)
1294 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001295 ConfigureError,"IncludeElementNestedTooDeeply","'%s'",token);
cristy3ed852e2009-09-05 21:47:34 +00001296 else
1297 {
1298 char
1299 path[MaxTextExtent],
1300 *xml;
1301
1302 GetPathComponent(filename,HeadPath,path);
1303 if (*path != '\0')
1304 (void) ConcatenateMagickString(path,DirectorySeparator,
1305 MaxTextExtent);
1306 if (*token == *DirectorySeparator)
1307 (void) CopyMagickString(path,token,MaxTextExtent);
1308 else
1309 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1310 xml=FileToString(path,~0,exception);
1311 if (xml != (char *) NULL)
1312 {
1313 status=LoadDelegateList(xml,path,depth+1,exception);
1314 xml=(char *) RelinquishMagickMemory(xml);
1315 }
1316 }
1317 }
1318 }
1319 continue;
1320 }
1321 if (LocaleCompare(keyword,"<delegate") == 0)
1322 {
1323 /*
1324 Delegate element.
1325 */
1326 delegate_info=(DelegateInfo *) AcquireMagickMemory(
1327 sizeof(*delegate_info));
1328 if (delegate_info == (DelegateInfo *) NULL)
1329 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1330 (void) ResetMagickMemory(delegate_info,0,sizeof(*delegate_info));
1331 delegate_info->path=ConstantString(filename);
1332 delegate_info->signature=MagickSignature;
1333 continue;
1334 }
1335 if (delegate_info == (DelegateInfo *) NULL)
1336 continue;
1337 if (LocaleCompare(keyword,"/>") == 0)
1338 {
1339 status=AppendValueToLinkedList(delegate_list,delegate_info);
anthony59c44432012-05-23 04:41:25 +00001340 if( IfMagickFalse(status) )
cristy3ed852e2009-09-05 21:47:34 +00001341 (void) ThrowMagickException(exception,GetMagickModule(),
anthonye5b39652012-04-21 05:37:29 +00001342 ResourceLimitError,"MemoryAllocationFailed","'%s'",
cristy3ed852e2009-09-05 21:47:34 +00001343 delegate_info->commands);
1344 delegate_info=(DelegateInfo *) NULL;
1345 }
1346 GetMagickToken(q,(const char **) NULL,token);
1347 if (*token != '=')
1348 continue;
1349 GetMagickToken(q,&q,token);
1350 GetMagickToken(q,&q,token);
1351 switch (*keyword)
1352 {
1353 case 'C':
1354 case 'c':
1355 {
1356 if (LocaleCompare((char *) keyword,"command") == 0)
1357 {
1358 char
1359 *commands;
1360
1361 commands=AcquireString(token);
cristy0157aea2010-04-24 21:12:18 +00001362#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001363 if (strchr(commands,'@') != (char *) NULL)
1364 {
1365 char
1366 path[MaxTextExtent];
1367
1368 NTGhostscriptEXE(path,MaxTextExtent);
1369 (void) SubstituteString((char **) &commands,"@PSDelegate@",
1370 path);
1371 (void) SubstituteString((char **) &commands,"\\","/");
1372 }
1373#endif
1374 (void) SubstituteString((char **) &commands,"&amp;","&");
1375 (void) SubstituteString((char **) &commands,"&quot;","\"");
1376 (void) SubstituteString((char **) &commands,"&gt;",">");
1377 (void) SubstituteString((char **) &commands,"&lt;","<");
1378 delegate_info->commands=commands;
1379 break;
1380 }
1381 break;
1382 }
1383 case 'D':
1384 case 'd':
1385 {
1386 if (LocaleCompare((char *) keyword,"decode") == 0)
1387 {
1388 delegate_info->decode=ConstantString(token);
1389 delegate_info->mode=1;
1390 break;
1391 }
1392 break;
1393 }
1394 case 'E':
1395 case 'e':
1396 {
1397 if (LocaleCompare((char *) keyword,"encode") == 0)
1398 {
1399 delegate_info->encode=ConstantString(token);
1400 delegate_info->mode=(-1);
1401 break;
1402 }
1403 break;
1404 }
1405 case 'M':
1406 case 'm':
1407 {
1408 if (LocaleCompare((char *) keyword,"mode") == 0)
1409 {
1410 delegate_info->mode=1;
1411 if (LocaleCompare(token,"bi") == 0)
1412 delegate_info->mode=0;
1413 else
1414 if (LocaleCompare(token,"encode") == 0)
1415 delegate_info->mode=(-1);
1416 break;
1417 }
1418 break;
1419 }
1420 case 'S':
1421 case 's':
1422 {
1423 if (LocaleCompare((char *) keyword,"spawn") == 0)
1424 {
anthony6f201312012-03-30 04:08:15 +00001425 delegate_info->spawn=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001426 break;
1427 }
1428 if (LocaleCompare((char *) keyword,"stealth") == 0)
1429 {
anthony6f201312012-03-30 04:08:15 +00001430 delegate_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001431 break;
1432 }
1433 break;
1434 }
1435 case 'T':
1436 case 't':
1437 {
1438 if (LocaleCompare((char *) keyword,"thread-support") == 0)
1439 {
anthony6f201312012-03-30 04:08:15 +00001440 delegate_info->thread_support=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001441 break;
1442 }
1443 break;
1444 }
1445 default:
1446 break;
1447 }
1448 }
1449 token=(char *) RelinquishMagickMemory(token);
1450 return(status);
1451}
1452
1453/*
1454%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1455% %
1456% %
1457% %
1458% L o a d D e l e g a t e L i s t s %
1459% %
1460% %
1461% %
1462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463%
1464% LoadDelegateList() loads one or more delegate configuration file which
1465% provides a mapping between delegate attributes and a delegate name.
1466%
1467% The format of the LoadDelegateLists method is:
1468%
1469% MagickBooleanType LoadDelegateLists(const char *filename,
1470% ExceptionInfo *exception)
1471%
1472% A description of each parameter follows:
1473%
1474% o filename: the font file name.
1475%
1476% o exception: return any errors or warnings in this structure.
1477%
1478*/
1479static MagickBooleanType LoadDelegateLists(const char *filename,
1480 ExceptionInfo *exception)
1481{
cristy6e3607c2011-09-13 13:59:17 +00001482#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001483 return(LoadDelegateList(DelegateMap,"built-in",0,exception));
1484#else
1485 const StringInfo
1486 *option;
1487
1488 LinkedListInfo
1489 *options;
1490
1491 MagickStatusType
1492 status;
1493
1494 status=MagickFalse;
1495 options=GetConfigureOptions(filename,exception);
1496 option=(const StringInfo *) GetNextValueInLinkedList(options);
1497 while (option != (const StringInfo *) NULL)
1498 {
1499 status|=LoadDelegateList((const char *) GetStringInfoDatum(option),
1500 GetStringInfoPath(option),0,exception);
1501 option=(const StringInfo *) GetNextValueInLinkedList(options);
1502 }
1503 options=DestroyConfigureOptions(options);
1504 if ((delegate_list == (LinkedListInfo *) NULL) ||
anthony59c44432012-05-23 04:41:25 +00001505 (IfMagickTrue(IsLinkedListEmpty(delegate_list))))
cristy3ed852e2009-09-05 21:47:34 +00001506 status|=LoadDelegateList(DelegateMap,"built-in",0,exception);
anthony59c44432012-05-23 04:41:25 +00001507 return(IsMagickTrue(status!=0));
cristy3ed852e2009-09-05 21:47:34 +00001508#endif
1509}