blob: b4187977b1e69dc0f2db6263c71b31729b890de7 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% M M AAA GGGG IIIII CCCC %
6% MM MM A A G I C %
7% M M M AAAAA G GGG I C %
8% M M A A G G I C %
9% M M A A GGGG IIIII CCCC %
10% %
11% %
12% MagickCore Image Magic Methods %
13% %
14% Software Design %
15% Bob Friesenhahn %
16% July 2000 %
17% %
18% %
cristy16af1cb2009-12-11 21:38:29 +000019% Copyright 1999-2010 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%
36*/
37
38/*
39 Include declarations.
40*/
41#include "magick/studio.h"
42#include "magick/blob.h"
43#include "magick/client.h"
44#include "magick/configure.h"
45#include "magick/exception.h"
46#include "magick/exception-private.h"
47#include "magick/hashmap.h"
48#include "magick/magic.h"
49#include "magick/memory_.h"
50#include "magick/semaphore.h"
51#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000052#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000053#include "magick/token.h"
54#include "magick/utility.h"
55#include "magick/xml-tree.h"
56
57/*
58 Define declarations.
59*/
60#define MagicFilename "magic.xml"
cristy54a531d2009-10-21 17:58:01 +000061#define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
cristy3ed852e2009-09-05 21:47:34 +000062
63/*
cristy54a531d2009-10-21 17:58:01 +000064 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000065*/
cristy1ca3eb32009-10-15 18:41:54 +000066typedef struct _MagicMapInfo
67{
68 const char
69 *name;
70
cristye3e77a12009-10-16 00:47:21 +000071 const MagickOffsetType
72 offset;
73
cristybcdce3d2009-10-15 20:04:49 +000074 const unsigned char
cristy1ca3eb32009-10-15 18:41:54 +000075 *magic;
76
cristye3e77a12009-10-16 00:47:21 +000077 const size_t
cristy1ca3eb32009-10-15 18:41:54 +000078 length;
cristy1ca3eb32009-10-15 18:41:54 +000079} MagicMapInfo;
cristy54a531d2009-10-21 17:58:01 +000080
81/*
82 Static declarations.
83*/
cristy1ca3eb32009-10-15 18:41:54 +000084static const MagicMapInfo
85 MagicMap[] =
86 {
cristye3e77a12009-10-16 00:47:21 +000087 { "AVI", 0, MagickString("RIFF") },
88 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
89 { "8BIMTEXT", 0, MagickString("8BIM#") },
90 { "8BIM", 0, MagickString("8BIM") },
91 { "BMP", 0, MagickString("BA") },
92 { "BMP", 0, MagickString("BM") },
93 { "BMP", 0, MagickString("CI") },
94 { "BMP", 0, MagickString("CP") },
95 { "BMP", 0, MagickString("IC") },
96 { "BMP", 0, MagickString("PI") },
97 { "CALS", 21, MagickString("version: MIL-STD-1840") },
98 { "CALS", 0, MagickString("srcdocid:") },
99 { "CALS", 9, MagickString("srcdocid:") },
100 { "CALS", 8, MagickString("rorient:") },
101 { "CGM", 0, MagickString("BEGMF") },
102 { "CIN", 0, MagickString("\200\052\137\327") },
103 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
104 { "DCM", 128, MagickString("DICM") },
105 { "DCX", 0, MagickString("\261\150\336\72") },
106 { "DIB", 0, MagickString("\050\000") },
107 { "DDS", 0, MagickString("DDS ") },
108 { "DJVU", 0, MagickString("AT&TFORM") },
109 { "DOT", 0, MagickString("digraph") },
110 { "DPX", 0, MagickString("SDPX") },
111 { "DPX", 0, MagickString("XPDS") },
112 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
113 { "EPT", 0, MagickString("\305\320\323\306") },
114 { "EXR", 0, MagickString("\166\057\061\001") },
115 { "FAX", 0, MagickString("DFAX") },
116 { "FIG", 0, MagickString("#FIG") },
117 { "FITS", 0, MagickString("IT0") },
118 { "FITS", 0, MagickString("SIMPLE") },
119 { "FPX", 0, MagickString("\320\317\021\340") },
120 { "GIF", 0, MagickString("GIF8") },
121 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
122 { "HDF", 1, MagickString("HDF") },
123 { "HPGL", 0, MagickString("IN;") },
124 { "HPGL", 0, MagickString("\033E\033") },
125 { "HTML", 1, MagickString("HTML") },
126 { "HTML", 1, MagickString("html") },
127 { "ILBM", 8, MagickString("ILBM") },
128 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
129 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
130 { "IPTC", 0, MagickString("\034\002") },
131 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
132 { "JPEG", 0, MagickString("\377\330\377") },
133 { "JPC", 0, MagickString("\377\117") },
134 { "JP2", 4, MagickString("\152\120\040\040\015") },
135 { "MIFF", 0, MagickString("Id=ImageMagick") },
136 { "MIFF", 0, MagickString("id=ImageMagick") },
137 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
138 { "MPC", 0, MagickString("id=MagickCache") },
139 { "MPEG", 0, MagickString("\000\000\001\263") },
140 { "MRW", 0, MagickString("\x00MRM") },
141 { "MVG", 0, MagickString("push graphic-context") },
142 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
143 { "PCD", 2048, MagickString("PCD_") },
144 { "PCL", 0, MagickString("\033E\033") },
145 { "PCX", 0, MagickString("\012\002") },
146 { "PCX", 0, MagickString("\012\005") },
147 { "PDB", 60, MagickString("vIMGView") },
148 { "PDF", 0, MagickString("%PDF-") },
cristy7adb4db2010-01-24 17:14:03 +0000149 { "PES", 0, MagickString("#PES") },
cristye3e77a12009-10-16 00:47:21 +0000150 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
151 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
152 { "PGX", 0, MagickString("\050\107\020\115\046") },
153 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
154 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
155 { "PNM", 0, MagickString("P1") },
156 { "PNM", 0, MagickString("P2") },
157 { "PNM", 0, MagickString("P3") },
158 { "PNM", 0, MagickString("P4") },
159 { "PNM", 0, MagickString("P5") },
160 { "PNM", 0, MagickString("P6") },
161 { "PNM", 0, MagickString("P7") },
162 { "PNM", 0, MagickString("PF") },
163 { "PNM", 0, MagickString("Pf") },
164 { "PS", 0, MagickString("%!") },
165 { "PS", 0, MagickString("\004%!") },
166 { "PS", 0, MagickString("\305\320\323\306") },
cristyb4233012010-02-28 20:09:14 +0000167 { "PSB", 0, MagickString("8BPB") },
cristye3e77a12009-10-16 00:47:21 +0000168 { "PSD", 0, MagickString("8BPS") },
169 { "PWP", 0, MagickString("SFW95") },
170 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
171 { "RAD", 0, MagickString("#?RADIANCE") },
172 { "RAD", 0, MagickString("VIEW= ") },
173 { "RLE", 0, MagickString("\122\314") },
174 { "SCT", 0, MagickString("CT") },
175 { "SFW", 0, MagickString("SFW94") },
176 { "SGI", 0, MagickString("\001\332") },
177 { "SUN", 0, MagickString("\131\246\152\225") },
178 { "SVG", 1, MagickString("?XML") },
179 { "SVG", 1, MagickString("?xml") },
180 { "TIFF", 0, MagickString("\115\115\000\052") },
181 { "TIFF", 0, MagickString("\111\111\052\000") },
182 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
183 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
184 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
185 { "VICAR", 0, MagickString("LBLSIZE") },
186 { "VICAR", 0, MagickString("NJPL1I") },
187 { "VIFF", 0, MagickString("\253\001") },
188 { "WMF", 0, MagickString("\327\315\306\232") },
189 { "WMF", 0, MagickString("\001\000\011\000") },
190 { "WPG", 0, MagickString("\377WPC") },
191 { "XBM", 0, MagickString("#define") },
192 { "XCF", 0, MagickString("gimp xcf") },
193 { "XEF", 0, MagickString("FOVb") },
194 { "XPM", 1, MagickString("* XPM *") },
195 { "XWD", 4, MagickString("\007\000\000") },
cristy54a531d2009-10-21 17:58:01 +0000196 { "XWD", 5, MagickString("\000\000\007") }
cristy1ca3eb32009-10-15 18:41:54 +0000197 };
cristy3ed852e2009-09-05 21:47:34 +0000198
199static LinkedListInfo
200 *magic_list = (LinkedListInfo *) NULL;
201
202static SemaphoreInfo
203 *magic_semaphore = (SemaphoreInfo *) NULL;
204
205static volatile MagickBooleanType
206 instantiate_magic = MagickFalse;
207
208/*
209 Forward declarations.
210*/
211static MagickBooleanType
212 InitializeMagicList(ExceptionInfo *),
213 LoadMagicLists(const char *,ExceptionInfo *);
214
215/*
216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217% %
218% %
219% %
cristy3ed852e2009-09-05 21:47:34 +0000220+ G e t M a g i c I n f o %
221% %
222% %
223% %
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225%
226% GetMagicInfo() searches the magic list for the specified name and if found
227% returns attributes for that magic.
228%
229% The format of the GetMagicInfo method is:
230%
231% const MagicInfo *GetMagicInfo(const unsigned char *magic,
232% const size_t length,ExceptionInfo *exception)
233%
234% A description of each parameter follows:
235%
236% o magic: A binary string generally representing the first few characters
237% of the image file or blob.
238%
239% o length: the length of the binary signature.
240%
241% o exception: return any errors or warnings in this structure.
242%
243*/
244MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
245 const size_t length,ExceptionInfo *exception)
246{
247 register const MagicInfo
248 *p;
249
250 assert(exception != (ExceptionInfo *) NULL);
251 if ((magic_list == (LinkedListInfo *) NULL) ||
252 (instantiate_magic == MagickFalse))
253 if (InitializeMagicList(exception) == MagickFalse)
254 return((const MagicInfo *) NULL);
255 if ((magic_list == (LinkedListInfo *) NULL) ||
256 (IsLinkedListEmpty(magic_list) != MagickFalse))
257 return((const MagicInfo *) NULL);
258 if (magic == (const unsigned char *) NULL)
259 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
260 if (length == 0)
261 return((const MagicInfo *) NULL);
262 /*
263 Search for magic tag.
264 */
cristyf84a1932010-01-03 18:00:18 +0000265 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000266 ResetLinkedListIterator(magic_list);
267 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
268 while (p != (const MagicInfo *) NULL)
269 {
270 assert(p->offset >= 0);
271 if (((size_t) (p->offset+p->length) <= length) &&
272 (memcmp(magic+p->offset,p->magic,p->length) == 0))
273 break;
274 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
275 }
276 if (p != (const MagicInfo *) NULL)
277 (void) InsertValueInLinkedList(magic_list,0,
278 RemoveElementByValueFromLinkedList(magic_list,p));
cristyf84a1932010-01-03 18:00:18 +0000279 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000280 return(p);
281}
282
283/*
284%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285% %
286% %
287% %
288% G e t M a g i c I n f o L i s t %
289% %
290% %
291% %
292%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293%
294% GetMagicInfoList() returns any image aliases that match the specified
295% pattern.
296%
297% The magic of the GetMagicInfoList function is:
298%
299% const MagicInfo **GetMagicInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000300% size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000301%
302% A description of each parameter follows:
303%
304% o pattern: Specifies a pointer to a text string containing a pattern.
305%
cristyfc0d1122009-10-17 20:22:37 +0000306% o number_aliases: This integer returns the number of aliases in the list.
cristy3ed852e2009-09-05 21:47:34 +0000307%
308% o exception: return any errors or warnings in this structure.
309%
310*/
311
312#if defined(__cplusplus) || defined(c_plusplus)
313extern "C" {
314#endif
315
316static int MagicInfoCompare(const void *x,const void *y)
317{
318 const MagicInfo
319 **p,
320 **q;
321
322 p=(const MagicInfo **) x,
323 q=(const MagicInfo **) y;
324 if (LocaleCompare((*p)->path,(*q)->path) == 0)
325 return(LocaleCompare((*p)->name,(*q)->name));
326 return(LocaleCompare((*p)->path,(*q)->path));
327}
328
329#if defined(__cplusplus) || defined(c_plusplus)
330}
331#endif
332
333MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000334 size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000335{
336 const MagicInfo
337 **aliases;
338
339 register const MagicInfo
340 *p;
341
cristybb503372010-05-27 20:51:26 +0000342 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000343 i;
344
345 /*
346 Allocate magic list.
347 */
348 assert(pattern != (char *) NULL);
349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000350 assert(number_aliases != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000351 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000352 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000353 if (p == (const MagicInfo *) NULL)
354 return((const MagicInfo **) NULL);
355 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
356 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
357 if (aliases == (const MagicInfo **) NULL)
358 return((const MagicInfo **) NULL);
359 /*
360 Generate magic list.
361 */
cristyf84a1932010-01-03 18:00:18 +0000362 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000363 ResetLinkedListIterator(magic_list);
364 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
365 for (i=0; p != (const MagicInfo *) NULL; )
366 {
367 if ((p->stealth == MagickFalse) &&
368 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
369 aliases[i++]=p;
370 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
371 }
cristyf84a1932010-01-03 18:00:18 +0000372 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000373 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
374 aliases[i]=(MagicInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000375 *number_aliases=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000376 return(aliases);
377}
378
379/*
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381% %
382% %
383% %
384% G e t M a g i c L i s t %
385% %
386% %
387% %
388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389%
390% GetMagicList() returns any image format aliases that match the specified
391% pattern.
392%
393% The format of the GetMagicList function is:
394%
cristybb503372010-05-27 20:51:26 +0000395% char **GetMagicList(const char *pattern,size_t *number_aliases,
cristy3ed852e2009-09-05 21:47:34 +0000396% ExceptionInfo *exception)
397%
398% A description of each parameter follows:
399%
400% o pattern: Specifies a pointer to a text string containing a pattern.
401%
402% o number_aliases: This integer returns the number of image format aliases
403% in the list.
404%
405% o exception: return any errors or warnings in this structure.
406%
407*/
408
409#if defined(__cplusplus) || defined(c_plusplus)
410extern "C" {
411#endif
412
413static int MagicCompare(const void *x,const void *y)
414{
415 register const char
416 *p,
417 *q;
418
419 p=(const char *) x;
420 q=(const char *) y;
421 return(LocaleCompare(p,q));
422}
423
424#if defined(__cplusplus) || defined(c_plusplus)
425}
426#endif
427
428MagickExport char **GetMagicList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000429 size_t *number_aliases,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000430{
431 char
432 **aliases;
433
434 register const MagicInfo
435 *p;
436
cristybb503372010-05-27 20:51:26 +0000437 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000438 i;
439
440 /*
441 Allocate configure list.
442 */
443 assert(pattern != (char *) NULL);
444 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000445 assert(number_aliases != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000446 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000447 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000448 if (p == (const MagicInfo *) NULL)
449 return((char **) NULL);
450 aliases=(char **) AcquireQuantumMemory((size_t)
451 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
452 if (aliases == (char **) NULL)
453 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000454 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000455 ResetLinkedListIterator(magic_list);
456 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
457 for (i=0; p != (const MagicInfo *) NULL; )
458 {
459 if ((p->stealth == MagickFalse) &&
460 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
461 aliases[i++]=ConstantString(p->name);
462 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
463 }
cristyf84a1932010-01-03 18:00:18 +0000464 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000465 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
466 aliases[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000467 *number_aliases=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000468 return(aliases);
469}
470
471/*
472%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
473% %
474% %
475% %
476% G e t M a g i c N a m e %
477% %
478% %
479% %
480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481%
482% GetMagicName() returns the name associated with the magic.
483%
484% The format of the GetMagicName method is:
485%
486% const char *GetMagicName(const MagicInfo *magic_info)
487%
488% A description of each parameter follows:
489%
490% o magic_info: The magic info.
491%
492*/
493MagickExport const char *GetMagicName(const MagicInfo *magic_info)
494{
495 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
496 assert(magic_info != (MagicInfo *) NULL);
497 assert(magic_info->signature == MagickSignature);
498 return(magic_info->name);
499}
500
501/*
502%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
503% %
504% %
505% %
506+ I n i t i a l i z e M a g i c L i s t %
507% %
508% %
509% %
510%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
511%
512% InitializeMagicList() initializes the magic list.
513%
514% The format of the InitializeMagicList method is:
515%
516% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
517%
518% A description of each parameter follows.
519%
520% o exception: return any errors or warnings in this structure.
521%
522*/
523static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
524{
525 if ((magic_list == (LinkedListInfo *) NULL) &&
526 (instantiate_magic == MagickFalse))
527 {
cristy4e1dff62009-10-25 20:36:03 +0000528 if (magic_semaphore == (SemaphoreInfo *) NULL)
529 AcquireSemaphoreInfo(&magic_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000530 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000531 if ((magic_list == (LinkedListInfo *) NULL) &&
532 (instantiate_magic == MagickFalse))
533 {
534 (void) LoadMagicLists(MagicFilename,exception);
535 instantiate_magic=MagickTrue;
536 }
cristyf84a1932010-01-03 18:00:18 +0000537 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000538 }
539 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
540}
541
542/*
543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544% %
545% %
546% %
547% L i s t M a g i c I n f o %
548% %
549% %
550% %
551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552%
553% ListMagicInfo() lists the magic info to a file.
554%
555% The format of the ListMagicInfo method is:
556%
557% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
558%
559% A description of each parameter follows.
560%
561% o file: An pointer to a FILE.
562%
563% o exception: return any errors or warnings in this structure.
564%
565*/
566MagickExport MagickBooleanType ListMagicInfo(FILE *file,
567 ExceptionInfo *exception)
568{
569 const char
570 *path;
571
572 const MagicInfo
573 **magic_info;
574
cristybb503372010-05-27 20:51:26 +0000575 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000576 j;
577
cristybb503372010-05-27 20:51:26 +0000578 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000579 i;
580
cristybb503372010-05-27 20:51:26 +0000581 size_t
cristy3ed852e2009-09-05 21:47:34 +0000582 number_aliases;
583
584 if (file == (const FILE *) NULL)
585 file=stdout;
586 magic_info=GetMagicInfoList("*",&number_aliases,exception);
587 if (magic_info == (const MagicInfo **) NULL)
588 return(MagickFalse);
589 j=0;
590 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +0000591 for (i=0; i < (ssize_t) number_aliases; i++)
cristy3ed852e2009-09-05 21:47:34 +0000592 {
593 if (magic_info[i]->stealth != MagickFalse)
594 continue;
595 if ((path == (const char *) NULL) ||
596 (LocaleCompare(path,magic_info[i]->path) != 0))
597 {
598 if (magic_info[i]->path != (char *) NULL)
599 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
600 (void) fprintf(file,"Name Offset Target\n");
601 (void) fprintf(file,"-------------------------------------------------"
602 "------------------------------\n");
603 }
604 path=magic_info[i]->path;
605 (void) fprintf(file,"%s",magic_info[i]->name);
cristybb503372010-05-27 20:51:26 +0000606 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
cristy3ed852e2009-09-05 21:47:34 +0000607 (void) fprintf(file," ");
cristybb503372010-05-27 20:51:26 +0000608 (void) fprintf(file,"%6ld ",(ssize_t) magic_info[i]->offset);
cristy3ed852e2009-09-05 21:47:34 +0000609 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000610 {
cristybb503372010-05-27 20:51:26 +0000611 register ssize_t
cristy1ca3eb32009-10-15 18:41:54 +0000612 j;
613
614 for (j=0; magic_info[i]->target[j] != '\0'; j++)
615 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
616 (void) fprintf(file,"%c",magic_info[i]->target[j]);
617 else
cristy50931922009-10-15 18:59:59 +0000618 (void) fprintf(file,"\\%03o",(unsigned int)
619 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000620 }
cristy3ed852e2009-09-05 21:47:34 +0000621 (void) fprintf(file,"\n");
622 }
623 (void) fflush(file);
624 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
625 return(MagickTrue);
626}
627
628/*
629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630% %
631% %
632% %
633+ L o a d M a g i c L i s t %
634% %
635% %
636% %
637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638%
639% LoadMagicList() loads the magic configuration file which provides a mapping
640% between magic attributes and a magic name.
641%
642% The format of the LoadMagicList method is:
643%
644% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000645% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000646%
647% A description of each parameter follows:
648%
cristy1ca3eb32009-10-15 18:41:54 +0000649% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000650%
cristy1ca3eb32009-10-15 18:41:54 +0000651% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000652%
653% o depth: depth of <include /> statements.
654%
655% o exception: return any errors or warnings in this structure.
656%
657*/
658static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +0000659 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000660{
661 char
662 keyword[MaxTextExtent],
663 *token;
664
665 const char
666 *q;
667
668 MagickBooleanType
669 status;
670
671 MagicInfo
672 *magic_info;
673
674 /*
675 Load the magic map file.
676 */
677 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
678 "Loading magic configure file \"%s\" ...",filename);
679 if (xml == (char *) NULL)
680 return(MagickFalse);
681 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000682 {
683 magic_list=NewLinkedList(0);
684 if (magic_list == (LinkedListInfo *) NULL)
685 {
686 ThrowFileException(exception,ResourceLimitError,
687 "MemoryAllocationFailed",filename);
688 return(MagickFalse);
689 }
690 }
cristy3ed852e2009-09-05 21:47:34 +0000691 status=MagickTrue;
692 magic_info=(MagicInfo *) NULL;
693 token=AcquireString(xml);
694 for (q=(char *) xml; *q != '\0'; )
695 {
696 /*
697 Interpret XML.
698 */
699 GetMagickToken(q,&q,token);
700 if (*token == '\0')
701 break;
702 (void) CopyMagickString(keyword,token,MaxTextExtent);
703 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
704 {
705 /*
706 Doctype element.
707 */
708 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
709 GetMagickToken(q,&q,token);
710 continue;
711 }
712 if (LocaleNCompare(keyword,"<!--",4) == 0)
713 {
714 /*
715 Comment element.
716 */
717 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
718 GetMagickToken(q,&q,token);
719 continue;
720 }
721 if (LocaleCompare(keyword,"<include") == 0)
722 {
723 /*
724 Include element.
725 */
726 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
727 {
728 (void) CopyMagickString(keyword,token,MaxTextExtent);
729 GetMagickToken(q,&q,token);
730 if (*token != '=')
731 continue;
732 GetMagickToken(q,&q,token);
733 if (LocaleCompare(keyword,"file") == 0)
734 {
735 if (depth > 200)
736 (void) ThrowMagickException(exception,GetMagickModule(),
737 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
738 else
739 {
740 char
741 path[MaxTextExtent],
742 *xml;
743
744 GetPathComponent(filename,HeadPath,path);
745 if (*path != '\0')
746 (void) ConcatenateMagickString(path,DirectorySeparator,
747 MaxTextExtent);
748 if (*token == *DirectorySeparator)
749 (void) CopyMagickString(path,token,MaxTextExtent);
750 else
751 (void) ConcatenateMagickString(path,token,MaxTextExtent);
752 xml=FileToString(path,~0,exception);
753 if (xml != (char *) NULL)
754 {
755 status=LoadMagicList(xml,path,depth+1,exception);
756 xml=(char *) RelinquishMagickMemory(xml);
757 }
758 }
759 }
760 }
761 continue;
762 }
763 if (LocaleCompare(keyword,"<magic") == 0)
764 {
765 /*
766 Magic element.
767 */
cristy90823212009-12-12 20:48:33 +0000768 magic_info=(MagicInfo *) AcquireAlignedMemory(1,sizeof(*magic_info));
cristy3ed852e2009-09-05 21:47:34 +0000769 if (magic_info == (MagicInfo *) NULL)
770 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
771 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
772 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000773 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000774 magic_info->signature=MagickSignature;
775 continue;
776 }
777 if (magic_info == (MagicInfo *) NULL)
778 continue;
779 if (LocaleCompare(keyword,"/>") == 0)
780 {
781 status=AppendValueToLinkedList(magic_list,magic_info);
782 if (status == MagickFalse)
783 (void) ThrowMagickException(exception,GetMagickModule(),
784 ResourceLimitError,"MemoryAllocationFailed","`%s'",
785 magic_info->name);
786 magic_info=(MagicInfo *) NULL;
787 }
788 GetMagickToken(q,(const char **) NULL,token);
789 if (*token != '=')
790 continue;
791 GetMagickToken(q,&q,token);
792 GetMagickToken(q,&q,token);
793 switch (*keyword)
794 {
795 case 'N':
796 case 'n':
797 {
798 if (LocaleCompare((char *) keyword,"name") == 0)
799 {
800 magic_info->name=ConstantString(token);
801 break;
802 }
803 break;
804 }
805 case 'O':
806 case 'o':
807 {
808 if (LocaleCompare((char *) keyword,"offset") == 0)
809 {
cristyf2f27272009-12-17 14:48:46 +0000810 magic_info->offset=(MagickOffsetType) StringToLong(token);
cristy3ed852e2009-09-05 21:47:34 +0000811 break;
812 }
813 break;
814 }
815 case 'S':
816 case 's':
817 {
818 if (LocaleCompare((char *) keyword,"stealth") == 0)
819 {
820 magic_info->stealth=IsMagickTrue(token);
821 break;
822 }
823 break;
824 }
825 case 'T':
826 case 't':
827 {
828 if (LocaleCompare((char *) keyword,"target") == 0)
829 {
830 char
831 *p;
832
833 register unsigned char
834 *q;
835
836 size_t
837 length;
838
839 length=strlen(token);
840 magic_info->target=ConstantString(token);
841 magic_info->magic=(unsigned char *) ConstantString(token);
842 q=magic_info->magic;
843 for (p=magic_info->target; *p != '\0'; )
844 {
845 if (*p == '\\')
846 {
847 p++;
848 if (isdigit((int) ((unsigned char) *p)) != 0)
849 {
850 char
851 *end;
852
853 *q++=(unsigned char) strtol(p,&end,8);
854 p+=(end-p);
855 magic_info->length++;
856 continue;
857 }
858 switch (*p)
859 {
860 case 'b': *q='\b'; break;
861 case 'f': *q='\f'; break;
862 case 'n': *q='\n'; break;
863 case 'r': *q='\r'; break;
864 case 't': *q='\t'; break;
865 case 'v': *q='\v'; break;
866 case 'a': *q='a'; break;
867 case '?': *q='\?'; break;
868 default: *q=(unsigned char) (*p); break;
869 }
870 p++;
871 q++;
872 magic_info->length++;
873 continue;
874 }
875 else
876 if (LocaleNCompare(p,"&amp;",5) == 0)
877 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
878 *q++=(unsigned char) (*p++);
879 magic_info->length++;
880 }
881 break;
882 }
883 break;
884 }
885 default:
886 break;
887 }
888 }
889 token=(char *) RelinquishMagickMemory(token);
890 return(status);
891}
892
893/*
894%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895% %
896% %
897% %
898% L o a d M a g i c L i s t s %
899% %
900% %
901% %
902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903%
904% LoadMagicLists() loads one or more magic configuration file which provides a
905% mapping between magic attributes and a magic name.
906%
907% The format of the LoadMagicLists method is:
908%
909% MagickBooleanType LoadMagicLists(const char *filename,
910% ExceptionInfo *exception)
911%
912% A description of each parameter follows:
913%
914% o filename: the font file name.
915%
916% o exception: return any errors or warnings in this structure.
917%
918*/
919static MagickBooleanType LoadMagicLists(const char *filename,
920 ExceptionInfo *exception)
921{
cristy3ed852e2009-09-05 21:47:34 +0000922 char
923 path[MaxTextExtent];
924
925 const StringInfo
926 *option;
927
928 LinkedListInfo
929 *options;
930
931 MagickStatusType
932 status;
933
cristybb503372010-05-27 20:51:26 +0000934 register ssize_t
cristy54a531d2009-10-21 17:58:01 +0000935 i;
cristy1ca3eb32009-10-15 18:41:54 +0000936
937 /*
938 Load built-in magic map.
939 */
cristy3ed852e2009-09-05 21:47:34 +0000940 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +0000941 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000942 {
943 magic_list=NewLinkedList(0);
944 if (magic_list == (LinkedListInfo *) NULL)
945 {
946 ThrowFileException(exception,ResourceLimitError,
947 "MemoryAllocationFailed",filename);
948 return(MagickFalse);
949 }
950 }
cristybb503372010-05-27 20:51:26 +0000951 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
cristy1ca3eb32009-10-15 18:41:54 +0000952 {
953 MagicInfo
954 *magic_info;
955
cristy54a531d2009-10-21 17:58:01 +0000956 register const MagicMapInfo
957 *p;
958
959 p=MagicMap+i;
cristy90823212009-12-12 20:48:33 +0000960 magic_info=(MagicInfo *) AcquireAlignedMemory(1,sizeof(*magic_info));
cristy1ca3eb32009-10-15 18:41:54 +0000961 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000962 {
963 (void) ThrowMagickException(exception,GetMagickModule(),
964 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
965 continue;
966 }
cristy1ca3eb32009-10-15 18:41:54 +0000967 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
cristy38b8ed92009-10-16 01:20:21 +0000968 magic_info->path=(char *) "[built-in]";
cristy1ca3eb32009-10-15 18:41:54 +0000969 magic_info->name=(char *) p->name;
970 magic_info->offset=p->offset;
971 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +0000972 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +0000973 magic_info->length=p->length;
974 magic_info->exempt=MagickTrue;
975 magic_info->signature=MagickSignature;
976 status=AppendValueToLinkedList(magic_list,magic_info);
977 if (status == MagickFalse)
978 (void) ThrowMagickException(exception,GetMagickModule(),
979 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
980 }
981 /*
982 Load external magic map.
983 */
cristy3ed852e2009-09-05 21:47:34 +0000984 *path='\0';
985 options=GetConfigureOptions(filename,exception);
986 option=(const StringInfo *) GetNextValueInLinkedList(options);
987 while (option != (const StringInfo *) NULL)
988 {
989 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
990 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
991 GetStringInfoPath(option),0,exception);
992 option=(const StringInfo *) GetNextValueInLinkedList(options);
993 }
994 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +0000995 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000996}
cristyf34a1452009-10-24 22:29:27 +0000997
998/*
999%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000% %
1001% %
1002% %
1003+ M a g i c C o m p o n e n t G e n e s i s %
1004% %
1005% %
1006% %
1007%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1008%
1009% MagicComponentGenesis() instantiates the magic component.
1010%
1011% The format of the MagicComponentGenesis method is:
1012%
1013% MagickBooleanType MagicComponentGenesis(void)
1014%
1015*/
1016MagickExport MagickBooleanType MagicComponentGenesis(void)
1017{
cristy165b6092009-10-26 13:52:10 +00001018 AcquireSemaphoreInfo(&magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001019 return(MagickTrue);
1020}
1021
1022/*
1023%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024% %
1025% %
1026% %
1027+ M a g i c C o m p o n e n t T e r m i n u s %
1028% %
1029% %
1030% %
1031%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032%
1033% MagicComponentTerminus() destroys the magic component.
1034%
1035% The format of the MagicComponentTerminus method is:
1036%
1037% MagicComponentTerminus(void)
1038%
1039*/
1040
1041static void *DestroyMagicElement(void *magic_info)
1042{
1043 register MagicInfo
1044 *p;
1045
1046 p=(MagicInfo *) magic_info;
1047 if (p->exempt == MagickFalse)
1048 {
1049 if (p->path != (char *) NULL)
1050 p->path=DestroyString(p->path);
1051 if (p->name != (char *) NULL)
1052 p->name=DestroyString(p->name);
1053 if (p->target != (char *) NULL)
1054 p->target=DestroyString(p->target);
1055 if (p->magic != (unsigned char *) NULL)
1056 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1057 }
1058 p=(MagicInfo *) RelinquishMagickMemory(p);
1059 return((void *) NULL);
1060}
1061
1062MagickExport void MagicComponentTerminus(void)
1063{
cristy18b17442009-10-25 18:36:48 +00001064 if (magic_semaphore == (SemaphoreInfo *) NULL)
1065 AcquireSemaphoreInfo(&magic_semaphore);
cristyf84a1932010-01-03 18:00:18 +00001066 LockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001067 if (magic_list != (LinkedListInfo *) NULL)
1068 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
1069 instantiate_magic=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001070 UnlockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001071 DestroySemaphoreInfo(&magic_semaphore);
1072}