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