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