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