blob: 822881a042c9a7505b4e695b239c677dbace6c10 [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% %
19% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
27% Unless required by applicable law or agreed to in writing, software %
28% distributed under the License is distributed on an "AS IS" BASIS, %
29% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30% See the License for the specific language governing permissions and %
31% limitations under the License. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35% 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*/
48#include "magick/studio.h"
49#include "magick/property.h"
50#include "magick/blob.h"
51#include "magick/client.h"
52#include "magick/configure.h"
53#include "magick/constitute.h"
54#include "magick/delegate.h"
55#include "magick/exception.h"
56#include "magick/exception-private.h"
57#include "magick/hashmap.h"
58#include "magick/list.h"
59#include "magick/memory_.h"
60#include "magick/policy.h"
61#include "magick/resource_.h"
62#include "magick/semaphore.h"
63#include "magick/string_.h"
64#include "magick/token.h"
65#include "magick/utility.h"
66#include "magick/xml-tree.h"
67
68/*
69 Define declarations.
70*/
71#define DelegateFilename "delegates.xml"
72
73/*
74 Declare delegate map.
75*/
76static const char
77 *DelegateMap = (const char *)
78 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
79 "<delegatemap>"
80 " <delegate decode=\"autotrace\" stealth=\"True\" command=\"&quot;autotrace&quot; -output-format svg -output-file &quot;%o&quot; &quot;%i&quot;\"/>"
81 " <delegate decode=\"avi:decode\" stealth=\"True\" command=\"&quot;mplayer&quot; &quot;%i&quot; -really-quiet -ao null -vo png:z=3\"/>"
82 " <delegate decode=\"browse\" stealth=\"True\" spawn=\"True\" command=\"&quot;xdg-open&quot; http://www.imagemagick.org/\"/>"
83 " <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;\"/>"
84 " <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;\"/>"
85 " <delegate decode=\"edit\" stealth=\"True\" command=\"&quot;xterm&quot; -title &quot;Edit Image Comment&quot; -e vi &quot;%o&quot;\"/>"
86 " <delegate decode=\"eps\" encode=\"pdf\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
87 " <delegate decode=\"eps\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
88 " <delegate decode=\"fig\" command=\"&quot;fig2dev&quot; -L ps &quot;%i&quot; &quot;%o&quot;\"/>"
89 " <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;\"/>"
90 " <delegate decode=\"hdr\" command=\"&quot;ra_pfm&quot; &quot;%i&quot; &quot;%o&quot;\"/>"
91 " <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;\"/>"
92 " <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\"/>"
93 " <delegate decode=\"htm\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
94 " <delegate decode=\"html\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
95 " <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"
96 " <delegate decode=\"ilbm\" command=\"&quot;ilbmtoppm&quot; &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
97 " <delegate decode=\"man\" command=\"&quot;groff&quot; -man -Tps &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
98 " <delegate decode=\"mpeg:decode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; --i &quot;%i&quot; -vcodec pam -an -f rawvideo -y &quot;%u0.pam&quot; 2;&gt; &quot;%Z&quot;\"/>"
99 " <delegate decode=\"null\" encode=\"mpeg:encode\" stealth=\"True\" command=\"&quot;ffmpeg&quot; &quot;%M%%d.jpg&quot; &quot;%u.%m&quot; 2;&gt; &quot;%Z&quot;\"/>"
100 " <delegate decode=\"pcl:color\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dPARANOIDSAFE -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;\"/>"
101 " <delegate decode=\"pcl:cmyk\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dPARANOIDSAFE -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;\"/>"
102 " <delegate decode=\"pcl:mono\" stealth=\"True\" command=\"&quot;pcl6&quot; -dQUIET -dSAFER -dPARANOIDSAFE -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;\"/>"
103 " <delegate decode=\"pdf\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=epswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
104 " <delegate decode=\"pdf\" encode=\"ps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pswrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
105 " <delegate decode=\"pic\" command=\"&quot;ra_pfm&quot; &quot;%i&quot; &quot;%o&quot;\"/>"
106 " <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;\"/>"
109 " <delegate decode=\"ps\" encode=\"eps\" mode=\"bi\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -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 -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pdfwrite&quot; &quot;-sOutputFile=%o&quot; &quot;-f%i&quot;\"/>"
111 " <delegate decode=\"ps\" encode=\"print\" mode=\"encode\" command=\"lpr &quot;%i&quot;\"/>"
112 " <delegate decode=\"ps:alpha\" stealth=\"True\" command=\"&quot;gs&quot; -q -dQUIET -dSAFER -dPARANOIDSAFE -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 -dPARANOIDSAFE -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 -dPARANOIDSAFE -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 &quot;-sDEVICE=pam&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 -dPARANOIDSAFE -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 -dPARANOIDSAFE -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;\"/>"
117 " <delegate decode=\"rad\" command=\"&quot;ra_pfm&quot; &quot;%i&quot; &quot;%o&quot;\"/>"
118 " <delegate decode=\"rgba\" encode=\"rle\" mode=\"encode\" command=\"&quot;rawtorle&quot; -o &quot;%o&quot; -v &quot;%i&quot;\"/>"
119 " <delegate decode=\"scan\" command=\"&quot;scanimage&quot; -d &quot;%i&quot; &gt; &quot;%o&quot;\"/>"
120 " <delegate encode=\"show\" stealth=\"True\" spawn=\"True\" command=\"&quot;/usr/local/bin/display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
121 " <delegate decode=\"shtml\" command=\"&quot;html2ps&quot; -U -o &quot;%o&quot; &quot;%i&quot;\"/>"
122 " <delegate decode=\"svg\" command=\"&quot;wmf2eps&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
123 " <delegate decode=\"txt\" encode=\"ps\" mode=\"bi\" command=\"&quot;enscript&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
124 " <delegate encode=\"win\" stealth=\"True\" spawn=\"True\" command=\"&quot;/usr/local/bin/display&quot; -immutable -delay 0 -window-group %g -title &quot;%l of %f&quot; &quot;temporary:%i&quot;\"/>"
125 " <delegate decode=\"wmf\" command=\"&quot;wmf2eps&quot; -o &quot;%o&quot; &quot;%i&quot;\"/>"
126 "</delegatemap>";
127
128/*
129 Global declaractions.
130*/
131static LinkedListInfo
132 *delegate_list = (LinkedListInfo *) NULL;
133
134static SemaphoreInfo
135 *delegate_semaphore = (SemaphoreInfo *) NULL;
136
137static volatile MagickBooleanType
138 instantiate_delegate = MagickFalse;
139
140/*
141 Forward declaractions.
142*/
143static MagickBooleanType
144 InitializeDelegateList(ExceptionInfo *),
145 LoadDelegateLists(const char *,ExceptionInfo *);
146
147/*
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149% %
150% %
151% %
cristyf34a1452009-10-24 22:29:27 +0000152+ 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 +0000153% %
154% %
155% %
156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157%
cristyf34a1452009-10-24 22:29:27 +0000158% DelegateComponentGenesis() instantiates the delegate component.
cristy3ed852e2009-09-05 21:47:34 +0000159%
cristyf34a1452009-10-24 22:29:27 +0000160% The format of the DelegateComponentGenesis method is:
cristy3ed852e2009-09-05 21:47:34 +0000161%
cristyf34a1452009-10-24 22:29:27 +0000162% MagickBooleanType DelegateComponentGenesis(void)
163%
164*/
165MagickExport MagickBooleanType DelegateComponentGenesis(void)
166{
167 AcquireSemaphoreInfo(&delegate_semaphore);
168 RelinquishSemaphoreInfo(delegate_semaphore);
169 return(MagickTrue);
170}
171
172/*
173%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174% %
175% %
176% %
177% 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 %
178% %
179% %
180% %
181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
182%
183% DelegateComponentTerminus() destroys the delegate component.
184%
185% The format of the DelegateComponentTerminus method is:
186%
187% DelegateComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000188%
189*/
190
191static void *DestroyDelegate(void *delegate_info)
192{
193 register DelegateInfo
194 *p;
195
196 p=(DelegateInfo *) delegate_info;
197 if (p->path != (char *) NULL)
198 p->path=DestroyString(p->path);
199 if (p->decode != (char *) NULL)
200 p->decode=DestroyString(p->decode);
201 if (p->encode != (char *) NULL)
202 p->encode=DestroyString(p->encode);
203 if (p->commands != (char *) NULL)
204 p->commands=DestroyString(p->commands);
205 p=(DelegateInfo *) RelinquishMagickMemory(p);
206 return((void *) NULL);
207}
208
209
cristyf34a1452009-10-24 22:29:27 +0000210MagickExport void DelegateComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000211{
212 AcquireSemaphoreInfo(&delegate_semaphore);
213 if (delegate_list != (LinkedListInfo *) NULL)
214 delegate_list=DestroyLinkedList(delegate_list,DestroyDelegate);
215 instantiate_delegate=MagickFalse;
216 RelinquishSemaphoreInfo(delegate_semaphore);
217 DestroySemaphoreInfo(&delegate_semaphore);
218}
219
220/*
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222% %
223% %
224% %
225% G e t D e l e g a t e C o m m a n d %
226% %
227% %
228% %
229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230%
231% GetDelegateCommand() replaces any embedded formatting characters with the
232% appropriate image attribute and returns the resulting command.
233%
234% The format of the GetDelegateCommand method is:
235%
236% char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
237% const char *decode,const char *encode,ExceptionInfo *exception)
238%
239% A description of each parameter follows:
240%
241% o command: Method GetDelegateCommand returns the command associated
242% with specified delegate tag.
243%
244% o image_info: the image info.
245%
246% o image: the image.
247%
248% o decode: Specifies the decode delegate we are searching for as a
249% character string.
250%
251% o encode: Specifies the encode delegate we are searching for as a
252% character string.
253%
254% o exception: return any errors or warnings in this structure.
255%
256*/
257MagickExport char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
258 const char *decode,const char *encode,ExceptionInfo *exception)
259{
260 char
261 *command,
262 **commands;
263
264 const DelegateInfo
265 *delegate_info;
266
267 register long
268 i;
269
270 assert(image_info != (ImageInfo *) NULL);
271 assert(image_info->signature == MagickSignature);
272 assert(image != (Image *) NULL);
273 assert(image->signature == MagickSignature);
274 if (image->debug != MagickFalse)
275 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
276 delegate_info=GetDelegateInfo(decode,encode,exception);
277 if (delegate_info == (const DelegateInfo *) NULL)
278 {
279 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
280 "NoTagFound","`%s'",decode ? decode : encode);
281 return((char *) NULL);
282 }
283 commands=StringToList(delegate_info->commands);
284 if (commands == (char **) NULL)
285 {
286 (void) ThrowMagickException(exception,GetMagickModule(),
287 ResourceLimitError,"MemoryAllocationFailed","`%s'",
288 decode ? decode : encode);
289 return((char *) NULL);
290 }
291 command=InterpretImageProperties(image_info,image,commands[0]);
292 if (command == (char *) NULL)
293 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
294 "MemoryAllocationFailed","`%s'",commands[0]);
295 /*
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(),"...");
329 assert(delegate_info != (DelegateInfo *) NULL);
330 assert(delegate_info->signature == MagickSignature);
331 return(delegate_info->commands);
332}
333
334/*
335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336% %
337% %
338% %
339% G e t D e l e g a t e I n f o %
340% %
341% %
342% %
343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
344%
345% GetDelegateInfo() returns any delegates associated with the specified tag.
346%
347% The format of the GetDelegateInfo method is:
348%
349% const DelegateInfo *GetDelegateInfo(const char *decode,
350% const char *encode,ExceptionInfo *exception)
351%
352% A description of each parameter follows:
353%
354% o decode: Specifies the decode delegate we are searching for as a
355% character string.
356%
357% o encode: Specifies the encode delegate we are searching for as a
358% character string.
359%
360% o exception: return any errors or warnings in this structure.
361%
362*/
363MagickExport const DelegateInfo *GetDelegateInfo(const char *decode,
364 const char *encode,ExceptionInfo *exception)
365{
366 register const DelegateInfo
367 *p;
368
369 assert(exception != (ExceptionInfo *) NULL);
370 if ((delegate_list == (LinkedListInfo *) NULL) ||
371 (instantiate_delegate == MagickFalse))
372 if (InitializeDelegateList(exception) == MagickFalse)
373 return((const DelegateInfo *) NULL);
374 if ((delegate_list == (LinkedListInfo *) NULL) ||
375 (IsLinkedListEmpty(delegate_list) != MagickFalse))
376 return((const DelegateInfo *) NULL);
377 if ((LocaleCompare(decode,"*") == 0) && (LocaleCompare(encode,"*") == 0))
378 return((const DelegateInfo *) GetValueFromLinkedList(delegate_list,0));
379 /*
380 Search for named delegate.
381 */
382 AcquireSemaphoreInfo(&delegate_semaphore);
383 ResetLinkedListIterator(delegate_list);
384 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
385 while (p != (const DelegateInfo *) NULL)
386 {
387 if (p->mode > 0)
388 {
389 if (LocaleCompare(p->decode,decode) == 0)
390 break;
391 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
392 continue;
393 }
394 if (p->mode < 0)
395 {
396 if (LocaleCompare(p->encode,encode) == 0)
397 break;
398 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
399 continue;
400 }
401 if (LocaleCompare(decode,p->decode) == 0)
402 if (LocaleCompare(encode,p->encode) == 0)
403 break;
404 if (LocaleCompare(decode,"*") == 0)
405 if (LocaleCompare(encode,p->encode) == 0)
406 break;
407 if (LocaleCompare(decode,p->decode) == 0)
408 if (LocaleCompare(encode,"*") == 0)
409 break;
410 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
411 }
412 if (p != (const DelegateInfo *) NULL)
413 (void) InsertValueInLinkedList(delegate_list,0,
414 RemoveElementByValueFromLinkedList(delegate_list,p));
415 RelinquishSemaphoreInfo(delegate_semaphore);
416 return(p);
417}
418
419/*
420%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421% %
422% %
423% %
424% G e t D e l e g a t e I n f o L i s t %
425% %
426% %
427% %
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429%
430% GetDelegateInfoList() returns any delegates that match the specified pattern.
431%
432% The delegate of the GetDelegateInfoList function is:
433%
434% const DelegateInfo **GetDelegateInfoList(const char *pattern,
435% unsigned long *number_delegates,ExceptionInfo *exception)
436%
437% A description of each parameter follows:
438%
439% o pattern: Specifies a pointer to a text string containing a pattern.
440%
441% o number_delegates: This integer returns the number of delegates in the
442% list.
443%
444% o exception: return any errors or warnings in this structure.
445%
446*/
447
448#if defined(__cplusplus) || defined(c_plusplus)
449extern "C" {
450#endif
451
452static int DelegateInfoCompare(const void *x,const void *y)
453{
454 const DelegateInfo
455 **p,
456 **q;
457
458 p=(const DelegateInfo **) x,
459 q=(const DelegateInfo **) y;
460 if (LocaleCompare((*p)->path,(*q)->path) == 0)
461 {
462 if ((*p)->decode == (char *) NULL)
463 if (((*p)->encode != (char *) NULL) &&
464 ((*q)->encode != (char *) NULL))
465 return(strcmp((*p)->encode,(*q)->encode));
466 if (((*p)->decode != (char *) NULL) &&
467 ((*q)->decode != (char *) NULL))
468 return(strcmp((*p)->decode,(*q)->decode));
469 }
470 return(LocaleCompare((*p)->path,(*q)->path));
471}
472
473#if defined(__cplusplus) || defined(c_plusplus)
474}
475#endif
476
477MagickExport const DelegateInfo **GetDelegateInfoList(const char *pattern,
478 unsigned long *number_delegates,ExceptionInfo *exception)
479{
480 const DelegateInfo
481 **delegates;
482
483 register const DelegateInfo
484 *p;
485
486 register long
487 i;
488
489 /*
490 Allocate delegate list.
491 */
492 assert(pattern != (char *) NULL);
493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
494 assert(number_delegates != (unsigned long *) NULL);
495 *number_delegates=0;
496 p=GetDelegateInfo("*","*",exception);
497 if (p == (const DelegateInfo *) NULL)
498 return((const DelegateInfo **) NULL);
499 delegates=(const DelegateInfo **) AcquireQuantumMemory((size_t)
500 GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
501 if (delegates == (const DelegateInfo **) NULL)
502 return((const DelegateInfo **) NULL);
503 /*
504 Generate delegate list.
505 */
506 AcquireSemaphoreInfo(&delegate_semaphore);
507 ResetLinkedListIterator(delegate_list);
508 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
509 for (i=0; p != (const DelegateInfo *) NULL; )
510 {
511 if ((p->stealth == MagickFalse) &&
512 ((GlobExpression(p->decode,pattern,MagickFalse) != MagickFalse) ||
513 (GlobExpression(p->encode,pattern,MagickFalse) != MagickFalse)))
514 delegates[i++]=p;
515 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
516 }
517 RelinquishSemaphoreInfo(delegate_semaphore);
518 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateInfoCompare);
519 delegates[i]=(DelegateInfo *) NULL;
520 *number_delegates=(unsigned long) i;
521 return(delegates);
522}
523
524/*
525%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526% %
527% %
528% %
529% G e t D e l e g a t e L i s t %
530% %
531% %
532% %
533%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534%
535% GetDelegateList() returns any image format delegates that match the
536% specified pattern.
537%
538% The format of the GetDelegateList function is:
539%
540% char **GetDelegateList(const char *pattern,
541% unsigned long *number_delegates,ExceptionInfo *exception)
542%
543% A description of each parameter follows:
544%
545% o pattern: Specifies a pointer to a text string containing a pattern.
546%
547% o number_delegates: This integer returns the number of delegates
548% in the list.
549%
550% o exception: return any errors or warnings in this structure.
551%
552*/
553
554#if defined(__cplusplus) || defined(c_plusplus)
555extern "C" {
556#endif
557
558static int DelegateCompare(const void *x,const void *y)
559{
560 register const char
561 **p,
562 **q;
563
564 p=(const char **) x;
565 q=(const char **) y;
566 return(LocaleCompare(*p,*q));
567}
568
569#if defined(__cplusplus) || defined(c_plusplus)
570}
571#endif
572
573MagickExport char **GetDelegateList(const char *pattern,
574 unsigned long *number_delegates,ExceptionInfo *exception)
575{
576 char
577 **delegates;
578
579 register const DelegateInfo
580 *p;
581
582 register long
583 i;
584
585 /*
586 Allocate delegate list.
587 */
588 assert(pattern != (char *) NULL);
589 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
590 assert(number_delegates != (unsigned long *) NULL);
591 *number_delegates=0;
592 p=GetDelegateInfo("*","*",exception);
593 if (p == (const DelegateInfo *) NULL)
594 return((char **) NULL);
595 delegates=(char **) AcquireQuantumMemory((size_t)
596 GetNumberOfElementsInLinkedList(delegate_list)+1UL,sizeof(*delegates));
597 if (delegates == (char **) NULL)
598 return((char **) NULL);
599 AcquireSemaphoreInfo(&delegate_semaphore);
600 ResetLinkedListIterator(delegate_list);
601 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
602 for (i=0; p != (const DelegateInfo *) NULL; )
603 {
604 if ((p->stealth == MagickFalse) &&
605 (GlobExpression(p->decode,pattern,MagickFalse) != MagickFalse))
606 delegates[i++]=ConstantString(p->decode);
607 if ((p->stealth == MagickFalse) &&
608 (GlobExpression(p->encode,pattern,MagickFalse) != MagickFalse))
609 delegates[i++]=ConstantString(p->encode);
610 p=(const DelegateInfo *) GetNextValueInLinkedList(delegate_list);
611 }
612 RelinquishSemaphoreInfo(delegate_semaphore);
613 qsort((void *) delegates,(size_t) i,sizeof(*delegates),DelegateCompare);
614 delegates[i]=(char *) NULL;
615 *number_delegates=(unsigned long) i;
616 return(delegates);
617}
618
619/*
620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621% %
622% %
623% %
624% G e t D e l e g a t e M o d e %
625% %
626% %
627% %
628%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629%
630% GetDelegateMode() returns the mode of the delegate.
631%
632% The format of the GetDelegateMode method is:
633%
634% long GetDelegateMode(const DelegateInfo *delegate_info)
635%
636% A description of each parameter follows:
637%
638% o delegate_info: The delegate info.
639%
640*/
641MagickExport long GetDelegateMode(const DelegateInfo *delegate_info)
642{
643 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
644 assert(delegate_info != (DelegateInfo *) NULL);
645 assert(delegate_info->signature == MagickSignature);
646 return(delegate_info->mode);
647}
648
649/*
650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651% %
652% %
653% %
654+ G e t D e l e g a t e T h r e a d S u p p o r t %
655% %
656% %
657% %
658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659%
660% GetDelegateThreadSupport() returns MagickTrue if the delegate supports
661% threads.
662%
663% The format of the GetDelegateThreadSupport method is:
664%
665% MagickBooleanType GetDelegateThreadSupport(
666% const DelegateInfo *delegate_info)
667%
668% A description of each parameter follows:
669%
670% o delegate_info: The delegate info.
671%
672*/
673MagickExport MagickBooleanType GetDelegateThreadSupport(
674 const DelegateInfo *delegate_info)
675{
676 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
677 assert(delegate_info != (DelegateInfo *) NULL);
678 assert(delegate_info->signature == MagickSignature);
679 return(delegate_info->thread_support);
680}
681
682/*
683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684% %
685% %
686% %
687+ I n i t i a l i z e D e l e g a t e L i s t %
688% %
689% %
690% %
691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692%
693% InitializeDelegateList() initializes the delegate list.
694%
695% The format of the InitializeDelegateList method is:
696%
697% MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
698%
699% A description of each parameter follows.
700%
701% o exception: return any errors or warnings in this structure.
702%
703*/
704static MagickBooleanType InitializeDelegateList(ExceptionInfo *exception)
705{
706 if ((delegate_list == (LinkedListInfo *) NULL) &&
707 (instantiate_delegate == MagickFalse))
708 {
709 AcquireSemaphoreInfo(&delegate_semaphore);
710 if ((delegate_list == (LinkedListInfo *) NULL) &&
711 (instantiate_delegate == MagickFalse))
712 {
713 (void) LoadDelegateLists(DelegateFilename,exception);
714 instantiate_delegate=MagickTrue;
715 }
716 RelinquishSemaphoreInfo(delegate_semaphore);
717 }
718 return(delegate_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
719}
720
721/*
722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723% %
724% %
725% %
726% I n v o k e D e l e g a t e %
727% %
728% %
729% %
730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731%
732% InvokeDelegate replaces any embedded formatting characters with the
733% appropriate image attribute and executes the resulting command. MagickFalse
734% is returned if the commands execute with success otherwise MagickTrue.
735%
736% The format of the InvokeDelegate method is:
737%
738% MagickBooleanType InvokeDelegate(ImageInfo *image_info,Image *image,
739% const char *decode,const char *encode,ExceptionInfo *exception)
740%
741% A description of each parameter follows:
742%
743% o image_info: the imageInfo.
744%
745% o image: the image.
746%
747% o exception: return any errors or warnings in this structure.
748%
749*/
750
751static inline size_t MagickMin(const size_t x,const size_t y)
752{
753 if (x < y)
754 return(x);
755 return(y);
756}
757
758static MagickBooleanType CopyDelegateFile(const char *source,
759 const char *destination)
760{
761 int
762 destination_file,
763 source_file;
764
765 MagickBooleanType
766 status;
767
768 register size_t
769 i;
770
771 size_t
772 length,
773 quantum;
774
775 ssize_t
776 count;
777
778 struct stat
779 attributes;
780
781 unsigned char
782 *buffer;
783
784 /*
785 Return if destination file already exists and is not empty.
786 */
787 assert(source != (const char *) NULL);
788 assert(destination != (char *) NULL);
789 status=GetPathAttributes(destination,&attributes);
790 if ((status != MagickFalse) && (attributes.st_size != 0))
791 return(MagickTrue);
792 /*
793 Copy source file to destination.
794 */
795 destination_file=open(destination,O_WRONLY | O_BINARY | O_CREAT,S_MODE);
796 if (destination_file == -1)
797 return(MagickFalse);
798 source_file=open(source,O_RDONLY | O_BINARY);
799 if (source_file == -1)
800 {
801 (void) close(destination_file);
802 return(MagickFalse);
803 }
804 quantum=(size_t) MagickMaxBufferExtent;
805 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
806 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
807 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
808 if (buffer == (unsigned char *) NULL)
809 {
810 (void) close(source_file);
811 (void) close(destination_file);
812 return(MagickFalse);
813 }
814 length=0;
815 for (i=0; ; i+=count)
816 {
817 count=(ssize_t) read(source_file,buffer,quantum);
818 if (count <= 0)
819 break;
820 length=(size_t) count;
821 count=(ssize_t) write(destination_file,buffer,length);
822 if ((size_t) count != length)
823 break;
824 }
825 (void) close(destination_file);
826 (void) close(source_file);
827 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
828 return(i != 0 ? MagickTrue : MagickFalse);
829}
830
831MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info,
832 Image *image,const char *decode,const char *encode,ExceptionInfo *exception)
833{
834 char
835 *command,
836 **commands,
837 input_filename[MaxTextExtent],
838 output_filename[MaxTextExtent];
839
840 const DelegateInfo
841 *delegate_info;
842
843 MagickBooleanType
844 status,
845 temporary;
846
847 register long
848 i;
849
850 PolicyRights
851 rights;
852
853 /*
854 Get delegate.
855 */
856 assert(image_info != (ImageInfo *) NULL);
857 assert(image_info->signature == MagickSignature);
858 assert(image != (Image *) NULL);
859 assert(image->signature == MagickSignature);
860 if (image->debug != MagickFalse)
861 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
862 rights=ExecutePolicyRights;
863 if (IsRightsAuthorized(DelegatePolicyDomain,rights,decode) == MagickFalse)
864 {
865 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
866 "NotAuthorized","`%s'",decode);
867 return(MagickFalse);
868 }
869 if (IsRightsAuthorized(DelegatePolicyDomain,rights,encode) == MagickFalse)
870 {
871 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
872 "NotAuthorized","`%s'",encode);
873 return(MagickFalse);
874 }
875 temporary=(*image->filename == '\0') ? MagickTrue : MagickFalse;
876 if (temporary != MagickFalse)
877 if (AcquireUniqueFilename(image->filename) == MagickFalse)
878 {
879 ThrowFileException(exception,FileOpenError,
880 "UnableToCreateTemporaryFile",image->filename);
881 return(MagickFalse);
882 }
883 delegate_info=GetDelegateInfo(decode,encode,exception);
884 if (delegate_info == (DelegateInfo *) NULL)
885 {
886 if (temporary != MagickFalse)
887 (void) RelinquishUniqueFileResource(image->filename);
888 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
889 "NoTagFound","`%s'",decode ? decode : encode);
890 return(MagickFalse);
891 }
892 if (*image_info->filename == '\0')
893 {
894 if (AcquireUniqueFilename(image_info->filename) == MagickFalse)
895 {
896 if (temporary != MagickFalse)
897 (void) RelinquishUniqueFileResource(image->filename);
898 ThrowFileException(exception,FileOpenError,
899 "UnableToCreateTemporaryFile",image_info->filename);
900 return(MagickFalse);
901 }
902 image_info->temporary=MagickTrue;
903 }
904 if ((delegate_info->mode != 0) &&
905 (((decode != (const char *) NULL) &&
906 (delegate_info->encode != (char *) NULL)) ||
907 ((encode != (const char *) NULL) &&
908 (delegate_info->decode != (char *) NULL))))
909 {
910 char
911 *magick;
912
913 ImageInfo
914 *clone_info;
915
916 register Image
917 *p;
918
919 /*
920 Delegate requires a particular image format.
921 */
922 if (AcquireUniqueFilename(image_info->unique) == MagickFalse)
923 {
924 ThrowFileException(exception,FileOpenError,
925 "UnableToCreateTemporaryFile",image_info->unique);
926 return(MagickFalse);
927 }
928 if (AcquireUniqueFilename(image_info->zero) == MagickFalse)
929 {
930 (void) RelinquishUniqueFileResource(image_info->zero);
931 ThrowFileException(exception,FileOpenError,
932 "UnableToCreateTemporaryFile",image_info->zero);
933 return(MagickFalse);
934 }
935 magick=InterpretImageProperties(image_info,image,decode != (char *) NULL ?
936 delegate_info->encode : delegate_info->decode);
937 if (magick == (char *) NULL)
938 {
939 (void) RelinquishUniqueFileResource(image_info->unique);
940 (void) RelinquishUniqueFileResource(image_info->zero);
941 if (temporary != MagickFalse)
942 (void) RelinquishUniqueFileResource(image->filename);
943 (void) ThrowMagickException(exception,GetMagickModule(),
944 DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
945 return(MagickFalse);
946 }
947 LocaleUpper(magick);
948 clone_info=CloneImageInfo(image_info);
949 (void) CopyMagickString((char *) clone_info->magick,magick,
950 MaxTextExtent);
951 if (LocaleCompare(magick,"NULL") != 0)
952 (void) CopyMagickString(image->magick,magick,MaxTextExtent);
953 magick=DestroyString(magick);
954 (void) FormatMagickString(clone_info->filename,MaxTextExtent,"%s:",
955 delegate_info->decode);
956 (void) SetImageInfo(clone_info,MagickTrue,exception);
957 (void) CopyMagickString(clone_info->filename,image_info->filename,
958 MaxTextExtent);
959 (void) CopyMagickString(image_info->filename,image->filename,
960 MaxTextExtent);
961 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
962 {
963 (void) FormatMagickString(p->filename,MaxTextExtent,"%s:%s",
964 delegate_info->decode,clone_info->filename);
965 status=WriteImage(clone_info,p);
966 if (status == MagickFalse)
967 {
968 (void) RelinquishUniqueFileResource(image_info->unique);
969 (void) RelinquishUniqueFileResource(image_info->zero);
970 if (temporary != MagickFalse)
971 (void) RelinquishUniqueFileResource(image->filename);
972 clone_info=DestroyImageInfo(clone_info);
973 (void) ThrowMagickException(exception,GetMagickModule(),
974 DelegateError,"DelegateFailed","`%s'",decode ? decode : encode);
975 return(MagickFalse);
976 }
977 if (clone_info->adjoin != MagickFalse)
978 break;
979 }
980 (void) RelinquishUniqueFileResource(image_info->unique);
981 (void) RelinquishUniqueFileResource(image_info->zero);
982 clone_info=DestroyImageInfo(clone_info);
983 }
984 /*
985 Invoke delegate.
986 */
987 commands=StringToList(delegate_info->commands);
988 if (commands == (char **) NULL)
989 {
990 if (temporary != MagickFalse)
991 (void) RelinquishUniqueFileResource(image->filename);
992 (void) ThrowMagickException(exception,GetMagickModule(),
993 ResourceLimitError,"MemoryAllocationFailed","`%s'",
994 decode ? decode : encode);
995 return(MagickFalse);
996 }
997 command=(char *) NULL;
998 status=MagickFalse;
999 (void) CopyMagickString(output_filename,image_info->filename,MaxTextExtent);
1000 (void) CopyMagickString(input_filename,image->filename,MaxTextExtent);
1001 for (i=0; commands[i] != (char *) NULL; i++)
1002 {
1003 status=AcquireUniqueSymbolicLink(output_filename,image_info->filename);
1004 if (AcquireUniqueFilename(image_info->unique) == MagickFalse)
1005 {
1006 ThrowFileException(exception,FileOpenError,
1007 "UnableToCreateTemporaryFile",image_info->unique);
1008 break;
1009 }
1010 if (AcquireUniqueFilename(image_info->zero) == MagickFalse)
1011 {
1012 (void) RelinquishUniqueFileResource(image_info->unique);
1013 ThrowFileException(exception,FileOpenError,
1014 "UnableToCreateTemporaryFile",image_info->zero);
1015 break;
1016 }
1017 if (LocaleCompare(decode,"SCAN") != 0)
1018 {
1019 status=AcquireUniqueSymbolicLink(input_filename,image->filename);
1020 if (status == MagickFalse)
1021 {
1022 ThrowFileException(exception,FileOpenError,
1023 "UnableToCreateTemporaryFile",input_filename);
1024 break;
1025 }
1026 }
1027 status=MagickFalse;
1028 command=InterpretImageProperties(image_info,image,commands[i]);
1029 if (command != (char *) NULL)
1030 {
1031 /*
1032 Execute delegate.
1033 */
1034 if (delegate_info->spawn != MagickFalse)
1035 (void) ConcatenateString(&command," &");
cristyb32b90a2009-09-07 21:45:48 +00001036 status=SystemCommand(image_info->verbose,command,exception) != 0 ?
1037 MagickTrue : MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001038 if (delegate_info->spawn != MagickFalse)
1039 (void) sleep(2);
1040 command=DestroyString(command);
1041 }
1042 if (LocaleCompare(decode,"SCAN") != 0)
1043 {
1044 if (CopyDelegateFile(image->filename,input_filename) == MagickFalse)
1045 (void) RelinquishUniqueFileResource(input_filename);
1046 }
1047 if (CopyDelegateFile(image_info->filename,output_filename) == MagickFalse)
1048 (void) RelinquishUniqueFileResource(output_filename);
1049 if (image_info->temporary != MagickFalse)
1050 (void) RelinquishUniqueFileResource(image_info->filename);
1051 (void) RelinquishUniqueFileResource(image_info->unique);
1052 (void) RelinquishUniqueFileResource(image_info->zero);
1053 (void) RelinquishUniqueFileResource(image_info->filename);
1054 (void) RelinquishUniqueFileResource(image->filename);
1055 if (status != MagickFalse)
1056 {
1057 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1058 "DelegateFailed","`%s'",commands[i]);
1059 break;
1060 }
1061 commands[i]=DestroyString(commands[i]);
1062 }
1063 (void) CopyMagickString(image_info->filename,output_filename,MaxTextExtent);
1064 (void) CopyMagickString(image->filename,input_filename,MaxTextExtent);
1065 /*
1066 Relinquish resources.
1067 */
1068 for ( ; commands[i] != (char *) NULL; i++)
1069 commands[i]=DestroyString(commands[i]);
1070 commands=(char **) RelinquishMagickMemory(commands);
1071 if (temporary != MagickFalse)
1072 (void) RelinquishUniqueFileResource(image->filename);
1073 return(status == MagickFalse ? MagickTrue : MagickFalse);
1074}
1075
1076/*
1077%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078% %
1079% %
1080% %
1081% L i s t D e l e g a t e I n f o %
1082% %
1083% %
1084% %
1085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1086%
1087% ListDelegateInfo() lists the image formats to a file.
1088%
1089% The format of the ListDelegateInfo method is:
1090%
1091% MagickBooleanType ListDelegateInfo(FILE *file,ExceptionInfo *exception)
1092%
1093% A description of each parameter follows.
1094%
1095% o file: An pointer to a FILE.
1096%
1097% o exception: return any errors or warnings in this structure.
1098%
1099*/
1100MagickExport MagickBooleanType ListDelegateInfo(FILE *file,
1101 ExceptionInfo *exception)
1102{
1103 const DelegateInfo
1104 **delegate_info;
1105
1106 char
1107 **commands,
1108 delegate[MaxTextExtent];
1109
1110 const char
1111 *path;
1112
1113 long
1114 j;
1115
1116 register long
1117 i;
1118
1119 unsigned long
1120 number_delegates;
1121
1122 if (file == (const FILE *) NULL)
1123 file=stdout;
1124 delegate_info=GetDelegateInfoList("*",&number_delegates,exception);
1125 if (delegate_info == (const DelegateInfo **) NULL)
1126 return(MagickFalse);
1127 path=(const char *) NULL;
1128 for (i=0; i < (long) number_delegates; i++)
1129 {
1130 if (delegate_info[i]->stealth != MagickFalse)
1131 continue;
1132 if ((path == (const char *) NULL) ||
1133 (LocaleCompare(path,delegate_info[i]->path) != 0))
1134 {
1135 if (delegate_info[i]->path != (char *) NULL)
1136 (void) fprintf(file,"\nPath: %s\n\n",delegate_info[i]->path);
1137 (void) fprintf(file,"Delegate Command\n");
1138 (void) fprintf(file,"-------------------------------------------------"
1139 "------------------------------\n");
1140 }
1141 path=delegate_info[i]->path;
1142 *delegate='\0';
1143 if (delegate_info[i]->encode != (char *) NULL)
1144 (void) CopyMagickString(delegate,delegate_info[i]->encode,MaxTextExtent);
1145 (void) ConcatenateMagickString(delegate," ",MaxTextExtent);
1146 delegate[8]='\0';
1147 commands=StringToList(delegate_info[i]->commands);
1148 if (commands == (char **) NULL)
1149 continue;
1150 (void) fprintf(file,"%11s%c=%c%s ",delegate_info[i]->decode ?
1151 delegate_info[i]->decode : "",delegate_info[i]->mode <= 0 ? '<' : ' ',
1152 delegate_info[i]->mode >= 0 ? '>' : ' ',delegate);
1153 StripString(commands[0]);
1154 (void) fprintf(file,"\"%s\"\n",commands[0]);
1155 for (j=1; commands[j] != (char *) NULL; j++)
1156 {
1157 StripString(commands[j]);
1158 (void) fprintf(file," \"%s\"\n",commands[j]);
1159 }
1160 for (j=0; commands[j] != (char *) NULL; j++)
1161 commands[j]=DestroyString(commands[j]);
1162 commands=(char **) RelinquishMagickMemory(commands);
1163 }
1164 (void) fflush(file);
1165 delegate_info=(const DelegateInfo **)
1166 RelinquishMagickMemory((void *) delegate_info);
1167 return(MagickTrue);
1168}
1169
1170/*
1171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172% %
1173% %
1174% %
1175+ L o a d D e l e g a t e L i s t %
1176% %
1177% %
1178% %
1179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1180%
1181% LoadDelegateList() loads the delegate configuration file which provides a
1182% mapping between delegate attributes and a delegate name.
1183%
1184% The format of the LoadDelegateList method is:
1185%
1186% MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
1187% const unsigned long depth,ExceptionInfo *exception)
1188%
1189% A description of each parameter follows:
1190%
1191% o xml: The delegate list in XML format.
1192%
1193% o filename: The delegate list filename.
1194%
1195% o depth: depth of <include /> statements.
1196%
1197% o exception: return any errors or warnings in this structure.
1198%
1199*/
1200static MagickBooleanType LoadDelegateList(const char *xml,const char *filename,
1201 const unsigned long depth,ExceptionInfo *exception)
1202{
1203 char
1204 keyword[MaxTextExtent],
1205 *token;
1206
1207 const char
1208 *q;
1209
1210 DelegateInfo
1211 *delegate_info;
1212
1213 MagickBooleanType
1214 status;
1215
1216 /*
1217 Load the delegate map file.
1218 */
1219 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1220 "Loading delegate configuration file \"%s\" ...",filename);
1221 if (xml == (const char *) NULL)
1222 return(MagickFalse);
1223 if (delegate_list == (LinkedListInfo *) NULL)
1224 {
1225 delegate_list=NewLinkedList(0);
1226 if (delegate_list == (LinkedListInfo *) NULL)
1227 {
1228 ThrowFileException(exception,ResourceLimitError,
1229 "MemoryAllocationFailed",filename);
1230 return(MagickFalse);
1231 }
1232 }
1233 status=MagickTrue;
1234 delegate_info=(DelegateInfo *) NULL;
1235 token=AcquireString(xml);
1236 for (q=(const char *) xml; *q != '\0'; )
1237 {
1238 /*
1239 Interpret XML.
1240 */
1241 GetMagickToken(q,&q,token);
1242 if (*token == '\0')
1243 break;
1244 (void) CopyMagickString(keyword,token,MaxTextExtent);
1245 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1246 {
1247 /*
1248 Doctype element.
1249 */
1250 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1251 GetMagickToken(q,&q,token);
1252 continue;
1253 }
1254 if (LocaleNCompare(keyword,"<!--",4) == 0)
1255 {
1256 /*
1257 Comment element.
1258 */
1259 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1260 GetMagickToken(q,&q,token);
1261 continue;
1262 }
1263 if (LocaleCompare(keyword,"<include") == 0)
1264 {
1265 /*
1266 Include element.
1267 */
1268 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1269 {
1270 (void) CopyMagickString(keyword,token,MaxTextExtent);
1271 GetMagickToken(q,&q,token);
1272 if (*token != '=')
1273 continue;
1274 GetMagickToken(q,&q,token);
1275 if (LocaleCompare(keyword,"file") == 0)
1276 {
1277 if (depth > 200)
1278 (void) ThrowMagickException(exception,GetMagickModule(),
1279 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1280 else
1281 {
1282 char
1283 path[MaxTextExtent],
1284 *xml;
1285
1286 GetPathComponent(filename,HeadPath,path);
1287 if (*path != '\0')
1288 (void) ConcatenateMagickString(path,DirectorySeparator,
1289 MaxTextExtent);
1290 if (*token == *DirectorySeparator)
1291 (void) CopyMagickString(path,token,MaxTextExtent);
1292 else
1293 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1294 xml=FileToString(path,~0,exception);
1295 if (xml != (char *) NULL)
1296 {
1297 status=LoadDelegateList(xml,path,depth+1,exception);
1298 xml=(char *) RelinquishMagickMemory(xml);
1299 }
1300 }
1301 }
1302 }
1303 continue;
1304 }
1305 if (LocaleCompare(keyword,"<delegate") == 0)
1306 {
1307 /*
1308 Delegate element.
1309 */
1310 delegate_info=(DelegateInfo *) AcquireMagickMemory(
1311 sizeof(*delegate_info));
1312 if (delegate_info == (DelegateInfo *) NULL)
1313 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1314 (void) ResetMagickMemory(delegate_info,0,sizeof(*delegate_info));
1315 delegate_info->path=ConstantString(filename);
1316 delegate_info->signature=MagickSignature;
1317 continue;
1318 }
1319 if (delegate_info == (DelegateInfo *) NULL)
1320 continue;
1321 if (LocaleCompare(keyword,"/>") == 0)
1322 {
1323 status=AppendValueToLinkedList(delegate_list,delegate_info);
1324 if (status == MagickFalse)
1325 (void) ThrowMagickException(exception,GetMagickModule(),
1326 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1327 delegate_info->commands);
1328 delegate_info=(DelegateInfo *) NULL;
1329 }
1330 GetMagickToken(q,(const char **) NULL,token);
1331 if (*token != '=')
1332 continue;
1333 GetMagickToken(q,&q,token);
1334 GetMagickToken(q,&q,token);
1335 switch (*keyword)
1336 {
1337 case 'C':
1338 case 'c':
1339 {
1340 if (LocaleCompare((char *) keyword,"command") == 0)
1341 {
1342 char
1343 *commands;
1344
1345 commands=AcquireString(token);
1346#if defined(__WINDOWS__)
1347 if (strchr(commands,'@') != (char *) NULL)
1348 {
1349 char
1350 path[MaxTextExtent];
1351
1352 NTGhostscriptEXE(path,MaxTextExtent);
1353 (void) SubstituteString((char **) &commands,"@PSDelegate@",
1354 path);
1355 (void) SubstituteString((char **) &commands,"\\","/");
1356 }
1357#endif
1358 (void) SubstituteString((char **) &commands,"&amp;","&");
1359 (void) SubstituteString((char **) &commands,"&quot;","\"");
1360 (void) SubstituteString((char **) &commands,"&gt;",">");
1361 (void) SubstituteString((char **) &commands,"&lt;","<");
1362 delegate_info->commands=commands;
1363 break;
1364 }
1365 break;
1366 }
1367 case 'D':
1368 case 'd':
1369 {
1370 if (LocaleCompare((char *) keyword,"decode") == 0)
1371 {
1372 delegate_info->decode=ConstantString(token);
1373 delegate_info->mode=1;
1374 break;
1375 }
1376 break;
1377 }
1378 case 'E':
1379 case 'e':
1380 {
1381 if (LocaleCompare((char *) keyword,"encode") == 0)
1382 {
1383 delegate_info->encode=ConstantString(token);
1384 delegate_info->mode=(-1);
1385 break;
1386 }
1387 break;
1388 }
1389 case 'M':
1390 case 'm':
1391 {
1392 if (LocaleCompare((char *) keyword,"mode") == 0)
1393 {
1394 delegate_info->mode=1;
1395 if (LocaleCompare(token,"bi") == 0)
1396 delegate_info->mode=0;
1397 else
1398 if (LocaleCompare(token,"encode") == 0)
1399 delegate_info->mode=(-1);
1400 break;
1401 }
1402 break;
1403 }
1404 case 'S':
1405 case 's':
1406 {
1407 if (LocaleCompare((char *) keyword,"spawn") == 0)
1408 {
1409 delegate_info->spawn=IsMagickTrue(token);
1410 break;
1411 }
1412 if (LocaleCompare((char *) keyword,"stealth") == 0)
1413 {
1414 delegate_info->stealth=IsMagickTrue(token);
1415 break;
1416 }
1417 break;
1418 }
1419 case 'T':
1420 case 't':
1421 {
1422 if (LocaleCompare((char *) keyword,"thread-support") == 0)
1423 {
1424 delegate_info->thread_support=IsMagickTrue(token);
1425 break;
1426 }
1427 break;
1428 }
1429 default:
1430 break;
1431 }
1432 }
1433 token=(char *) RelinquishMagickMemory(token);
1434 return(status);
1435}
1436
1437/*
1438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439% %
1440% %
1441% %
1442% L o a d D e l e g a t e L i s t s %
1443% %
1444% %
1445% %
1446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447%
1448% LoadDelegateList() loads one or more delegate configuration file which
1449% provides a mapping between delegate attributes and a delegate name.
1450%
1451% The format of the LoadDelegateLists method is:
1452%
1453% MagickBooleanType LoadDelegateLists(const char *filename,
1454% ExceptionInfo *exception)
1455%
1456% A description of each parameter follows:
1457%
1458% o filename: the font file name.
1459%
1460% o exception: return any errors or warnings in this structure.
1461%
1462*/
1463static MagickBooleanType LoadDelegateLists(const char *filename,
1464 ExceptionInfo *exception)
1465{
1466#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1467 return(LoadDelegateList(DelegateMap,"built-in",0,exception));
1468#else
1469 const StringInfo
1470 *option;
1471
1472 LinkedListInfo
1473 *options;
1474
1475 MagickStatusType
1476 status;
1477
1478 status=MagickFalse;
1479 options=GetConfigureOptions(filename,exception);
1480 option=(const StringInfo *) GetNextValueInLinkedList(options);
1481 while (option != (const StringInfo *) NULL)
1482 {
1483 status|=LoadDelegateList((const char *) GetStringInfoDatum(option),
1484 GetStringInfoPath(option),0,exception);
1485 option=(const StringInfo *) GetNextValueInLinkedList(options);
1486 }
1487 options=DestroyConfigureOptions(options);
1488 if ((delegate_list == (LinkedListInfo *) NULL) ||
1489 (IsLinkedListEmpty(delegate_list) != MagickFalse))
1490 status|=LoadDelegateList(DelegateMap,"built-in",0,exception);
1491 return(status != 0 ? MagickTrue : MagickFalse);
1492#endif
1493}