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