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 
257  if (ma->offset != mb->offset)
258  return((int) (ma->offset-mb->offset));
259 
260  return((int) (mb->length-ma->length));
261 }
262 
263 static LinkedListInfo *AcquireMagicCache(const char *filename,
264  ExceptionInfo *exception)
265 {
267  *cache;
268 
270  status;
271 
272  register ssize_t
273  i;
274 
275  /*
276  Load external magic map.
277  */
278  cache=NewLinkedList(0);
279  status=MagickTrue;
280 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
281  {
282  char
283  path[MagickPathExtent];
284 
285  const StringInfo
286  *option;
287 
289  *options;
290 
291  *path='\0';
292  options=GetConfigureOptions(filename,exception);
293  option=(const StringInfo *) GetNextValueInLinkedList(options);
294  while (option != (const StringInfo *) NULL)
295  {
297  status&=LoadMagicCache(cache,(const char *)
298  GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
299  option=(const StringInfo *) GetNextValueInLinkedList(options);
300  }
301  options=DestroyConfigureOptions(options);
302  }
303 #endif
304  /*
305  Load built-in magic map.
306  */
307  for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
308  {
309  MagicInfo
310  *magic_info;
311 
312  register const MagicMapInfo
313  *p;
314 
315  p=MagicMap+i;
316  magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
317  if (magic_info == (MagicInfo *) NULL)
318  {
319  (void) ThrowMagickException(exception,GetMagickModule(),
320  ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
321  continue;
322  }
323  (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
324  magic_info->path=(char *) "[built-in]";
325  magic_info->name=(char *) p->name;
326  magic_info->offset=p->offset;
327  magic_info->target=(char *) p->magic;
328  magic_info->magic=(unsigned char *) p->magic;
329  magic_info->length=p->length;
330  magic_info->exempt=MagickTrue;
331  magic_info->signature=MagickCoreSignature;
333  NULL,magic_info);
334  if (status == MagickFalse)
335  (void) ThrowMagickException(exception,GetMagickModule(),
336  ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
337  }
338  return(cache);
339 }
340 
341 /*
342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343 % %
344 % %
345 % %
346 % G e t M a g i c I n f o %
347 % %
348 % %
349 % %
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351 %
352 % GetMagicInfo() searches the magic list for the specified name and if found
353 % returns attributes for that magic.
354 %
355 % The format of the GetMagicInfo method is:
356 %
357 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
358 % const size_t length,ExceptionInfo *exception)
359 %
360 % A description of each parameter follows:
361 %
362 % o magic: A binary string generally representing the first few characters
363 % of the image file or blob.
364 %
365 % o length: the length of the binary signature.
366 %
367 % o exception: return any errors or warnings in this structure.
368 %
369 */
370 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
371  const size_t length,ExceptionInfo *exception)
372 {
373  register const MagicInfo
374  *p;
375 
376  assert(exception != (ExceptionInfo *) NULL);
377  if (IsMagicCacheInstantiated(exception) == MagickFalse)
378  return((const MagicInfo *) NULL);
379  /*
380  Search for magic tag.
381  */
385  if (magic == (const unsigned char *) NULL)
386  {
388  return(p);
389  }
390  while (p != (const MagicInfo *) NULL)
391  {
392  assert(p->offset >= 0);
393  if (((size_t) (p->offset+p->length) <= length) &&
394  (memcmp(magic+p->offset,p->magic,p->length) == 0))
395  break;
397  }
398  if (p != (const MagicInfo *) NULL)
402  return(p);
403 }
404 
405 /*
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 % %
408 % %
409 % %
410 % G e t M a g i c P a t t e r n E x t e n t %
411 % %
412 % %
413 % %
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
415 %
416 % GetMagicPatternExtent() returns the the extent of the buffer that is
417 % required to check all the MagickInfos. It returns zero if the list is empty.
418 %
419 % The format of the GetMagicPatternExtent method is:
420 %
421 % size_t GetMagicPatternExtent(ExceptionInfo *exception)
422 %
423 % A description of each parameter follows:
424 %
425 % o exception: return any errors or warnings in this structure.
426 %
427 */
429 {
430  register const MagicInfo
431  *p;
432 
433  size_t
434  magickSize,
435  max;
436 
437  static size_t
438  size=0;
439 
440  assert(exception != (ExceptionInfo *) NULL);
441  if ((size != 0) || (IsMagicCacheInstantiated(exception) == MagickFalse))
442  return(size);
445  max=0;
447  while (p != (const MagicInfo *) NULL)
448  {
449  magickSize=(size_t) (p->offset+p->length);
450  if (magickSize > max)
451  max=magickSize;
453  }
454  size=max;
456  return(size);
457 }
458 
459 /*
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 % %
462 % %
463 % %
464 % G e t M a g i c I n f o L i s t %
465 % %
466 % %
467 % %
468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469 %
470 % GetMagicInfoList() returns any image aliases that match the specified
471 % pattern.
472 %
473 % The magic of the GetMagicInfoList function is:
474 %
475 % const MagicInfo **GetMagicInfoList(const char *pattern,
476 % size_t *number_aliases,ExceptionInfo *exception)
477 %
478 % A description of each parameter follows:
479 %
480 % o pattern: Specifies a pointer to a text string containing a pattern.
481 %
482 % o number_aliases: This integer returns the number of aliases in the list.
483 %
484 % o exception: return any errors or warnings in this structure.
485 %
486 */
487 
488 #if defined(__cplusplus) || defined(c_plusplus)
489 extern "C" {
490 #endif
491 
492 static int MagicInfoCompare(const void *x,const void *y)
493 {
494  const MagicInfo
495  **p,
496  **q;
497 
498  p=(const MagicInfo **) x,
499  q=(const MagicInfo **) y;
500  if (LocaleCompare((*p)->path,(*q)->path) == 0)
501  return(LocaleCompare((*p)->name,(*q)->name));
502  return(LocaleCompare((*p)->path,(*q)->path));
503 }
504 
505 #if defined(__cplusplus) || defined(c_plusplus)
506 }
507 #endif
508 
509 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
510  size_t *number_aliases,ExceptionInfo *exception)
511 {
512  const MagicInfo
513  **aliases;
514 
515  register const MagicInfo
516  *p;
517 
518  register ssize_t
519  i;
520 
521  /*
522  Allocate magic list.
523  */
524  assert(pattern != (char *) NULL);
525  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
526  assert(number_aliases != (size_t *) NULL);
527  *number_aliases=0;
528  p=GetMagicInfo((const unsigned char *) NULL,0,exception);
529  if (p == (const MagicInfo *) NULL)
530  return((const MagicInfo **) NULL);
531  aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
532  GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
533  if (aliases == (const MagicInfo **) NULL)
534  return((const MagicInfo **) NULL);
535  /*
536  Generate magic list.
537  */
541  for (i=0; p != (const MagicInfo *) NULL; )
542  {
543  if ((p->stealth == MagickFalse) &&
544  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
545  aliases[i++]=p;
547  }
549  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
550  aliases[i]=(MagicInfo *) NULL;
551  *number_aliases=(size_t) i;
552  return(aliases);
553 }
554 
555 /*
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557 % %
558 % %
559 % %
560 % G e t M a g i c L i s t %
561 % %
562 % %
563 % %
564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 %
566 % GetMagicList() returns any image format aliases that match the specified
567 % pattern.
568 %
569 % The format of the GetMagicList function is:
570 %
571 % char **GetMagicList(const char *pattern,size_t *number_aliases,
572 % ExceptionInfo *exception)
573 %
574 % A description of each parameter follows:
575 %
576 % o pattern: Specifies a pointer to a text string containing a pattern.
577 %
578 % o number_aliases: This integer returns the number of image format aliases
579 % in the list.
580 %
581 % o exception: return any errors or warnings in this structure.
582 %
583 */
584 
585 #if defined(__cplusplus) || defined(c_plusplus)
586 extern "C" {
587 #endif
588 
589 static int MagicCompare(const void *x,const void *y)
590 {
591  register const char
592  *p,
593  *q;
594 
595  p=(const char *) x;
596  q=(const char *) y;
597  return(LocaleCompare(p,q));
598 }
599 
600 #if defined(__cplusplus) || defined(c_plusplus)
601 }
602 #endif
603 
604 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
605  ExceptionInfo *exception)
606 {
607  char
608  **aliases;
609 
610  register const MagicInfo
611  *p;
612 
613  register ssize_t
614  i;
615 
616  /*
617  Allocate configure list.
618  */
619  assert(pattern != (char *) NULL);
620  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
621  assert(number_aliases != (size_t *) NULL);
622  *number_aliases=0;
623  p=GetMagicInfo((const unsigned char *) NULL,0,exception);
624  if (p == (const MagicInfo *) NULL)
625  return((char **) NULL);
626  aliases=(char **) AcquireQuantumMemory((size_t)
627  GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
628  if (aliases == (char **) NULL)
629  return((char **) NULL);
633  for (i=0; p != (const MagicInfo *) NULL; )
634  {
635  if ((p->stealth == MagickFalse) &&
636  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
637  aliases[i++]=ConstantString(p->name);
639  }
641  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
642  aliases[i]=(char *) NULL;
643  *number_aliases=(size_t) i;
644  return(aliases);
645 }
646 
647 /*
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % %
650 % %
651 % %
652 % G e t M a g i c N a m e %
653 % %
654 % %
655 % %
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657 %
658 % GetMagicName() returns the name associated with the magic.
659 %
660 % The format of the GetMagicName method is:
661 %
662 % const char *GetMagicName(const MagicInfo *magic_info)
663 %
664 % A description of each parameter follows:
665 %
666 % o magic_info: The magic info.
667 %
668 */
669 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
670 {
671  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
672  assert(magic_info != (MagicInfo *) NULL);
673  assert(magic_info->signature == MagickCoreSignature);
674  return(magic_info->name);
675 }
676 
677 /*
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % %
680 % %
681 % %
682 + I s M a g i c C a c h e I n s t a n t i a t e d %
683 % %
684 % %
685 % %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
687 %
688 % IsMagicCacheInstantiated() determines if the magic list is instantiated.
689 % If not, it instantiates the list and returns it.
690 %
691 % The format of the IsMagicInstantiated method is:
692 %
693 % MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
694 %
695 % A description of each parameter follows.
696 %
697 % o exception: return any errors or warnings in this structure.
698 %
699 */
701 {
702  if (magic_cache == (LinkedListInfo *) NULL)
703  {
704  if (magic_semaphore == (SemaphoreInfo *) NULL)
707  if (magic_cache == (LinkedListInfo *) NULL)
710  }
711  return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
712 }
713 
714 /*
715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716 % %
717 % %
718 % %
719 % L i s t M a g i c I n f o %
720 % %
721 % %
722 % %
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 %
725 % ListMagicInfo() lists the magic info to a file.
726 %
727 % The format of the ListMagicInfo method is:
728 %
729 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
730 %
731 % A description of each parameter follows.
732 %
733 % o file: An pointer to a FILE.
734 %
735 % o exception: return any errors or warnings in this structure.
736 %
737 */
739  ExceptionInfo *exception)
740 {
741  const char
742  *path;
743 
744  const MagicInfo
745  **magic_info;
746 
747  register ssize_t
748  i;
749 
750  size_t
751  number_aliases;
752 
753  ssize_t
754  j;
755 
756  if (file == (const FILE *) NULL)
757  file=stdout;
758  magic_info=GetMagicInfoList("*",&number_aliases,exception);
759  if (magic_info == (const MagicInfo **) NULL)
760  return(MagickFalse);
761  path=(const char *) NULL;
762  for (i=0; i < (ssize_t) number_aliases; i++)
763  {
764  if (magic_info[i]->stealth != MagickFalse)
765  continue;
766  if ((path == (const char *) NULL) ||
767  (LocaleCompare(path,magic_info[i]->path) != 0))
768  {
769  if (magic_info[i]->path != (char *) NULL)
770  (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
771  (void) FormatLocaleFile(file,"Name Offset Target\n");
772  (void) FormatLocaleFile(file,
773  "-------------------------------------------------"
774  "------------------------------\n");
775  }
776  path=magic_info[i]->path;
777  (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
778  for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
779  (void) FormatLocaleFile(file," ");
780  (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
781  if (magic_info[i]->target != (char *) NULL)
782  {
783  for (j=0; magic_info[i]->target[j] != '\0'; j++)
784  if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
785  (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
786  else
787  (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
788  ((unsigned char) magic_info[i]->target[j]));
789  }
790  (void) FormatLocaleFile(file,"\n");
791  }
792  (void) fflush(file);
793  magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
794  return(MagickTrue);
795 }
796 
797 /*
798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799 % %
800 % %
801 % %
802 + L o a d M a g i c C a c h e %
803 % %
804 % %
805 % %
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807 %
808 % LoadMagicCache() loads the magic configurations which provides a mapping
809 % between magic attributes and a magic name.
810 %
811 % The format of the LoadMagicCache method is:
812 %
813 % MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml,
814 % const char *filename,const size_t depth,ExceptionInfo *exception)
815 %
816 % A description of each parameter follows:
817 %
818 % o xml: The magic list in XML format.
819 %
820 % o filename: The magic list filename.
821 %
822 % o depth: depth of <include /> statements.
823 %
824 % o exception: return any errors or warnings in this structure.
825 %
826 */
827 static MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml,
828  const char *filename,const size_t depth,ExceptionInfo *exception)
829 {
830  char
831  keyword[MagickPathExtent],
832  *token;
833 
834  const char
835  *q;
836 
837  MagicInfo
838  *magic_info;
839 
841  status;
842 
843  size_t
844  extent;
845 
846  /*
847  Load the magic map file.
848  */
850  "Loading magic configure file \"%s\" ...",filename);
851  if (xml == (char *) NULL)
852  return(MagickFalse);
853  status=MagickTrue;
854  magic_info=(MagicInfo *) NULL;
855  token=AcquireString(xml);
856  extent=strlen(token)+MagickPathExtent;
857  for (q=(char *) xml; *q != '\0'; )
858  {
859  /*
860  Interpret XML.
861  */
862  GetNextToken(q,&q,extent,token);
863  if (*token == '\0')
864  break;
865  (void) CopyMagickString(keyword,token,MagickPathExtent);
866  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
867  {
868  /*
869  Doctype element.
870  */
871  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
872  GetNextToken(q,&q,extent,token);
873  continue;
874  }
875  if (LocaleNCompare(keyword,"<!--",4) == 0)
876  {
877  /*
878  Comment element.
879  */
880  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
881  GetNextToken(q,&q,extent,token);
882  continue;
883  }
884  if (LocaleCompare(keyword,"<include") == 0)
885  {
886  /*
887  Include element.
888  */
889  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
890  {
891  (void) CopyMagickString(keyword,token,MagickPathExtent);
892  GetNextToken(q,&q,extent,token);
893  if (*token != '=')
894  continue;
895  GetNextToken(q,&q,extent,token);
896  if (LocaleCompare(keyword,"file") == 0)
897  {
898  if (depth > 200)
899  (void) ThrowMagickException(exception,GetMagickModule(),
900  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
901  else
902  {
903  char
904  path[MagickPathExtent],
905  *file_xml;
906 
907  GetPathComponent(filename,HeadPath,path);
908  if (*path != '\0')
911  if (*token == *DirectorySeparator)
912  (void) CopyMagickString(path,token,MagickPathExtent);
913  else
914  (void) ConcatenateMagickString(path,token,MagickPathExtent);
915  file_xml=FileToXML(path,~0UL);
916  if (xml != (char *) NULL)
917  {
918  status&=LoadMagicCache(cache,file_xml,path,depth+1,
919  exception);
920  file_xml=DestroyString(file_xml);
921  }
922  }
923  }
924  }
925  continue;
926  }
927  if (LocaleCompare(keyword,"<magic") == 0)
928  {
929  /*
930  Magic element.
931  */
932  magic_info=(MagicInfo *) AcquireCriticalMemory(sizeof(*magic_info));
933  (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
934  magic_info->path=ConstantString(filename);
935  magic_info->exempt=MagickFalse;
936  magic_info->signature=MagickCoreSignature;
937  continue;
938  }
939  if (magic_info == (MagicInfo *) NULL)
940  continue;
941  if ((LocaleCompare(keyword,"/>") == 0) ||
942  (LocaleCompare(keyword,"</policy>") == 0))
943  {
945  NULL,magic_info);
946  if (status == MagickFalse)
947  (void) ThrowMagickException(exception,GetMagickModule(),
948  ResourceLimitError,"MemoryAllocationFailed","`%s'",
949  magic_info->name);
950  magic_info=(MagicInfo *) NULL;
951  continue;
952  }
953  GetNextToken(q,(const char **) NULL,extent,token);
954  if (*token != '=')
955  continue;
956  GetNextToken(q,&q,extent,token);
957  GetNextToken(q,&q,extent,token);
958  switch (*keyword)
959  {
960  case 'N':
961  case 'n':
962  {
963  if (LocaleCompare((char *) keyword,"name") == 0)
964  {
965  magic_info->name=ConstantString(token);
966  break;
967  }
968  break;
969  }
970  case 'O':
971  case 'o':
972  {
973  if (LocaleCompare((char *) keyword,"offset") == 0)
974  {
975  magic_info->offset=(MagickOffsetType) StringToLong(token);
976  break;
977  }
978  break;
979  }
980  case 'S':
981  case 's':
982  {
983  if (LocaleCompare((char *) keyword,"stealth") == 0)
984  {
985  magic_info->stealth=IsStringTrue(token);
986  break;
987  }
988  break;
989  }
990  case 'T':
991  case 't':
992  {
993  if (LocaleCompare((char *) keyword,"target") == 0)
994  {
995  char
996  *p;
997 
998  register unsigned char
999  *r;
1000 
1001  size_t
1002  length;
1003 
1004  length=strlen(token);
1005  magic_info->target=ConstantString(token);
1006  magic_info->magic=(unsigned char *) ConstantString(token);
1007  r=magic_info->magic;
1008  for (p=magic_info->target; *p != '\0'; )
1009  {
1010  if (*p == '\\')
1011  {
1012  p++;
1013  if (isdigit((int) ((unsigned char) *p)) != 0)
1014  {
1015  char
1016  *end;
1017 
1018  *r++=(unsigned char) strtol(p,&end,8);
1019  p+=(end-p);
1020  magic_info->length++;
1021  continue;
1022  }
1023  switch (*p)
1024  {
1025  case 'b': *r='\b'; break;
1026  case 'f': *r='\f'; break;
1027  case 'n': *r='\n'; break;
1028  case 'r': *r='\r'; break;
1029  case 't': *r='\t'; break;
1030  case 'v': *r='\v'; break;
1031  case 'a': *r='a'; break;
1032  case '?': *r='\?'; break;
1033  default: *r=(unsigned char) (*p); break;
1034  }
1035  p++;
1036  r++;
1037  magic_info->length++;
1038  continue;
1039  }
1040  else
1041  if (LocaleNCompare(p,"&amp;",5) == 0)
1042  (void) CopyMagickString(p+1,p+5,length-magic_info->length);
1043  *r++=(unsigned char) (*p++);
1044  magic_info->length++;
1045  }
1046  break;
1047  }
1048  break;
1049  }
1050  default:
1051  break;
1052  }
1053  }
1054  token=(char *) RelinquishMagickMemory(token);
1055  return(status != 0 ? MagickTrue : MagickFalse);
1056 }
1057 
1058 /*
1059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1060 % %
1061 % %
1062 % %
1063 + M a g i c C o m p o n e n t G e n e s i s %
1064 % %
1065 % %
1066 % %
1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068 %
1069 % MagicComponentGenesis() instantiates the magic component.
1070 %
1071 % The format of the MagicComponentGenesis method is:
1072 %
1073 % MagickBooleanType MagicComponentGenesis(void)
1074 %
1075 */
1077 {
1078  if (magic_semaphore == (SemaphoreInfo *) NULL)
1080  return(MagickTrue);
1081 }
1082 
1083 /*
1084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1085 % %
1086 % %
1087 % %
1088 + M a g i c C o m p o n e n t T e r m i n u s %
1089 % %
1090 % %
1091 % %
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1093 %
1094 % MagicComponentTerminus() destroys the magic component.
1095 %
1096 % The format of the MagicComponentTerminus method is:
1097 %
1098 % MagicComponentTerminus(void)
1099 %
1100 */
1101 
1102 static void *DestroyMagicElement(void *magic_info)
1103 {
1104  register MagicInfo
1105  *p;
1106 
1107  p=(MagicInfo *) magic_info;
1108  if (p->exempt == MagickFalse)
1109  {
1110  if (p->path != (char *) NULL)
1111  p->path=DestroyString(p->path);
1112  if (p->name != (char *) NULL)
1113  p->name=DestroyString(p->name);
1114  if (p->target != (char *) NULL)
1115  p->target=DestroyString(p->target);
1116  if (p->magic != (unsigned char *) NULL)
1117  p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1118  }
1120  return((void *) NULL);
1121 }
1122 
1124 {
1125  if (magic_semaphore == (SemaphoreInfo *) NULL)
1128  if (magic_cache != (LinkedListInfo *) NULL)
1132 }
MagickExport char ** GetMagicList(const char *pattern, size_t *number_aliases, ExceptionInfo *exception)
Definition: magic.c:604
char * path
Definition: magic.h:28
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:669
MagickExport size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:410
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:589
static int MagicInfoCompare(const void *x, const void *y)
Definition: magic.c:492
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:700
#define MagickCoreSignature
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1283
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:378
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:738
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1164
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:529
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1509
#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:349
#define MagickPathExtent
static MagickBooleanType LoadMagicCache(LinkedListInfo *, const char *, const char *, const size_t, ExceptionInfo *)
Definition: magic.c:827
MagickExport MagickBooleanType IsStringTrue(const char *value)
Definition: string.c:1464
MagickExport MagickBooleanType static void * AcquireCriticalMemory(const size_t size)
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:1102
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:742
MagickBooleanType stealth
Definition: magic.h:42
MagickBooleanType exempt
Definition: magic.h:42
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1409
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:1341
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:509
static LinkedListInfo * AcquireMagicCache(const char *filename, ExceptionInfo *exception)
Definition: magic.c:263
MagickExport char * DestroyString(char *string)
Definition: string.c:810
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:458
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:370
const MagickOffsetType offset
Definition: magic.c:78
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1038
MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
Definition: magic.c:428
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:600
#define MagickExport
MagickPrivate void MagicComponentTerminus(void)
Definition: magic.c:1123
struct _MagicMapInfo MagicMapInfo
static int CompareMagickInfoSize(const void *a, const void *b)
Definition: magic.c:248
MagickPrivate MagickBooleanType MagicComponentGenesis(void)
Definition: magic.c:1076
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:687