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