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