blob: d5bd5f32b07c1b2a8ed4be82c20f112bad17985c [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% %
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%
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"
52#include "magick/token.h"
53#include "magick/utility.h"
54#include "magick/xml-tree.h"
55
56/*
57 Define declarations.
58*/
59#define MagicFilename "magic.xml"
60
61/*
62 Static declarations.
63*/
cristy1ca3eb32009-10-15 18:41:54 +000064typedef struct _MagicMapInfo
65{
66 const char
67 *name;
68
cristye3e77a12009-10-16 00:47:21 +000069 const MagickOffsetType
70 offset;
71
cristybcdce3d2009-10-15 20:04:49 +000072 const unsigned char
cristy1ca3eb32009-10-15 18:41:54 +000073 *magic;
74
cristye3e77a12009-10-16 00:47:21 +000075 const size_t
cristy1ca3eb32009-10-15 18:41:54 +000076 length;
cristy1ca3eb32009-10-15 18:41:54 +000077} MagicMapInfo;
78
cristye3e77a12009-10-16 00:47:21 +000079#define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
cristy1ca3eb32009-10-15 18:41:54 +000080
81static const MagicMapInfo
82 MagicMap[] =
83 {
cristye3e77a12009-10-16 00:47:21 +000084 { "AVI", 0, MagickString("RIFF") },
85 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
86 { "8BIMTEXT", 0, MagickString("8BIM#") },
87 { "8BIM", 0, MagickString("8BIM") },
88 { "BMP", 0, MagickString("BA") },
89 { "BMP", 0, MagickString("BM") },
90 { "BMP", 0, MagickString("CI") },
91 { "BMP", 0, MagickString("CP") },
92 { "BMP", 0, MagickString("IC") },
93 { "BMP", 0, MagickString("PI") },
94 { "CALS", 21, MagickString("version: MIL-STD-1840") },
95 { "CALS", 0, MagickString("srcdocid:") },
96 { "CALS", 9, MagickString("srcdocid:") },
97 { "CALS", 8, MagickString("rorient:") },
98 { "CGM", 0, MagickString("BEGMF") },
99 { "CIN", 0, MagickString("\200\052\137\327") },
100 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
101 { "DCM", 128, MagickString("DICM") },
102 { "DCX", 0, MagickString("\261\150\336\72") },
103 { "DIB", 0, MagickString("\050\000") },
104 { "DDS", 0, MagickString("DDS ") },
105 { "DJVU", 0, MagickString("AT&TFORM") },
106 { "DOT", 0, MagickString("digraph") },
107 { "DPX", 0, MagickString("SDPX") },
108 { "DPX", 0, MagickString("XPDS") },
109 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
110 { "EPT", 0, MagickString("\305\320\323\306") },
111 { "EXR", 0, MagickString("\166\057\061\001") },
112 { "FAX", 0, MagickString("DFAX") },
113 { "FIG", 0, MagickString("#FIG") },
114 { "FITS", 0, MagickString("IT0") },
115 { "FITS", 0, MagickString("SIMPLE") },
116 { "FPX", 0, MagickString("\320\317\021\340") },
117 { "GIF", 0, MagickString("GIF8") },
118 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
119 { "HDF", 1, MagickString("HDF") },
120 { "HPGL", 0, MagickString("IN;") },
121 { "HPGL", 0, MagickString("\033E\033") },
122 { "HTML", 1, MagickString("HTML") },
123 { "HTML", 1, MagickString("html") },
124 { "ILBM", 8, MagickString("ILBM") },
125 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
126 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
127 { "IPTC", 0, MagickString("\034\002") },
128 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
129 { "JPEG", 0, MagickString("\377\330\377") },
130 { "JPC", 0, MagickString("\377\117") },
131 { "JP2", 4, MagickString("\152\120\040\040\015") },
132 { "MIFF", 0, MagickString("Id=ImageMagick") },
133 { "MIFF", 0, MagickString("id=ImageMagick") },
134 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
135 { "MPC", 0, MagickString("id=MagickCache") },
136 { "MPEG", 0, MagickString("\000\000\001\263") },
137 { "MRW", 0, MagickString("\x00MRM") },
138 { "MVG", 0, MagickString("push graphic-context") },
139 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
140 { "PCD", 2048, MagickString("PCD_") },
141 { "PCL", 0, MagickString("\033E\033") },
142 { "PCX", 0, MagickString("\012\002") },
143 { "PCX", 0, MagickString("\012\005") },
144 { "PDB", 60, MagickString("vIMGView") },
145 { "PDF", 0, MagickString("%PDF-") },
146 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
147 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
148 { "PGX", 0, MagickString("\050\107\020\115\046") },
149 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
150 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
151 { "PNM", 0, MagickString("P1") },
152 { "PNM", 0, MagickString("P2") },
153 { "PNM", 0, MagickString("P3") },
154 { "PNM", 0, MagickString("P4") },
155 { "PNM", 0, MagickString("P5") },
156 { "PNM", 0, MagickString("P6") },
157 { "PNM", 0, MagickString("P7") },
158 { "PNM", 0, MagickString("PF") },
159 { "PNM", 0, MagickString("Pf") },
160 { "PS", 0, MagickString("%!") },
161 { "PS", 0, MagickString("\004%!") },
162 { "PS", 0, MagickString("\305\320\323\306") },
163 { "PSD", 0, MagickString("8BPS") },
164 { "PWP", 0, MagickString("SFW95") },
165 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
166 { "RAD", 0, MagickString("#?RADIANCE") },
167 { "RAD", 0, MagickString("VIEW= ") },
168 { "RLE", 0, MagickString("\122\314") },
169 { "SCT", 0, MagickString("CT") },
170 { "SFW", 0, MagickString("SFW94") },
171 { "SGI", 0, MagickString("\001\332") },
172 { "SUN", 0, MagickString("\131\246\152\225") },
173 { "SVG", 1, MagickString("?XML") },
174 { "SVG", 1, MagickString("?xml") },
175 { "TIFF", 0, MagickString("\115\115\000\052") },
176 { "TIFF", 0, MagickString("\111\111\052\000") },
177 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
178 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
179 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
180 { "VICAR", 0, MagickString("LBLSIZE") },
181 { "VICAR", 0, MagickString("NJPL1I") },
182 { "VIFF", 0, MagickString("\253\001") },
183 { "WMF", 0, MagickString("\327\315\306\232") },
184 { "WMF", 0, MagickString("\001\000\011\000") },
185 { "WPG", 0, MagickString("\377WPC") },
186 { "XBM", 0, MagickString("#define") },
187 { "XCF", 0, MagickString("gimp xcf") },
188 { "XEF", 0, MagickString("FOVb") },
189 { "XPM", 1, MagickString("* XPM *") },
190 { "XWD", 4, MagickString("\007\000\000") },
191 { "XWD", 5, MagickString("\000\000\007") },
192 { (const char *) NULL, 0, MagickString((const char *) NULL) }
cristy1ca3eb32009-10-15 18:41:54 +0000193 };
cristy3ed852e2009-09-05 21:47:34 +0000194
195static LinkedListInfo
196 *magic_list = (LinkedListInfo *) NULL;
197
198static SemaphoreInfo
199 *magic_semaphore = (SemaphoreInfo *) NULL;
200
201static volatile MagickBooleanType
202 instantiate_magic = MagickFalse;
203
204/*
205 Forward declarations.
206*/
207static MagickBooleanType
208 InitializeMagicList(ExceptionInfo *),
209 LoadMagicLists(const char *,ExceptionInfo *);
210
211/*
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213% %
214% %
215% %
cristydf1cc5f2009-10-19 16:02:33 +0000216+ D e s t r o y M a g i c C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000217% %
218% %
219% %
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221%
cristydf1cc5f2009-10-19 16:02:33 +0000222% DestroyMagicComponent() destroys the magic component.
cristy3ed852e2009-09-05 21:47:34 +0000223%
cristydf1cc5f2009-10-19 16:02:33 +0000224% The format of the DestroyMagicComponent method is:
cristy3ed852e2009-09-05 21:47:34 +0000225%
cristydf1cc5f2009-10-19 16:02:33 +0000226% DestroyMagicComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000227%
228*/
229
230static void *DestroyMagicElement(void *magic_info)
231{
232 register MagicInfo
233 *p;
234
235 p=(MagicInfo *) magic_info;
cristy1ca3eb32009-10-15 18:41:54 +0000236 if (p->exempt == MagickFalse)
237 {
238 if (p->path != (char *) NULL)
239 p->path=DestroyString(p->path);
240 if (p->name != (char *) NULL)
241 p->name=DestroyString(p->name);
242 if (p->target != (char *) NULL)
243 p->target=DestroyString(p->target);
244 if (p->magic != (unsigned char *) NULL)
245 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
246 }
cristy3ed852e2009-09-05 21:47:34 +0000247 p=(MagicInfo *) RelinquishMagickMemory(p);
248 return((void *) NULL);
249}
250
cristydf1cc5f2009-10-19 16:02:33 +0000251MagickExport void DestroyMagicComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000252{
253 AcquireSemaphoreInfo(&magic_semaphore);
254 if (magic_list != (LinkedListInfo *) NULL)
255 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
256 instantiate_magic=MagickFalse;
257 RelinquishSemaphoreInfo(magic_semaphore);
258 DestroySemaphoreInfo(&magic_semaphore);
259}
260
261/*
262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263% %
264% %
265% %
266+ G e t M a g i c I n f o %
267% %
268% %
269% %
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271%
272% GetMagicInfo() searches the magic list for the specified name and if found
273% returns attributes for that magic.
274%
275% The format of the GetMagicInfo method is:
276%
277% const MagicInfo *GetMagicInfo(const unsigned char *magic,
278% const size_t length,ExceptionInfo *exception)
279%
280% A description of each parameter follows:
281%
282% o magic: A binary string generally representing the first few characters
283% of the image file or blob.
284%
285% o length: the length of the binary signature.
286%
287% o exception: return any errors or warnings in this structure.
288%
289*/
290MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
291 const size_t length,ExceptionInfo *exception)
292{
293 register const MagicInfo
294 *p;
295
296 assert(exception != (ExceptionInfo *) NULL);
297 if ((magic_list == (LinkedListInfo *) NULL) ||
298 (instantiate_magic == MagickFalse))
299 if (InitializeMagicList(exception) == MagickFalse)
300 return((const MagicInfo *) NULL);
301 if ((magic_list == (LinkedListInfo *) NULL) ||
302 (IsLinkedListEmpty(magic_list) != MagickFalse))
303 return((const MagicInfo *) NULL);
304 if (magic == (const unsigned char *) NULL)
305 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
306 if (length == 0)
307 return((const MagicInfo *) NULL);
308 /*
309 Search for magic tag.
310 */
311 AcquireSemaphoreInfo(&magic_semaphore);
312 ResetLinkedListIterator(magic_list);
313 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
314 while (p != (const MagicInfo *) NULL)
315 {
316 assert(p->offset >= 0);
317 if (((size_t) (p->offset+p->length) <= length) &&
318 (memcmp(magic+p->offset,p->magic,p->length) == 0))
319 break;
320 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
321 }
322 if (p != (const MagicInfo *) NULL)
323 (void) InsertValueInLinkedList(magic_list,0,
324 RemoveElementByValueFromLinkedList(magic_list,p));
325 RelinquishSemaphoreInfo(magic_semaphore);
326 return(p);
327}
328
329/*
330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331% %
332% %
333% %
334% G e t M a g i c I n f o L i s t %
335% %
336% %
337% %
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339%
340% GetMagicInfoList() returns any image aliases that match the specified
341% pattern.
342%
343% The magic of the GetMagicInfoList function is:
344%
345% const MagicInfo **GetMagicInfoList(const char *pattern,
346% unsigned long *number_aliases,ExceptionInfo *exception)
347%
348% A description of each parameter follows:
349%
350% o pattern: Specifies a pointer to a text string containing a pattern.
351%
cristyfc0d1122009-10-17 20:22:37 +0000352% o number_aliases: This integer returns the number of aliases in the list.
cristy3ed852e2009-09-05 21:47:34 +0000353%
354% o exception: return any errors or warnings in this structure.
355%
356*/
357
358#if defined(__cplusplus) || defined(c_plusplus)
359extern "C" {
360#endif
361
362static int MagicInfoCompare(const void *x,const void *y)
363{
364 const MagicInfo
365 **p,
366 **q;
367
368 p=(const MagicInfo **) x,
369 q=(const MagicInfo **) y;
370 if (LocaleCompare((*p)->path,(*q)->path) == 0)
371 return(LocaleCompare((*p)->name,(*q)->name));
372 return(LocaleCompare((*p)->path,(*q)->path));
373}
374
375#if defined(__cplusplus) || defined(c_plusplus)
376}
377#endif
378
379MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
380 unsigned long *number_aliases,ExceptionInfo *exception)
381{
382 const MagicInfo
383 **aliases;
384
385 register const MagicInfo
386 *p;
387
388 register long
389 i;
390
391 /*
392 Allocate magic list.
393 */
394 assert(pattern != (char *) NULL);
395 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
396 assert(number_aliases != (unsigned long *) NULL);
397 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000398 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000399 if (p == (const MagicInfo *) NULL)
400 return((const MagicInfo **) NULL);
401 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
402 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
403 if (aliases == (const MagicInfo **) NULL)
404 return((const MagicInfo **) NULL);
405 /*
406 Generate magic list.
407 */
408 AcquireSemaphoreInfo(&magic_semaphore);
409 ResetLinkedListIterator(magic_list);
410 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
411 for (i=0; p != (const MagicInfo *) NULL; )
412 {
413 if ((p->stealth == MagickFalse) &&
414 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
415 aliases[i++]=p;
416 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
417 }
418 RelinquishSemaphoreInfo(magic_semaphore);
419 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
420 aliases[i]=(MagicInfo *) NULL;
421 *number_aliases=(unsigned long) i;
422 return(aliases);
423}
424
425/*
426%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427% %
428% %
429% %
430% G e t M a g i c L i s t %
431% %
432% %
433% %
434%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435%
436% GetMagicList() returns any image format aliases that match the specified
437% pattern.
438%
439% The format of the GetMagicList function is:
440%
441% char **GetMagicList(const char *pattern,unsigned long *number_aliases,
442% ExceptionInfo *exception)
443%
444% A description of each parameter follows:
445%
446% o pattern: Specifies a pointer to a text string containing a pattern.
447%
448% o number_aliases: This integer returns the number of image format aliases
449% in the list.
450%
451% o exception: return any errors or warnings in this structure.
452%
453*/
454
455#if defined(__cplusplus) || defined(c_plusplus)
456extern "C" {
457#endif
458
459static int MagicCompare(const void *x,const void *y)
460{
461 register const char
462 *p,
463 *q;
464
465 p=(const char *) x;
466 q=(const char *) y;
467 return(LocaleCompare(p,q));
468}
469
470#if defined(__cplusplus) || defined(c_plusplus)
471}
472#endif
473
474MagickExport char **GetMagicList(const char *pattern,
475 unsigned long *number_aliases,ExceptionInfo *exception)
476{
477 char
478 **aliases;
479
480 register const MagicInfo
481 *p;
482
483 register long
484 i;
485
486 /*
487 Allocate configure list.
488 */
489 assert(pattern != (char *) NULL);
490 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
491 assert(number_aliases != (unsigned long *) NULL);
492 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000493 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000494 if (p == (const MagicInfo *) NULL)
495 return((char **) NULL);
496 aliases=(char **) AcquireQuantumMemory((size_t)
497 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
498 if (aliases == (char **) NULL)
499 return((char **) NULL);
500 AcquireSemaphoreInfo(&magic_semaphore);
501 ResetLinkedListIterator(magic_list);
502 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
503 for (i=0; p != (const MagicInfo *) NULL; )
504 {
505 if ((p->stealth == MagickFalse) &&
506 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
507 aliases[i++]=ConstantString(p->name);
508 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
509 }
510 RelinquishSemaphoreInfo(magic_semaphore);
511 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
512 aliases[i]=(char *) NULL;
513 *number_aliases=(unsigned long) i;
514 return(aliases);
515}
516
517/*
518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519% %
520% %
521% %
522% G e t M a g i c N a m e %
523% %
524% %
525% %
526%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527%
528% GetMagicName() returns the name associated with the magic.
529%
530% The format of the GetMagicName method is:
531%
532% const char *GetMagicName(const MagicInfo *magic_info)
533%
534% A description of each parameter follows:
535%
536% o magic_info: The magic info.
537%
538*/
539MagickExport const char *GetMagicName(const MagicInfo *magic_info)
540{
541 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
542 assert(magic_info != (MagicInfo *) NULL);
543 assert(magic_info->signature == MagickSignature);
544 return(magic_info->name);
545}
546
547/*
548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549% %
550% %
551% %
552+ I n i t i a l i z e M a g i c L i s t %
553% %
554% %
555% %
556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557%
558% InitializeMagicList() initializes the magic list.
559%
560% The format of the InitializeMagicList method is:
561%
562% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
563%
564% A description of each parameter follows.
565%
566% o exception: return any errors or warnings in this structure.
567%
568*/
569static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
570{
571 if ((magic_list == (LinkedListInfo *) NULL) &&
572 (instantiate_magic == MagickFalse))
573 {
574 AcquireSemaphoreInfo(&magic_semaphore);
575 if ((magic_list == (LinkedListInfo *) NULL) &&
576 (instantiate_magic == MagickFalse))
577 {
578 (void) LoadMagicLists(MagicFilename,exception);
579 instantiate_magic=MagickTrue;
580 }
581 RelinquishSemaphoreInfo(magic_semaphore);
582 }
583 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
584}
585
586/*
587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588% %
589% %
590% %
cristydf1cc5f2009-10-19 16:02:33 +0000591+ I n s t a n t i a t e M a g i c C o m p o n e n t %
cristy41c3c772009-10-19 02:17:37 +0000592% %
593% %
594% %
595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596%
cristydf1cc5f2009-10-19 16:02:33 +0000597% InstantiateMagicComponent() instantiates the magic component.
cristy41c3c772009-10-19 02:17:37 +0000598%
cristydf1cc5f2009-10-19 16:02:33 +0000599% The format of the InstantiateMagicComponent method is:
cristy41c3c772009-10-19 02:17:37 +0000600%
cristydf1cc5f2009-10-19 16:02:33 +0000601% MagickBooleanType InstantiateMagicComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000602%
603*/
cristydf1cc5f2009-10-19 16:02:33 +0000604MagickExport MagickBooleanType InstantiateMagicComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000605{
606 AcquireSemaphoreInfo(&magic_semaphore);
607 RelinquishSemaphoreInfo(magic_semaphore);
608 return(MagickTrue);
609}
610
611/*
612%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613% %
614% %
615% %
cristy3ed852e2009-09-05 21:47:34 +0000616% L i s t M a g i c I n f o %
617% %
618% %
619% %
620%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621%
622% ListMagicInfo() lists the magic info to a file.
623%
624% The format of the ListMagicInfo method is:
625%
626% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
627%
628% A description of each parameter follows.
629%
630% o file: An pointer to a FILE.
631%
632% o exception: return any errors or warnings in this structure.
633%
634*/
635MagickExport MagickBooleanType ListMagicInfo(FILE *file,
636 ExceptionInfo *exception)
637{
638 const char
639 *path;
640
641 const MagicInfo
642 **magic_info;
643
644 long
645 j;
646
647 register long
648 i;
649
650 unsigned long
651 number_aliases;
652
653 if (file == (const FILE *) NULL)
654 file=stdout;
655 magic_info=GetMagicInfoList("*",&number_aliases,exception);
656 if (magic_info == (const MagicInfo **) NULL)
657 return(MagickFalse);
658 j=0;
659 path=(const char *) NULL;
660 for (i=0; i < (long) number_aliases; i++)
661 {
662 if (magic_info[i]->stealth != MagickFalse)
663 continue;
664 if ((path == (const char *) NULL) ||
665 (LocaleCompare(path,magic_info[i]->path) != 0))
666 {
667 if (magic_info[i]->path != (char *) NULL)
668 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
669 (void) fprintf(file,"Name Offset Target\n");
670 (void) fprintf(file,"-------------------------------------------------"
671 "------------------------------\n");
672 }
673 path=magic_info[i]->path;
674 (void) fprintf(file,"%s",magic_info[i]->name);
675 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
676 (void) fprintf(file," ");
677 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
678 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000679 {
680 register long
681 j;
682
683 for (j=0; magic_info[i]->target[j] != '\0'; j++)
684 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
685 (void) fprintf(file,"%c",magic_info[i]->target[j]);
686 else
cristy50931922009-10-15 18:59:59 +0000687 (void) fprintf(file,"\\%03o",(unsigned int)
688 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000689 }
cristy3ed852e2009-09-05 21:47:34 +0000690 (void) fprintf(file,"\n");
691 }
692 (void) fflush(file);
693 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
694 return(MagickTrue);
695}
696
697/*
698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699% %
700% %
701% %
702+ L o a d M a g i c L i s t %
703% %
704% %
705% %
706%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707%
708% LoadMagicList() loads the magic configuration file which provides a mapping
709% between magic attributes and a magic name.
710%
711% The format of the LoadMagicList method is:
712%
713% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
714% const unsigned long depth,ExceptionInfo *exception)
715%
716% A description of each parameter follows:
717%
cristy1ca3eb32009-10-15 18:41:54 +0000718% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000719%
cristy1ca3eb32009-10-15 18:41:54 +0000720% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000721%
722% o depth: depth of <include /> statements.
723%
724% o exception: return any errors or warnings in this structure.
725%
726*/
727static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
728 const unsigned long depth,ExceptionInfo *exception)
729{
730 char
731 keyword[MaxTextExtent],
732 *token;
733
734 const char
735 *q;
736
737 MagickBooleanType
738 status;
739
740 MagicInfo
741 *magic_info;
742
743 /*
744 Load the magic map file.
745 */
746 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
747 "Loading magic configure file \"%s\" ...",filename);
748 if (xml == (char *) NULL)
749 return(MagickFalse);
750 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000751 {
752 magic_list=NewLinkedList(0);
753 if (magic_list == (LinkedListInfo *) NULL)
754 {
755 ThrowFileException(exception,ResourceLimitError,
756 "MemoryAllocationFailed",filename);
757 return(MagickFalse);
758 }
759 }
cristy3ed852e2009-09-05 21:47:34 +0000760 status=MagickTrue;
761 magic_info=(MagicInfo *) NULL;
762 token=AcquireString(xml);
763 for (q=(char *) xml; *q != '\0'; )
764 {
765 /*
766 Interpret XML.
767 */
768 GetMagickToken(q,&q,token);
769 if (*token == '\0')
770 break;
771 (void) CopyMagickString(keyword,token,MaxTextExtent);
772 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
773 {
774 /*
775 Doctype element.
776 */
777 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
778 GetMagickToken(q,&q,token);
779 continue;
780 }
781 if (LocaleNCompare(keyword,"<!--",4) == 0)
782 {
783 /*
784 Comment element.
785 */
786 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
787 GetMagickToken(q,&q,token);
788 continue;
789 }
790 if (LocaleCompare(keyword,"<include") == 0)
791 {
792 /*
793 Include element.
794 */
795 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
796 {
797 (void) CopyMagickString(keyword,token,MaxTextExtent);
798 GetMagickToken(q,&q,token);
799 if (*token != '=')
800 continue;
801 GetMagickToken(q,&q,token);
802 if (LocaleCompare(keyword,"file") == 0)
803 {
804 if (depth > 200)
805 (void) ThrowMagickException(exception,GetMagickModule(),
806 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
807 else
808 {
809 char
810 path[MaxTextExtent],
811 *xml;
812
813 GetPathComponent(filename,HeadPath,path);
814 if (*path != '\0')
815 (void) ConcatenateMagickString(path,DirectorySeparator,
816 MaxTextExtent);
817 if (*token == *DirectorySeparator)
818 (void) CopyMagickString(path,token,MaxTextExtent);
819 else
820 (void) ConcatenateMagickString(path,token,MaxTextExtent);
821 xml=FileToString(path,~0,exception);
822 if (xml != (char *) NULL)
823 {
824 status=LoadMagicList(xml,path,depth+1,exception);
825 xml=(char *) RelinquishMagickMemory(xml);
826 }
827 }
828 }
829 }
830 continue;
831 }
832 if (LocaleCompare(keyword,"<magic") == 0)
833 {
834 /*
835 Magic element.
836 */
837 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
838 if (magic_info == (MagicInfo *) NULL)
839 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
840 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
841 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000842 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000843 magic_info->signature=MagickSignature;
844 continue;
845 }
846 if (magic_info == (MagicInfo *) NULL)
847 continue;
848 if (LocaleCompare(keyword,"/>") == 0)
849 {
850 status=AppendValueToLinkedList(magic_list,magic_info);
851 if (status == MagickFalse)
852 (void) ThrowMagickException(exception,GetMagickModule(),
853 ResourceLimitError,"MemoryAllocationFailed","`%s'",
854 magic_info->name);
855 magic_info=(MagicInfo *) NULL;
856 }
857 GetMagickToken(q,(const char **) NULL,token);
858 if (*token != '=')
859 continue;
860 GetMagickToken(q,&q,token);
861 GetMagickToken(q,&q,token);
862 switch (*keyword)
863 {
864 case 'N':
865 case 'n':
866 {
867 if (LocaleCompare((char *) keyword,"name") == 0)
868 {
869 magic_info->name=ConstantString(token);
870 break;
871 }
872 break;
873 }
874 case 'O':
875 case 'o':
876 {
877 if (LocaleCompare((char *) keyword,"offset") == 0)
878 {
879 magic_info->offset=(MagickOffsetType) atol(token);
880 break;
881 }
882 break;
883 }
884 case 'S':
885 case 's':
886 {
887 if (LocaleCompare((char *) keyword,"stealth") == 0)
888 {
889 magic_info->stealth=IsMagickTrue(token);
890 break;
891 }
892 break;
893 }
894 case 'T':
895 case 't':
896 {
897 if (LocaleCompare((char *) keyword,"target") == 0)
898 {
899 char
900 *p;
901
902 register unsigned char
903 *q;
904
905 size_t
906 length;
907
908 length=strlen(token);
909 magic_info->target=ConstantString(token);
910 magic_info->magic=(unsigned char *) ConstantString(token);
911 q=magic_info->magic;
912 for (p=magic_info->target; *p != '\0'; )
913 {
914 if (*p == '\\')
915 {
916 p++;
917 if (isdigit((int) ((unsigned char) *p)) != 0)
918 {
919 char
920 *end;
921
922 *q++=(unsigned char) strtol(p,&end,8);
923 p+=(end-p);
924 magic_info->length++;
925 continue;
926 }
927 switch (*p)
928 {
929 case 'b': *q='\b'; break;
930 case 'f': *q='\f'; break;
931 case 'n': *q='\n'; break;
932 case 'r': *q='\r'; break;
933 case 't': *q='\t'; break;
934 case 'v': *q='\v'; break;
935 case 'a': *q='a'; break;
936 case '?': *q='\?'; break;
937 default: *q=(unsigned char) (*p); break;
938 }
939 p++;
940 q++;
941 magic_info->length++;
942 continue;
943 }
944 else
945 if (LocaleNCompare(p,"&amp;",5) == 0)
946 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
947 *q++=(unsigned char) (*p++);
948 magic_info->length++;
949 }
950 break;
951 }
952 break;
953 }
954 default:
955 break;
956 }
957 }
958 token=(char *) RelinquishMagickMemory(token);
959 return(status);
960}
961
962/*
963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964% %
965% %
966% %
967% L o a d M a g i c L i s t s %
968% %
969% %
970% %
971%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972%
973% LoadMagicLists() loads one or more magic configuration file which provides a
974% mapping between magic attributes and a magic name.
975%
976% The format of the LoadMagicLists method is:
977%
978% MagickBooleanType LoadMagicLists(const char *filename,
979% ExceptionInfo *exception)
980%
981% A description of each parameter follows:
982%
983% o filename: the font file name.
984%
985% o exception: return any errors or warnings in this structure.
986%
987*/
988static MagickBooleanType LoadMagicLists(const char *filename,
989 ExceptionInfo *exception)
990{
cristy3ed852e2009-09-05 21:47:34 +0000991 char
992 path[MaxTextExtent];
993
994 const StringInfo
995 *option;
996
997 LinkedListInfo
998 *options;
999
1000 MagickStatusType
1001 status;
1002
cristy1ca3eb32009-10-15 18:41:54 +00001003 register const MagicMapInfo
1004 *p;
1005
1006 /*
1007 Load built-in magic map.
1008 */
cristy3ed852e2009-09-05 21:47:34 +00001009 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +00001010 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +00001011 {
1012 magic_list=NewLinkedList(0);
1013 if (magic_list == (LinkedListInfo *) NULL)
1014 {
1015 ThrowFileException(exception,ResourceLimitError,
1016 "MemoryAllocationFailed",filename);
1017 return(MagickFalse);
1018 }
1019 }
cristy1ca3eb32009-10-15 18:41:54 +00001020 for (p=MagicMap; p->name != (const char *) NULL; p++)
1021 {
1022 MagicInfo
1023 *magic_info;
1024
1025 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
1026 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +00001027 {
1028 (void) ThrowMagickException(exception,GetMagickModule(),
1029 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1030 continue;
1031 }
cristy1ca3eb32009-10-15 18:41:54 +00001032 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
cristy38b8ed92009-10-16 01:20:21 +00001033 magic_info->path=(char *) "[built-in]";
cristy1ca3eb32009-10-15 18:41:54 +00001034 magic_info->name=(char *) p->name;
1035 magic_info->offset=p->offset;
1036 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +00001037 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +00001038 magic_info->length=p->length;
1039 magic_info->exempt=MagickTrue;
1040 magic_info->signature=MagickSignature;
1041 status=AppendValueToLinkedList(magic_list,magic_info);
1042 if (status == MagickFalse)
1043 (void) ThrowMagickException(exception,GetMagickModule(),
1044 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1045 }
1046 /*
1047 Load external magic map.
1048 */
cristy3ed852e2009-09-05 21:47:34 +00001049 *path='\0';
1050 options=GetConfigureOptions(filename,exception);
1051 option=(const StringInfo *) GetNextValueInLinkedList(options);
1052 while (option != (const StringInfo *) NULL)
1053 {
1054 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1055 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
1056 GetStringInfoPath(option),0,exception);
1057 option=(const StringInfo *) GetNextValueInLinkedList(options);
1058 }
1059 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001060 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001061}