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