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