2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M AAA GGGG IIIII CCCC %
8 % M M M AAAAA G GGG I C %
10 % M M A A GGGG IIIII CCCC %
13 % MagickCore Image Magic Methods %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % https://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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/linked-list.h"
50 #include "MagickCore/magic.h"
51 #include "MagickCore/magic-private.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/memory-private.h"
54 #include "MagickCore/semaphore.h"
55 #include "MagickCore/string_.h"
56 #include "MagickCore/string-private.h"
57 #include "MagickCore/token.h"
58 #include "MagickCore/utility.h"
59 #include "MagickCore/utility-private.h"
60 #include "MagickCore/xml-tree.h"
61 #include "MagickCore/xml-tree-private.h"
66 #define MagicFilename "magic.xml"
67 #define MagicPattern(magic) (const unsigned char *) (magic), sizeof(magic)-1
72 typedef struct _MagicMapInfo
77 const MagickOffsetType
90 static const MagicMapInfo
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 { "SVG", 1, MagicPattern("SVG") },
190 { "SVG", 1, MagicPattern("svg") },
191 { "TIFF", 0, MagicPattern("\115\115\000\052") },
192 { "TIFF", 0, MagicPattern("\111\111\052\000") },
193 { "TIFF64", 0, MagicPattern("\115\115\000\053\000\010\000\000") },
194 { "TIFF64", 0, MagicPattern("\111\111\053\000\010\000\000\000") },
195 { "TTF", 0, MagicPattern("\000\001\000\000\000") },
196 { "TXT", 0, MagicPattern("# ImageMagick pixel enumeration:") },
197 { "VICAR", 0, MagicPattern("LBLSIZE") },
198 { "VICAR", 0, MagicPattern("NJPL1I") },
199 { "VIFF", 0, MagicPattern("\253\001") },
200 { "WEBP", 8, MagicPattern("WEBP") },
201 { "WMF", 0, MagicPattern("\327\315\306\232") },
202 { "WMF", 0, MagicPattern("\001\000\011\000") },
203 { "WPG", 0, MagicPattern("\377WPC") },
204 { "XBM", 0, MagicPattern("#define") },
205 { "XCF", 0, MagicPattern("gimp xcf") },
206 { "XEF", 0, MagicPattern("FOVb") },
207 { "XPM", 1, MagicPattern("* XPM *") }
210 static LinkedListInfo
211 *magic_cache = (LinkedListInfo *) NULL;
214 *magic_semaphore = (SemaphoreInfo *) NULL;
217 Forward declarations.
219 static MagickBooleanType
220 IsMagicCacheInstantiated(ExceptionInfo *),
221 LoadMagicCache(LinkedListInfo *,const char *,const char *,const size_t,
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229 % A c q u i r e M a g i c L i s t s %
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 % AcquireMagicCache() caches one or more magic configurations which provides a
236 % mapping between magic attributes and a magic name.
238 % The format of the AcquireMagicCache method is:
240 % LinkedListInfo *AcquireMagicCache(const char *filename,
241 % ExceptionInfo *exception)
243 % A description of each parameter follows:
245 % o filename: the font file name.
247 % o exception: return any errors or warnings in this structure.
250 static int CompareMagickInfoSize(const void *a,const void *b)
258 if (ma->offset != mb->offset)
259 return((int) (ma->offset-mb->offset));
260 return((int) (mb->length-ma->length));
263 static LinkedListInfo *AcquireMagicCache(const char *filename,
264 ExceptionInfo *exception)
276 Load external magic map.
278 cache=NewLinkedList(0);
280 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
283 path[MagickPathExtent];
292 options=GetConfigureOptions(filename,exception);
293 option=(const StringInfo *) GetNextValueInLinkedList(options);
294 while (option != (const StringInfo *) NULL)
296 (void) CopyMagickString(path,GetStringInfoPath(option),MagickPathExtent);
297 status&=LoadMagicCache(cache,(const char *)
298 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
299 option=(const StringInfo *) GetNextValueInLinkedList(options);
301 options=DestroyConfigureOptions(options);
305 Load built-in magic map.
307 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
312 register const MagicMapInfo
316 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
317 if (magic_info == (MagicInfo *) NULL)
319 (void) ThrowMagickException(exception,GetMagickModule(),
320 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
323 (void) memset(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;
332 status&=InsertValueInSortedLinkedList(cache,CompareMagickInfoSize,
334 if (status == MagickFalse)
335 (void) ThrowMagickException(exception,GetMagickModule(),
336 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
342 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 % G e t M a g i c I n f o %
350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
352 % GetMagicInfo() searches the magic list for the specified name and if found
353 % returns attributes for that magic.
355 % The format of the GetMagicInfo method is:
357 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
358 % const size_t length,ExceptionInfo *exception)
360 % A description of each parameter follows:
362 % o magic: A binary string generally representing the first few characters
363 % of the image file or blob.
365 % o length: the length of the binary signature.
367 % o exception: return any errors or warnings in this structure.
370 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
371 const size_t length,ExceptionInfo *exception)
373 register const MagicInfo
376 assert(exception != (ExceptionInfo *) NULL);
377 if (IsMagicCacheInstantiated(exception) == MagickFalse)
378 return((const MagicInfo *) NULL);
380 Search for magic tag.
382 LockSemaphoreInfo(magic_semaphore);
383 ResetLinkedListIterator(magic_cache);
384 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
385 if (magic == (const unsigned char *) NULL)
387 UnlockSemaphoreInfo(magic_semaphore);
390 while (p != (const MagicInfo *) NULL)
392 assert(p->offset >= 0);
393 if (((size_t) (p->offset+p->length) <= length) &&
394 (memcmp(magic+p->offset,p->magic,p->length) == 0))
396 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
398 if (p != (const MagicInfo *) NULL)
399 (void) InsertValueInLinkedList(magic_cache,0,
400 RemoveElementByValueFromLinkedList(magic_cache,p));
401 UnlockSemaphoreInfo(magic_semaphore);
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
410 % G e t M a g i c P a t t e r n E x t e n t %
414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
419 % The format of the GetMagicPatternExtent method is:
421 % size_t GetMagicPatternExtent(ExceptionInfo *exception)
423 % A description of each parameter follows:
425 % o exception: return any errors or warnings in this structure.
428 MagickExport size_t GetMagicPatternExtent(ExceptionInfo *exception)
430 register const MagicInfo
440 assert(exception != (ExceptionInfo *) NULL);
441 if ((size != 0) || (IsMagicCacheInstantiated(exception) == MagickFalse))
443 LockSemaphoreInfo(magic_semaphore);
444 ResetLinkedListIterator(magic_cache);
446 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
447 while (p != (const MagicInfo *) NULL)
449 magickSize=(size_t) (p->offset+p->length);
450 if (magickSize > max)
452 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
455 UnlockSemaphoreInfo(magic_semaphore);
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 % G e t M a g i c I n f o L i s t %
468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 % GetMagicInfoList() returns any image aliases that match the specified
473 % The magic of the GetMagicInfoList function is:
475 % const MagicInfo **GetMagicInfoList(const char *pattern,
476 % size_t *number_aliases,ExceptionInfo *exception)
478 % A description of each parameter follows:
480 % o pattern: Specifies a pointer to a text string containing a pattern.
482 % o number_aliases: This integer returns the number of aliases in the list.
484 % o exception: return any errors or warnings in this structure.
488 #if defined(__cplusplus) || defined(c_plusplus)
492 static int MagicInfoCompare(const void *x,const void *y)
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));
505 #if defined(__cplusplus) || defined(c_plusplus)
509 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
510 size_t *number_aliases,ExceptionInfo *exception)
515 register const MagicInfo
524 assert(pattern != (char *) NULL);
525 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
526 assert(number_aliases != (size_t *) NULL);
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);
538 LockSemaphoreInfo(magic_semaphore);
539 ResetLinkedListIterator(magic_cache);
540 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
541 for (i=0; p != (const MagicInfo *) NULL; )
543 if ((p->stealth == MagickFalse) &&
544 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
546 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
548 UnlockSemaphoreInfo(magic_semaphore);
549 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
550 aliases[i]=(MagicInfo *) NULL;
551 *number_aliases=(size_t) i;
556 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 % G e t M a g i c L i s t %
564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566 % GetMagicList() returns any image format aliases that match the specified
569 % The format of the GetMagicList function is:
571 % char **GetMagicList(const char *pattern,size_t *number_aliases,
572 % ExceptionInfo *exception)
574 % A description of each parameter follows:
576 % o pattern: Specifies a pointer to a text string containing a pattern.
578 % o number_aliases: This integer returns the number of image format aliases
581 % o exception: return any errors or warnings in this structure.
585 #if defined(__cplusplus) || defined(c_plusplus)
589 static int MagicCompare(const void *x,const void *y)
597 return(LocaleCompare(p,q));
600 #if defined(__cplusplus) || defined(c_plusplus)
604 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
605 ExceptionInfo *exception)
610 register const MagicInfo
617 Allocate configure list.
619 assert(pattern != (char *) NULL);
620 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
621 assert(number_aliases != (size_t *) NULL);
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);
630 LockSemaphoreInfo(magic_semaphore);
631 ResetLinkedListIterator(magic_cache);
632 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
633 for (i=0; p != (const MagicInfo *) NULL; )
635 if ((p->stealth == MagickFalse) &&
636 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
637 aliases[i++]=ConstantString(p->name);
638 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
640 UnlockSemaphoreInfo(magic_semaphore);
641 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
642 aliases[i]=(char *) NULL;
643 *number_aliases=(size_t) i;
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % G e t M a g i c N a m e %
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 % GetMagicName() returns the name associated with the magic.
660 % The format of the GetMagicName method is:
662 % const char *GetMagicName(const MagicInfo *magic_info)
664 % A description of each parameter follows:
666 % o magic_info: The magic info.
669 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
671 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
672 assert(magic_info != (MagicInfo *) NULL);
673 assert(magic_info->signature == MagickCoreSignature);
674 return(magic_info->name);
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 % IsMagicCacheInstantiated() determines if the magic list is instantiated.
689 % If not, it instantiates the list and returns it.
691 % The format of the IsMagicInstantiated method is:
693 % MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
695 % A description of each parameter follows.
697 % o exception: return any errors or warnings in this structure.
700 static MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
702 if (magic_cache == (LinkedListInfo *) NULL)
704 if (magic_semaphore == (SemaphoreInfo *) NULL)
705 ActivateSemaphoreInfo(&magic_semaphore);
706 LockSemaphoreInfo(magic_semaphore);
707 if (magic_cache == (LinkedListInfo *) NULL)
708 magic_cache=AcquireMagicCache(MagicFilename,exception);
709 UnlockSemaphoreInfo(magic_semaphore);
711 return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 % L i s t M a g i c I n f o %
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
725 % ListMagicInfo() lists the magic info to a file.
727 % The format of the ListMagicInfo method is:
729 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
731 % A description of each parameter follows.
733 % o file: An pointer to a FILE.
735 % o exception: return any errors or warnings in this structure.
738 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
739 ExceptionInfo *exception)
756 if (file == (const FILE *) NULL)
758 magic_info=GetMagicInfoList("*",&number_aliases,exception);
759 if (magic_info == (const MagicInfo **) NULL)
761 path=(const char *) NULL;
762 for (i=0; i < (ssize_t) number_aliases; i++)
764 if (magic_info[i]->stealth != MagickFalse)
766 if ((path == (const char *) NULL) ||
767 (LocaleCompare(path,magic_info[i]->path) != 0))
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");
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)
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]);
787 (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
788 ((unsigned char) magic_info[i]->target[j]));
790 (void) FormatLocaleFile(file,"\n");
793 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 + L o a d M a g i c C a c h e %
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 % LoadMagicCache() loads the magic configurations which provides a mapping
809 % between magic attributes and a magic name.
811 % The format of the LoadMagicCache method is:
813 % MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml,
814 % const char *filename,const size_t depth,ExceptionInfo *exception)
816 % A description of each parameter follows:
818 % o xml: The magic list in XML format.
820 % o filename: The magic list filename.
822 % o depth: depth of <include /> statements.
824 % o exception: return any errors or warnings in this structure.
827 static MagickBooleanType LoadMagicCache(LinkedListInfo *cache,const char *xml,
828 const char *filename,const size_t depth,ExceptionInfo *exception)
831 keyword[MagickPathExtent],
847 Load the magic map file.
849 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
850 "Loading magic configure file \"%s\" ...",filename);
851 if (xml == (char *) NULL)
854 magic_info=(MagicInfo *) NULL;
855 token=AcquireString(xml);
856 extent=strlen(token)+MagickPathExtent;
857 for (q=(char *) xml; *q != '\0'; )
862 GetNextToken(q,&q,extent,token);
865 (void) CopyMagickString(keyword,token,MagickPathExtent);
866 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
871 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
872 GetNextToken(q,&q,extent,token);
875 if (LocaleNCompare(keyword,"<!--",4) == 0)
880 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
881 GetNextToken(q,&q,extent,token);
884 if (LocaleCompare(keyword,"<include") == 0)
889 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
891 (void) CopyMagickString(keyword,token,MagickPathExtent);
892 GetNextToken(q,&q,extent,token);
895 GetNextToken(q,&q,extent,token);
896 if (LocaleCompare(keyword,"file") == 0)
898 if (depth > MagickMaxRecursionDepth)
899 (void) ThrowMagickException(exception,GetMagickModule(),
900 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
904 path[MagickPathExtent],
907 GetPathComponent(filename,HeadPath,path);
909 (void) ConcatenateMagickString(path,DirectorySeparator,
911 if (*token == *DirectorySeparator)
912 (void) CopyMagickString(path,token,MagickPathExtent);
914 (void) ConcatenateMagickString(path,token,MagickPathExtent);
915 file_xml=FileToXML(path,~0UL);
916 if (xml != (char *) NULL)
918 status&=LoadMagicCache(cache,file_xml,path,depth+1,
920 file_xml=DestroyString(file_xml);
927 if (LocaleCompare(keyword,"<magic") == 0)
932 magic_info=(MagicInfo *) AcquireCriticalMemory(sizeof(*magic_info));
933 (void) memset(magic_info,0,sizeof(*magic_info));
934 magic_info->path=ConstantString(filename);
935 magic_info->exempt=MagickFalse;
936 magic_info->signature=MagickCoreSignature;
939 if (magic_info == (MagicInfo *) NULL)
941 if ((LocaleCompare(keyword,"/>") == 0) ||
942 (LocaleCompare(keyword,"</policy>") == 0))
944 status=InsertValueInSortedLinkedList(cache,CompareMagickInfoSize,
946 if (status == MagickFalse)
947 (void) ThrowMagickException(exception,GetMagickModule(),
948 ResourceLimitError,"MemoryAllocationFailed","`%s'",
950 magic_info=(MagicInfo *) NULL;
953 GetNextToken(q,(const char **) NULL,extent,token);
956 GetNextToken(q,&q,extent,token);
957 GetNextToken(q,&q,extent,token);
963 if (LocaleCompare((char *) keyword,"name") == 0)
965 magic_info->name=ConstantString(token);
973 if (LocaleCompare((char *) keyword,"offset") == 0)
975 magic_info->offset=(MagickOffsetType) StringToLong(token);
983 if (LocaleCompare((char *) keyword,"stealth") == 0)
985 magic_info->stealth=IsStringTrue(token);
993 if (LocaleCompare((char *) keyword,"target") == 0)
998 register unsigned char
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'; )
1013 if (isdigit((int) ((unsigned char) *p)) != 0)
1018 *r++=(unsigned char) strtol(p,&end,8);
1020 magic_info->length++;
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;
1037 magic_info->length++;
1041 if (LocaleNCompare(p,"&",5) == 0)
1042 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
1043 *r++=(unsigned char) (*p++);
1044 magic_info->length++;
1054 token=(char *) RelinquishMagickMemory(token);
1055 return(status != 0 ? MagickTrue : MagickFalse);
1059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 + M a g i c C o m p o n e n t G e n e s i s %
1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 % MagicComponentGenesis() instantiates the magic component.
1071 % The format of the MagicComponentGenesis method is:
1073 % MagickBooleanType MagicComponentGenesis(void)
1076 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
1078 if (magic_semaphore == (SemaphoreInfo *) NULL)
1079 magic_semaphore=AcquireSemaphoreInfo();
1084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1088 + M a g i c C o m p o n e n t T e r m i n u s %
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094 % MagicComponentTerminus() destroys the magic component.
1096 % The format of the MagicComponentTerminus method is:
1098 % MagicComponentTerminus(void)
1102 static void *DestroyMagicElement(void *magic_info)
1107 p=(MagicInfo *) magic_info;
1108 if (p->exempt == MagickFalse)
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);
1119 p=(MagicInfo *) RelinquishMagickMemory(p);
1120 return((void *) NULL);
1123 MagickPrivate void MagicComponentTerminus(void)
1125 if (magic_semaphore == (SemaphoreInfo *) NULL)
1126 ActivateSemaphoreInfo(&magic_semaphore);
1127 LockSemaphoreInfo(magic_semaphore);
1128 if (magic_cache != (LinkedListInfo *) NULL)
1129 magic_cache=DestroyLinkedList(magic_cache,DestroyMagicElement);
1130 UnlockSemaphoreInfo(magic_semaphore);
1131 RelinquishSemaphoreInfo(&magic_semaphore);