]> 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-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 MagickString(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, MagickString("8\000B\000I\000M\000#") },
93     { "8BIMTEXT", 0, MagickString("8BIM#") },
94     { "8BIM", 0, MagickString("8BIM") },
95     { "BMP", 0, MagickString("BA") },
96     { "BMP", 0, MagickString("BM") },
97     { "BMP", 0, MagickString("CI") },
98     { "BMP", 0, MagickString("CP") },
99     { "BMP", 0, MagickString("IC") },
100     { "PICT", 0, MagickString("PICT") },
101     { "BMP", 0, MagickString("PI") },
102     { "CALS", 21, MagickString("version: MIL-STD-1840") },
103     { "CALS", 0, MagickString("srcdocid:") },
104     { "CALS", 9, MagickString("srcdocid:") },
105     { "CALS", 8, MagickString("rorient:") },
106     { "CGM", 0, MagickString("BEGMF") },
107     { "CIN", 0, MagickString("\200\052\137\327") },
108     { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
109     { "DCM", 128, MagickString("DICM") },
110     { "DCX", 0, MagickString("\261\150\336\72") },
111     { "DIB", 0, MagickString("\050\000") },
112     { "DDS", 0, MagickString("DDS ") },
113     { "DJVU", 0, MagickString("AT&TFORM") },
114     { "DOT", 0, MagickString("digraph") },
115     { "DPX", 0, MagickString("SDPX") },
116     { "DPX", 0, MagickString("XPDS") },
117     { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
118     { "EPT", 0, MagickString("\305\320\323\306") },
119     { "EXR", 0, MagickString("\166\057\061\001") },
120     { "FAX", 0, MagickString("DFAX") },
121     { "FIG", 0, MagickString("#FIG") },
122     { "FITS", 0, MagickString("IT0") },
123     { "FITS", 0, MagickString("SIMPLE") },
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_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 LinkedListInfo *AcquireMagicCache(const char *filename,
247   ExceptionInfo *exception)
248 {
249   char
250     path[MaxTextExtent];
251
252   const StringInfo
253     *option;
254
255   LinkedListInfo
256     *magic_cache,
257     *options;
258
259   MagickStatusType
260     status;
261
262   register ssize_t
263     i;
264
265   /*
266     Load external magic map.
267   */
268   magic_cache=NewLinkedList(0);
269   if (magic_cache == (LinkedListInfo *) NULL)
270     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
271   status=MagickTrue;
272   *path='\0';
273   options=GetConfigureOptions(filename,exception);
274   option=(const StringInfo *) GetNextValueInLinkedList(options);
275   while (option != (const StringInfo *) NULL)
276   {
277     (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
278     status&=LoadMagicCache(magic_cache,(const char *)
279       GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
280     option=(const StringInfo *) GetNextValueInLinkedList(options);
281   }
282   options=DestroyConfigureOptions(options);
283   /*
284     Load built-in magic map.
285   */
286   for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
287   {
288     MagicInfo
289       *magic_info;
290
291     register const MagicMapInfo
292       *p;
293
294     p=MagicMap+i;
295     magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
296     if (magic_info == (MagicInfo *) NULL)
297       {
298         (void) ThrowMagickException(exception,GetMagickModule(),
299           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
300         continue;
301       }
302     (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
303     magic_info->path=(char *) "[built-in]";
304     magic_info->name=(char *) p->name;
305     magic_info->offset=p->offset;
306     magic_info->target=(char *) p->magic;
307     magic_info->magic=(unsigned char *) p->magic;
308     magic_info->length=p->length;
309     magic_info->exempt=MagickTrue;
310     magic_info->signature=MagickSignature;
311     status&=AppendValueToLinkedList(magic_cache,magic_info);
312     if (status == MagickFalse)
313       (void) ThrowMagickException(exception,GetMagickModule(),
314         ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
315   }
316   return(magic_cache);
317 }
318 \f
319 /*
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 %                                                                             %
322 %                                                                             %
323 %                                                                             %
324 +   G e t M a g i c I n f o                                                   %
325 %                                                                             %
326 %                                                                             %
327 %                                                                             %
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 %
330 %  GetMagicInfo() searches the magic list for the specified name and if found
331 %  returns attributes for that magic.
332 %
333 %  The format of the GetMagicInfo method is:
334 %
335 %      const MagicInfo *GetMagicInfo(const unsigned char *magic,
336 %        const size_t length,ExceptionInfo *exception)
337 %
338 %  A description of each parameter follows:
339 %
340 %    o magic: A binary string generally representing the first few characters
341 %      of the image file or blob.
342 %
343 %    o length: the length of the binary signature.
344 %
345 %    o exception: return any errors or warnings in this structure.
346 %
347 */
348 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
349   const size_t length,ExceptionInfo *exception)
350 {
351   register const MagicInfo
352     *p;
353
354   assert(exception != (ExceptionInfo *) NULL);
355   if (IsMagicCacheInstantiated(exception) == MagickFalse)
356     return((const MagicInfo *) NULL);
357   /*
358     Search for magic tag.
359   */
360   LockSemaphoreInfo(magic_semaphore);
361   ResetLinkedListIterator(magic_cache);
362   p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
363   if (magic == (const unsigned char *) NULL)
364     {
365       UnlockSemaphoreInfo(magic_semaphore);
366       return(p);
367     }
368   while (p != (const MagicInfo *) NULL)
369   {
370     assert(p->offset >= 0);
371     if (((size_t) (p->offset+p->length) <= length) &&
372         (memcmp(magic+p->offset,p->magic,p->length) == 0))
373       break;
374     p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
375   }
376   if (p != (const MagicInfo *) NULL)
377     (void) InsertValueInLinkedList(magic_cache,0,
378       RemoveElementByValueFromLinkedList(magic_cache,p));
379   UnlockSemaphoreInfo(magic_semaphore);
380   return(p);
381 }
382 \f
383 /*
384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 %                                                                             %
386 %                                                                             %
387 %                                                                             %
388 %   G e t M a g i c I n f o L i s t                                           %
389 %                                                                             %
390 %                                                                             %
391 %                                                                             %
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 %
394 %  GetMagicInfoList() returns any image aliases that match the specified
395 %  pattern.
396 %
397 %  The magic of the GetMagicInfoList function is:
398 %
399 %      const MagicInfo **GetMagicInfoList(const char *pattern,
400 %        size_t *number_aliases,ExceptionInfo *exception)
401 %
402 %  A description of each parameter follows:
403 %
404 %    o pattern: Specifies a pointer to a text string containing a pattern.
405 %
406 %    o number_aliases:  This integer returns the number of aliases in the list.
407 %
408 %    o exception: return any errors or warnings in this structure.
409 %
410 */
411
412 #if defined(__cplusplus) || defined(c_plusplus)
413 extern "C" {
414 #endif
415
416 static int MagicInfoCompare(const void *x,const void *y)
417 {
418   const MagicInfo
419     **p,
420     **q;
421
422   p=(const MagicInfo **) x,
423   q=(const MagicInfo **) y;
424   if (LocaleCompare((*p)->path,(*q)->path) == 0)
425     return(LocaleCompare((*p)->name,(*q)->name));
426   return(LocaleCompare((*p)->path,(*q)->path));
427 }
428
429 #if defined(__cplusplus) || defined(c_plusplus)
430 }
431 #endif
432
433 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
434   size_t *number_aliases,ExceptionInfo *exception)
435 {
436   const MagicInfo
437     **aliases;
438
439   register const MagicInfo
440     *p;
441
442   register ssize_t
443     i;
444
445   /*
446     Allocate magic 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((const MagicInfo **) NULL);
455   aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
456     GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
457   if (aliases == (const MagicInfo **) NULL)
458     return((const MagicInfo **) NULL);
459   /*
460     Generate magic list.
461   */
462   LockSemaphoreInfo(magic_semaphore);
463   ResetLinkedListIterator(magic_cache);
464   p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
465   for (i=0; p != (const MagicInfo *) NULL; )
466   {
467     if ((p->stealth == MagickFalse) &&
468         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
469       aliases[i++]=p;
470     p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
471   }
472   UnlockSemaphoreInfo(magic_semaphore);
473   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
474   aliases[i]=(MagicInfo *) NULL;
475   *number_aliases=(size_t) i;
476   return(aliases);
477 }
478 \f
479 /*
480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481 %                                                                             %
482 %                                                                             %
483 %                                                                             %
484 %   G e t M a g i c L i s t                                                   %
485 %                                                                             %
486 %                                                                             %
487 %                                                                             %
488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
489 %
490 %  GetMagicList() returns any image format aliases that match the specified
491 %  pattern.
492 %
493 %  The format of the GetMagicList function is:
494 %
495 %      char **GetMagicList(const char *pattern,size_t *number_aliases,
496 %        ExceptionInfo *exception)
497 %
498 %  A description of each parameter follows:
499 %
500 %    o pattern: Specifies a pointer to a text string containing a pattern.
501 %
502 %    o number_aliases:  This integer returns the number of image format aliases
503 %      in the list.
504 %
505 %    o exception: return any errors or warnings in this structure.
506 %
507 */
508
509 #if defined(__cplusplus) || defined(c_plusplus)
510 extern "C" {
511 #endif
512
513 static int MagicCompare(const void *x,const void *y)
514 {
515   register const char
516     *p,
517     *q;
518
519   p=(const char *) x;
520   q=(const char *) y;
521   return(LocaleCompare(p,q));
522 }
523
524 #if defined(__cplusplus) || defined(c_plusplus)
525 }
526 #endif
527
528 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
529   ExceptionInfo *exception)
530 {
531   char
532     **aliases;
533
534   register const MagicInfo
535     *p;
536
537   register ssize_t
538     i;
539
540   /*
541     Allocate configure list.
542   */
543   assert(pattern != (char *) NULL);
544   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
545   assert(number_aliases != (size_t *) NULL);
546   *number_aliases=0;
547   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
548   if (p == (const MagicInfo *) NULL)
549     return((char **) NULL);
550   aliases=(char **) AcquireQuantumMemory((size_t)
551     GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
552   if (aliases == (char **) NULL)
553     return((char **) NULL);
554   LockSemaphoreInfo(magic_semaphore);
555   ResetLinkedListIterator(magic_cache);
556   p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
557   for (i=0; p != (const MagicInfo *) NULL; )
558   {
559     if ((p->stealth == MagickFalse) &&
560         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
561       aliases[i++]=ConstantString(p->name);
562     p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
563   }
564   UnlockSemaphoreInfo(magic_semaphore);
565   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
566   aliases[i]=(char *) NULL;
567   *number_aliases=(size_t) i;
568   return(aliases);
569 }
570 \f
571 /*
572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
573 %                                                                             %
574 %                                                                             %
575 %                                                                             %
576 %   G e t M a g i c N a m e                                                   %
577 %                                                                             %
578 %                                                                             %
579 %                                                                             %
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 %
582 %  GetMagicName() returns the name associated with the magic.
583 %
584 %  The format of the GetMagicName method is:
585 %
586 %      const char *GetMagicName(const MagicInfo *magic_info)
587 %
588 %  A description of each parameter follows:
589 %
590 %    o magic_info:  The magic info.
591 %
592 */
593 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
594 {
595   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
596   assert(magic_info != (MagicInfo *) NULL);
597   assert(magic_info->signature == MagickSignature);
598   return(magic_info->name);
599 }
600 \f
601 /*
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 %                                                                             %
604 %                                                                             %
605 %                                                                             %
606 +   I s M a g i c C a c h e I n s t a n t i a t e d                           %
607 %                                                                             %
608 %                                                                             %
609 %                                                                             %
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %
612 %  IsMagicCacheInstantiated() determines if the magic list is instantiated.
613 %  If not, it instantiates the list and returns it.
614 %
615 %  The format of the IsMagicInstantiated method is:
616 %
617 %      MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
618 %
619 %  A description of each parameter follows.
620 %
621 %    o exception: return any errors or warnings in this structure.
622 %
623 */
624 static MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
625 {
626   if (magic_cache == (LinkedListInfo *) NULL)
627     {
628       if (magic_semaphore == (SemaphoreInfo *) NULL)
629         ActivateSemaphoreInfo(&magic_semaphore);
630       LockSemaphoreInfo(magic_semaphore);
631       if (magic_cache == (LinkedListInfo *) NULL)
632         magic_cache=AcquireMagicCache(MagicFilename,exception);
633       UnlockSemaphoreInfo(magic_semaphore);
634     }
635   return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
636 }
637 \f
638 /*
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 %                                                                             %
641 %                                                                             %
642 %                                                                             %
643 %  L i s t M a g i c I n f o                                                  %
644 %                                                                             %
645 %                                                                             %
646 %                                                                             %
647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 %
649 %  ListMagicInfo() lists the magic info to a file.
650 %
651 %  The format of the ListMagicInfo method is:
652 %
653 %      MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
654 %
655 %  A description of each parameter follows.
656 %
657 %    o file:  An pointer to a FILE.
658 %
659 %    o exception: return any errors or warnings in this structure.
660 %
661 */
662 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
663   ExceptionInfo *exception)
664 {
665   const char
666     *path;
667
668   const MagicInfo
669     **magic_info;
670
671   register ssize_t
672     i;
673
674   size_t
675     number_aliases;
676
677   ssize_t
678     j;
679
680   if (file == (const FILE *) NULL)
681     file=stdout;
682   magic_info=GetMagicInfoList("*",&number_aliases,exception);
683   if (magic_info == (const MagicInfo **) NULL)
684     return(MagickFalse);
685   j=0;
686   path=(const char *) NULL;
687   for (i=0; i < (ssize_t) number_aliases; i++)
688   {
689     if (magic_info[i]->stealth != MagickFalse)
690       continue;
691     if ((path == (const char *) NULL) ||
692         (LocaleCompare(path,magic_info[i]->path) != 0))
693       {
694         if (magic_info[i]->path != (char *) NULL)
695           (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
696         (void) FormatLocaleFile(file,"Name      Offset Target\n");
697         (void) FormatLocaleFile(file,
698           "-------------------------------------------------"
699           "------------------------------\n");
700       }
701     path=magic_info[i]->path;
702     (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
703     for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
704       (void) FormatLocaleFile(file," ");
705     (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
706     if (magic_info[i]->target != (char *) NULL)
707       {
708         register ssize_t
709           j;
710
711         for (j=0; magic_info[i]->target[j] != '\0'; j++)
712           if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
713             (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
714           else
715             (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
716               ((unsigned char) magic_info[i]->target[j]));
717       }
718     (void) FormatLocaleFile(file,"\n");
719   }
720   (void) fflush(file);
721   magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
722   return(MagickTrue);
723 }
724 \f
725 /*
726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 %                                                                             %
728 %                                                                             %
729 %                                                                             %
730 +   L o a d M a g i c L i s t                                                 %
731 %                                                                             %
732 %                                                                             %
733 %                                                                             %
734 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
735 %
736 %  LoadMagicCache() loads the magic configurations which provides a mapping
737 %  between magic attributes and a magic name.
738 %
739 %  The format of the LoadMagicCache method is:
740 %
741 %      MagickBooleanType LoadMagicCache(LinkedListInfo *magic_cache,
742 %        const char *xml,const char *filename,const size_t depth,
743 %        ExceptionInfo *exception)
744 %
745 %  A description of each parameter follows:
746 %
747 %    o xml: The magic list in XML format.
748 %
749 %    o filename: The magic list filename.
750 %
751 %    o depth: depth of <include /> statements.
752 %
753 %    o exception: return any errors or warnings in this structure.
754 %
755 */
756 static MagickBooleanType LoadMagicCache(LinkedListInfo *magic_cache,
757   const char *xml,const char *filename,const size_t depth,
758   ExceptionInfo *exception)
759 {
760   char
761     keyword[MaxTextExtent],
762     *token;
763
764   const char
765     *q;
766
767   MagicInfo
768     *magic_info;
769
770   MagickStatusType
771     status;
772
773   /*
774     Load the magic map file.
775   */
776   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
777     "Loading magic configure file \"%s\" ...",filename);
778   if (xml == (char *) NULL)
779     return(MagickFalse);
780   status=MagickTrue;
781   magic_info=(MagicInfo *) NULL;
782   token=AcquireString(xml);
783   for (q=(char *) xml; *q != '\0'; )
784   {
785     /*
786       Interpret XML.
787     */
788     GetMagickToken(q,&q,token);
789     if (*token == '\0')
790       break;
791     (void) CopyMagickString(keyword,token,MaxTextExtent);
792     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
793       {
794         /*
795           Doctype element.
796         */
797         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
798           GetMagickToken(q,&q,token);
799         continue;
800       }
801     if (LocaleNCompare(keyword,"<!--",4) == 0)
802       {
803         /*
804           Comment element.
805         */
806         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
807           GetMagickToken(q,&q,token);
808         continue;
809       }
810     if (LocaleCompare(keyword,"<include") == 0)
811       {
812         /*
813           Include element.
814         */
815         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
816         {
817           (void) CopyMagickString(keyword,token,MaxTextExtent);
818           GetMagickToken(q,&q,token);
819           if (*token != '=')
820             continue;
821           GetMagickToken(q,&q,token);
822           if (LocaleCompare(keyword,"file") == 0)
823             {
824               if (depth > 200)
825                 (void) ThrowMagickException(exception,GetMagickModule(),
826                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
827               else
828                 {
829                   char
830                     path[MaxTextExtent],
831                     *xml;
832
833                   GetPathComponent(filename,HeadPath,path);
834                   if (*path != '\0')
835                     (void) ConcatenateMagickString(path,DirectorySeparator,
836                       MaxTextExtent);
837                   if (*token == *DirectorySeparator)
838                     (void) CopyMagickString(path,token,MaxTextExtent);
839                   else
840                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
841                   xml=FileToXML(path,~0UL);
842                   if (xml != (char *) NULL)
843                     {
844                       status&=LoadMagicCache(magic_cache,xml,path,depth+1,
845                         exception);
846                       xml=(char *) RelinquishMagickMemory(xml);
847                     }
848                 }
849             }
850         }
851         continue;
852       }
853     if (LocaleCompare(keyword,"<magic") == 0)
854       {
855         /*
856           Magic element.
857         */
858         magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
859         if (magic_info == (MagicInfo *) NULL)
860           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
861         (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
862         magic_info->path=ConstantString(filename);
863         magic_info->exempt=MagickFalse;
864         magic_info->signature=MagickSignature;
865         continue;
866       }
867     if (magic_info == (MagicInfo *) NULL)
868       continue;
869     if (LocaleCompare(keyword,"/>") == 0)
870       {
871         status=AppendValueToLinkedList(magic_cache,magic_info);
872         if (status == MagickFalse)
873           (void) ThrowMagickException(exception,GetMagickModule(),
874             ResourceLimitError,"MemoryAllocationFailed","`%s'",
875             magic_info->name);
876         magic_info=(MagicInfo *) NULL;
877         continue;
878       }
879     GetMagickToken(q,(const char **) NULL,token);
880     if (*token != '=')
881       continue;
882     GetMagickToken(q,&q,token);
883     GetMagickToken(q,&q,token);
884     switch (*keyword)
885     {
886       case 'N':
887       case 'n':
888       {
889         if (LocaleCompare((char *) keyword,"name") == 0)
890           {
891             magic_info->name=ConstantString(token);
892             break;
893           }
894         break;
895       }
896       case 'O':
897       case 'o':
898       {
899         if (LocaleCompare((char *) keyword,"offset") == 0)
900           {
901             magic_info->offset=(MagickOffsetType) StringToLong(token);
902             break;
903           }
904         break;
905       }
906       case 'S':
907       case 's':
908       {
909         if (LocaleCompare((char *) keyword,"stealth") == 0)
910           {
911             magic_info->stealth=IsStringTrue(token);
912             break;
913           }
914         break;
915       }
916       case 'T':
917       case 't':
918       {
919         if (LocaleCompare((char *) keyword,"target") == 0)
920           {
921             char
922               *p;
923
924             register unsigned char
925               *q;
926
927             size_t
928               length;
929
930             length=strlen(token);
931             magic_info->target=ConstantString(token);
932             magic_info->magic=(unsigned char *) ConstantString(token);
933             q=magic_info->magic;
934             for (p=magic_info->target; *p != '\0'; )
935             {
936               if (*p == '\\')
937                 {
938                   p++;
939                   if (isdigit((int) ((unsigned char) *p)) != 0)
940                     {
941                       char
942                         *end;
943
944                       *q++=(unsigned char) strtol(p,&end,8);
945                       p+=(end-p);
946                       magic_info->length++;
947                       continue;
948                     }
949                   switch (*p)
950                   {
951                     case 'b': *q='\b'; break;
952                     case 'f': *q='\f'; break;
953                     case 'n': *q='\n'; break;
954                     case 'r': *q='\r'; break;
955                     case 't': *q='\t'; break;
956                     case 'v': *q='\v'; break;
957                     case 'a': *q='a'; break;
958                     case '?': *q='\?'; break;
959                     default: *q=(unsigned char) (*p); break;
960                   }
961                   p++;
962                   q++;
963                   magic_info->length++;
964                   continue;
965                 }
966               else
967                 if (LocaleNCompare(p,"&amp;",5) == 0)
968                   (void) CopyMagickString(p+1,p+5,length-magic_info->length);
969               *q++=(unsigned char) (*p++);
970               magic_info->length++;
971             }
972             break;
973           }
974         break;
975       }
976       default:
977         break;
978     }
979   }
980   token=(char *) RelinquishMagickMemory(token);
981   return(status != 0 ? MagickTrue : MagickFalse);
982 }
983 \f
984 /*
985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986 %                                                                             %
987 %                                                                             %
988 %                                                                             %
989 +   M a g i c C o m p o n e n t G e n e s i s                                 %
990 %                                                                             %
991 %                                                                             %
992 %                                                                             %
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994 %
995 %  MagicComponentGenesis() instantiates the magic component.
996 %
997 %  The format of the MagicComponentGenesis method is:
998 %
999 %      MagickBooleanType MagicComponentGenesis(void)
1000 %
1001 */
1002 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
1003 {
1004   if (magic_semaphore == (SemaphoreInfo *) NULL)
1005     magic_semaphore=AcquireSemaphoreInfo();
1006   return(MagickTrue);
1007 }
1008 \f
1009 /*
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %                                                                             %
1012 %                                                                             %
1013 %                                                                             %
1014 +   M a g i c C o m p o n e n t T e r m i n u s                               %
1015 %                                                                             %
1016 %                                                                             %
1017 %                                                                             %
1018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 %
1020 %  MagicComponentTerminus() destroys the magic component.
1021 %
1022 %  The format of the MagicComponentTerminus method is:
1023 %
1024 %      MagicComponentTerminus(void)
1025 %
1026 */
1027
1028 static void *DestroyMagicElement(void *magic_info)
1029 {
1030   register MagicInfo
1031     *p;
1032
1033   p=(MagicInfo *) magic_info;
1034   if (p->exempt == MagickFalse)
1035     {
1036       if (p->path != (char *) NULL)
1037         p->path=DestroyString(p->path);
1038       if (p->name != (char *) NULL)
1039         p->name=DestroyString(p->name);
1040       if (p->target != (char *) NULL)
1041         p->target=DestroyString(p->target);
1042       if (p->magic != (unsigned char *) NULL)
1043         p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1044     }
1045   p=(MagicInfo *) RelinquishMagickMemory(p);
1046   return((void *) NULL);
1047 }
1048
1049 MagickPrivate void MagicComponentTerminus(void)
1050 {
1051   if (magic_semaphore == (SemaphoreInfo *) NULL)
1052     ActivateSemaphoreInfo(&magic_semaphore);
1053   LockSemaphoreInfo(magic_semaphore);
1054   if (magic_cache != (LinkedListInfo *) NULL)
1055     magic_cache=DestroyLinkedList(magic_cache,DestroyMagicElement);
1056   UnlockSemaphoreInfo(magic_semaphore);
1057   RelinquishSemaphoreInfo(&magic_semaphore);
1058 }