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