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-2014 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 % http://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/hashmap.h"
50 #include "MagickCore/magic.h"
51 #include "MagickCore/magic-private.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/semaphore.h"
54 #include "MagickCore/string_.h"
55 #include "MagickCore/string-private.h"
56 #include "MagickCore/token.h"
57 #include "MagickCore/utility.h"
58 #include "MagickCore/utility-private.h"
59 #include "MagickCore/xml-tree.h"
60 #include "MagickCore/xml-tree-private.h"
65 #define MagicFilename "magic.xml"
66 #define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
71 typedef struct _MagicMapInfo
76 const MagickOffsetType
89 static const MagicMapInfo
92 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
93 { "8BIMTEXT", 0, MagickString("8BIM#") },
94 { "8BIM", 0, MagickString("8BIM") },
95 { "BMP", 0, MagickString("BA") },
96 { "BMP", 0, MagickString("BM") },
97 { "BMP", 0, MagickString("CI") },
98 { "BMP", 0, MagickString("CP") },
99 { "BMP", 0, MagickString("IC") },
100 { "PICT", 0, MagickString("PICT") },
101 { "BMP", 0, MagickString("PI") },
102 { "CALS", 21, MagickString("version: MIL-STD-1840") },
103 { "CALS", 0, MagickString("srcdocid:") },
104 { "CALS", 9, MagickString("srcdocid:") },
105 { "CALS", 8, MagickString("rorient:") },
106 { "CGM", 0, MagickString("BEGMF") },
107 { "CIN", 0, MagickString("\200\052\137\327") },
108 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
109 { "DCM", 128, MagickString("DICM") },
110 { "DCX", 0, MagickString("\261\150\336\72") },
111 { "DIB", 0, MagickString("\050\000") },
112 { "DDS", 0, MagickString("DDS ") },
113 { "DJVU", 0, MagickString("AT&TFORM") },
114 { "DOT", 0, MagickString("digraph") },
115 { "DPX", 0, MagickString("SDPX") },
116 { "DPX", 0, MagickString("XPDS") },
117 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
118 { "EPT", 0, MagickString("\305\320\323\306") },
119 { "EXR", 0, MagickString("\166\057\061\001") },
120 { "FAX", 0, MagickString("DFAX") },
121 { "FIG", 0, MagickString("#FIG") },
122 { "FITS", 0, MagickString("IT0") },
123 { "FITS", 0, MagickString("SIMPLE") },
124 { "FPX", 0, MagickString("\320\317\021\340") },
125 { "GIF", 0, MagickString("GIF8") },
126 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
127 { "HDF", 1, MagickString("HDF") },
128 { "HDR", 0, MagickString("#?RADIANCE") },
129 { "HDR", 0, MagickString("#?RGBE") },
130 { "HPGL", 0, MagickString("IN;") },
131 { "HTML", 1, MagickString("HTML") },
132 { "HTML", 1, MagickString("html") },
133 { "ILBM", 8, MagickString("ILBM") },
134 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
135 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
136 { "IPTC", 0, MagickString("\034\002") },
137 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
138 { "JPEG", 0, MagickString("\377\330\377") },
139 { "J2K", 0, MagickString("\xff\x4f\xff\x51") },
140 { "JPC", 0, MagickString("\x0d\x0a\x87\x0a") },
141 { "JP2", 4, MagickString("\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a") },
142 { "MAT", 0, MagickString("MATLAB 5.0 MAT-file,") },
143 { "MIFF", 0, MagickString("Id=ImageMagick") },
144 { "MIFF", 0, MagickString("id=ImageMagick") },
145 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
146 { "MPC", 0, MagickString("id=MagickCache") },
147 { "MPEG", 0, MagickString("\000\000\001\263") },
148 { "MRW", 0, MagickString("\x00MRM") },
149 { "MVG", 0, MagickString("push graphic-context") },
150 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
151 { "PCD", 2048, MagickString("PCD_") },
152 { "PCL", 0, MagickString("\033E\033") },
153 { "PCX", 0, MagickString("\012\002") },
154 { "PCX", 0, MagickString("\012\005") },
155 { "PDB", 60, MagickString("vIMGView") },
156 { "PDF", 0, MagickString("%PDF-") },
157 { "PES", 0, MagickString("#PES") },
158 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
159 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
160 { "PGX", 0, MagickString("\050\107\020\115\046") },
161 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
162 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
163 { "PBM", 0, MagickString("P1") },
164 { "PGM", 0, MagickString("P2") },
165 { "PPM", 0, MagickString("P3") },
166 { "PBM", 0, MagickString("P4") },
167 { "PGM", 0, MagickString("P5") },
168 { "PPM", 0, MagickString("P6") },
169 { "PAM", 0, MagickString("P7") },
170 { "PFM", 0, MagickString("PF") },
171 { "PFM", 0, MagickString("Pf") },
172 { "PS", 0, MagickString("%!") },
173 { "PS", 0, MagickString("\004%!") },
174 { "PS", 0, MagickString("\305\320\323\306") },
175 { "PSB", 0, MagickString("8BPB") },
176 { "PSD", 0, MagickString("8BPS") },
177 { "PWP", 0, MagickString("SFW95") },
178 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
179 { "RLE", 0, MagickString("\122\314") },
180 { "SCT", 0, MagickString("CT") },
181 { "SFW", 0, MagickString("SFW94") },
182 { "SGI", 0, MagickString("\001\332") },
183 { "SUN", 0, MagickString("\131\246\152\225") },
184 { "SVG", 1, MagickString("?XML") },
185 { "SVG", 1, MagickString("?xml") },
186 { "TIFF", 0, MagickString("\115\115\000\052") },
187 { "TIFF", 0, MagickString("\111\111\052\000") },
188 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
189 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
190 { "TTF", 0, MagickString("\000\001\000\000\000") },
191 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
192 { "VICAR", 0, MagickString("LBLSIZE") },
193 { "VICAR", 0, MagickString("NJPL1I") },
194 { "VIFF", 0, MagickString("\253\001") },
195 { "WEBP", 8, MagickString("WEBP") },
196 { "WMF", 0, MagickString("\327\315\306\232") },
197 { "WMF", 0, MagickString("\001\000\011\000") },
198 { "WPG", 0, MagickString("\377WPC") },
199 { "XBM", 0, MagickString("#define") },
200 { "XCF", 0, MagickString("gimp xcf") },
201 { "XEF", 0, MagickString("FOVb") },
202 { "XPM", 1, MagickString("* XPM *") },
203 { "XWD", 4, MagickString("\007\000\000") },
204 { "XWD", 5, MagickString("\000\000\007") }
207 static LinkedListInfo
208 *magic_cache = (LinkedListInfo *) NULL;
211 *magic_semaphore = (SemaphoreInfo *) NULL;
214 Forward declarations.
216 static MagickBooleanType
217 IsMagicCacheInstantiated(ExceptionInfo *),
218 LoadMagicCache(LinkedListInfo *,const char *,const char *,const size_t,
222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 % A c q u i r e M a g i c L i s t s %
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 % AcquireMagicCache() caches one or more magic configurations which provides a
233 % mapping between magic attributes and a magic name.
235 % The format of the AcquireMagicCache method is:
237 % LinkedListInfo *AcquireMagicCache(const char *filename,
238 % ExceptionInfo *exception)
240 % A description of each parameter follows:
242 % o filename: the font file name.
244 % o exception: return any errors or warnings in this structure.
247 static LinkedListInfo *AcquireMagicCache(const char *filename,
248 ExceptionInfo *exception)
267 Load external magic map.
269 magic_cache=NewLinkedList(0);
270 if (magic_cache == (LinkedListInfo *) NULL)
271 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
274 options=GetConfigureOptions(filename,exception);
275 option=(const StringInfo *) GetNextValueInLinkedList(options);
276 while (option != (const StringInfo *) NULL)
278 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
279 status&=LoadMagicCache(magic_cache,(const char *)
280 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
281 option=(const StringInfo *) GetNextValueInLinkedList(options);
283 options=DestroyConfigureOptions(options);
285 Load built-in magic map.
287 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
292 register const MagicMapInfo
296 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
297 if (magic_info == (MagicInfo *) NULL)
299 (void) ThrowMagickException(exception,GetMagickModule(),
300 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
303 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
304 magic_info->path=(char *) "[built-in]";
305 magic_info->name=(char *) p->name;
306 magic_info->offset=p->offset;
307 magic_info->target=(char *) p->magic;
308 magic_info->magic=(unsigned char *) p->magic;
309 magic_info->length=p->length;
310 magic_info->exempt=MagickTrue;
311 magic_info->signature=MagickSignature;
312 status&=AppendValueToLinkedList(magic_cache,magic_info);
313 if (status == MagickFalse)
314 (void) ThrowMagickException(exception,GetMagickModule(),
315 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 + G e t M a g i c I n f o %
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331 % GetMagicInfo() searches the magic list for the specified name and if found
332 % returns attributes for that magic.
334 % The format of the GetMagicInfo method is:
336 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
337 % const size_t length,ExceptionInfo *exception)
339 % A description of each parameter follows:
341 % o magic: A binary string generally representing the first few characters
342 % of the image file or blob.
344 % o length: the length of the binary signature.
346 % o exception: return any errors or warnings in this structure.
349 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
350 const size_t length,ExceptionInfo *exception)
352 register const MagicInfo
355 assert(exception != (ExceptionInfo *) NULL);
356 if (IsMagicCacheInstantiated(exception) == MagickFalse)
357 return((const MagicInfo *) NULL);
359 Search for magic tag.
361 LockSemaphoreInfo(magic_semaphore);
362 ResetLinkedListIterator(magic_cache);
363 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
364 if (magic == (const unsigned char *) NULL)
366 UnlockSemaphoreInfo(magic_semaphore);
369 while (p != (const MagicInfo *) NULL)
371 assert(p->offset >= 0);
372 if (((size_t) (p->offset+p->length) <= length) &&
373 (memcmp(magic+p->offset,p->magic,p->length) == 0))
375 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
377 if (p != (const MagicInfo *) NULL)
378 (void) InsertValueInLinkedList(magic_cache,0,
379 RemoveElementByValueFromLinkedList(magic_cache,p));
380 UnlockSemaphoreInfo(magic_semaphore);
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 % G e t M a g i c I n f o L i s t %
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 % GetMagicInfoList() returns any image aliases that match the specified
398 % The magic of the GetMagicInfoList function is:
400 % const MagicInfo **GetMagicInfoList(const char *pattern,
401 % size_t *number_aliases,ExceptionInfo *exception)
403 % A description of each parameter follows:
405 % o pattern: Specifies a pointer to a text string containing a pattern.
407 % o number_aliases: This integer returns the number of aliases in the list.
409 % o exception: return any errors or warnings in this structure.
413 #if defined(__cplusplus) || defined(c_plusplus)
417 static int MagicInfoCompare(const void *x,const void *y)
423 p=(const MagicInfo **) x,
424 q=(const MagicInfo **) y;
425 if (LocaleCompare((*p)->path,(*q)->path) == 0)
426 return(LocaleCompare((*p)->name,(*q)->name));
427 return(LocaleCompare((*p)->path,(*q)->path));
430 #if defined(__cplusplus) || defined(c_plusplus)
434 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
435 size_t *number_aliases,ExceptionInfo *exception)
440 register const MagicInfo
449 assert(pattern != (char *) NULL);
450 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
451 assert(number_aliases != (size_t *) NULL);
453 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
454 if (p == (const MagicInfo *) NULL)
455 return((const MagicInfo **) NULL);
456 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
457 GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
458 if (aliases == (const MagicInfo **) NULL)
459 return((const MagicInfo **) NULL);
463 LockSemaphoreInfo(magic_semaphore);
464 ResetLinkedListIterator(magic_cache);
465 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
466 for (i=0; p != (const MagicInfo *) NULL; )
468 if ((p->stealth == MagickFalse) &&
469 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
471 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
473 UnlockSemaphoreInfo(magic_semaphore);
474 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
475 aliases[i]=(MagicInfo *) NULL;
476 *number_aliases=(size_t) i;
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 % G e t M a g i c L i s t %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491 % GetMagicList() returns any image format aliases that match the specified
494 % The format of the GetMagicList function is:
496 % char **GetMagicList(const char *pattern,size_t *number_aliases,
497 % ExceptionInfo *exception)
499 % A description of each parameter follows:
501 % o pattern: Specifies a pointer to a text string containing a pattern.
503 % o number_aliases: This integer returns the number of image format aliases
506 % o exception: return any errors or warnings in this structure.
510 #if defined(__cplusplus) || defined(c_plusplus)
514 static int MagicCompare(const void *x,const void *y)
522 return(LocaleCompare(p,q));
525 #if defined(__cplusplus) || defined(c_plusplus)
529 MagickExport char **GetMagicList(const char *pattern,size_t *number_aliases,
530 ExceptionInfo *exception)
535 register const MagicInfo
542 Allocate configure list.
544 assert(pattern != (char *) NULL);
545 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
546 assert(number_aliases != (size_t *) NULL);
548 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
549 if (p == (const MagicInfo *) NULL)
550 return((char **) NULL);
551 aliases=(char **) AcquireQuantumMemory((size_t)
552 GetNumberOfElementsInLinkedList(magic_cache)+1UL,sizeof(*aliases));
553 if (aliases == (char **) NULL)
554 return((char **) NULL);
555 LockSemaphoreInfo(magic_semaphore);
556 ResetLinkedListIterator(magic_cache);
557 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
558 for (i=0; p != (const MagicInfo *) NULL; )
560 if ((p->stealth == MagickFalse) &&
561 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
562 aliases[i++]=ConstantString(p->name);
563 p=(const MagicInfo *) GetNextValueInLinkedList(magic_cache);
565 UnlockSemaphoreInfo(magic_semaphore);
566 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
567 aliases[i]=(char *) NULL;
568 *number_aliases=(size_t) i;
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 % G e t M a g i c N a m e %
581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 % GetMagicName() returns the name associated with the magic.
585 % The format of the GetMagicName method is:
587 % const char *GetMagicName(const MagicInfo *magic_info)
589 % A description of each parameter follows:
591 % o magic_info: The magic info.
594 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
596 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
597 assert(magic_info != (MagicInfo *) NULL);
598 assert(magic_info->signature == MagickSignature);
599 return(magic_info->name);
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 + I s M a g i c C a c h e I n s t a n t i a t e d %
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
613 % IsMagicCacheInstantiated() determines if the magic list is instantiated.
614 % If not, it instantiates the list and returns it.
616 % The format of the IsMagicInstantiated method is:
618 % MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
620 % A description of each parameter follows.
622 % o exception: return any errors or warnings in this structure.
625 static MagickBooleanType IsMagicCacheInstantiated(ExceptionInfo *exception)
627 if (magic_cache == (LinkedListInfo *) NULL)
629 if (magic_semaphore == (SemaphoreInfo *) NULL)
630 ActivateSemaphoreInfo(&magic_semaphore);
631 LockSemaphoreInfo(magic_semaphore);
632 if (magic_cache == (LinkedListInfo *) NULL)
633 magic_cache=AcquireMagicCache(MagicFilename,exception);
634 UnlockSemaphoreInfo(magic_semaphore);
636 return(magic_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 % L i s t M a g i c I n f o %
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 % ListMagicInfo() lists the magic info to a file.
652 % The format of the ListMagicInfo method is:
654 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
656 % A description of each parameter follows.
658 % o file: An pointer to a FILE.
660 % o exception: return any errors or warnings in this structure.
663 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
664 ExceptionInfo *exception)
681 if (file == (const FILE *) NULL)
683 magic_info=GetMagicInfoList("*",&number_aliases,exception);
684 if (magic_info == (const MagicInfo **) NULL)
687 path=(const char *) NULL;
688 for (i=0; i < (ssize_t) number_aliases; i++)
690 if (magic_info[i]->stealth != MagickFalse)
692 if ((path == (const char *) NULL) ||
693 (LocaleCompare(path,magic_info[i]->path) != 0))
695 if (magic_info[i]->path != (char *) NULL)
696 (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
697 (void) FormatLocaleFile(file,"Name Offset Target\n");
698 (void) FormatLocaleFile(file,
699 "-------------------------------------------------"
700 "------------------------------\n");
702 path=magic_info[i]->path;
703 (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
704 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
705 (void) FormatLocaleFile(file," ");
706 (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
707 if (magic_info[i]->target != (char *) NULL)
712 for (j=0; magic_info[i]->target[j] != '\0'; j++)
713 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
714 (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
716 (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
717 ((unsigned char) magic_info[i]->target[j]));
719 (void) FormatLocaleFile(file,"\n");
722 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 + L o a d M a g i c L i s t %
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 % LoadMagicCache() loads the magic configurations which provides a mapping
738 % between magic attributes and a magic name.
740 % The format of the LoadMagicCache method is:
742 % MagickBooleanType LoadMagicCache(LinkedListInfo *magic_cache,
743 % const char *xml,const char *filename,const size_t depth,
744 % ExceptionInfo *exception)
746 % A description of each parameter follows:
748 % o xml: The magic list in XML format.
750 % o filename: The magic list filename.
752 % o depth: depth of <include /> statements.
754 % o exception: return any errors or warnings in this structure.
757 static MagickBooleanType LoadMagicCache(LinkedListInfo *magic_cache,
758 const char *xml,const char *filename,const size_t depth,
759 ExceptionInfo *exception)
762 keyword[MaxTextExtent],
775 Load the magic map file.
777 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
778 "Loading magic configure file \"%s\" ...",filename);
779 if (xml == (char *) NULL)
782 magic_info=(MagicInfo *) NULL;
783 token=AcquireString(xml);
784 for (q=(char *) xml; *q != '\0'; )
789 GetMagickToken(q,&q,token);
792 (void) CopyMagickString(keyword,token,MaxTextExtent);
793 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
798 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
799 GetMagickToken(q,&q,token);
802 if (LocaleNCompare(keyword,"<!--",4) == 0)
807 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
808 GetMagickToken(q,&q,token);
811 if (LocaleCompare(keyword,"<include") == 0)
816 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
818 (void) CopyMagickString(keyword,token,MaxTextExtent);
819 GetMagickToken(q,&q,token);
822 GetMagickToken(q,&q,token);
823 if (LocaleCompare(keyword,"file") == 0)
826 (void) ThrowMagickException(exception,GetMagickModule(),
827 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
834 GetPathComponent(filename,HeadPath,path);
836 (void) ConcatenateMagickString(path,DirectorySeparator,
838 if (*token == *DirectorySeparator)
839 (void) CopyMagickString(path,token,MaxTextExtent);
841 (void) ConcatenateMagickString(path,token,MaxTextExtent);
842 xml=FileToXML(path,~0UL);
843 if (xml != (char *) NULL)
845 status&=LoadMagicCache(magic_cache,xml,path,depth+1,
847 xml=(char *) RelinquishMagickMemory(xml);
854 if (LocaleCompare(keyword,"<magic") == 0)
859 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
860 if (magic_info == (MagicInfo *) NULL)
861 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
862 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
863 magic_info->path=ConstantString(filename);
864 magic_info->exempt=MagickFalse;
865 magic_info->signature=MagickSignature;
868 if (magic_info == (MagicInfo *) NULL)
870 if (LocaleCompare(keyword,"/>") == 0)
872 status=AppendValueToLinkedList(magic_cache,magic_info);
873 if (status == MagickFalse)
874 (void) ThrowMagickException(exception,GetMagickModule(),
875 ResourceLimitError,"MemoryAllocationFailed","`%s'",
877 magic_info=(MagicInfo *) NULL;
880 GetMagickToken(q,(const char **) NULL,token);
883 GetMagickToken(q,&q,token);
884 GetMagickToken(q,&q,token);
890 if (LocaleCompare((char *) keyword,"name") == 0)
892 magic_info->name=ConstantString(token);
900 if (LocaleCompare((char *) keyword,"offset") == 0)
902 magic_info->offset=(MagickOffsetType) StringToLong(token);
910 if (LocaleCompare((char *) keyword,"stealth") == 0)
912 magic_info->stealth=IsStringTrue(token);
920 if (LocaleCompare((char *) keyword,"target") == 0)
925 register unsigned char
931 length=strlen(token);
932 magic_info->target=ConstantString(token);
933 magic_info->magic=(unsigned char *) ConstantString(token);
935 for (p=magic_info->target; *p != '\0'; )
940 if (isdigit((int) ((unsigned char) *p)) != 0)
945 *q++=(unsigned char) strtol(p,&end,8);
947 magic_info->length++;
952 case 'b': *q='\b'; break;
953 case 'f': *q='\f'; break;
954 case 'n': *q='\n'; break;
955 case 'r': *q='\r'; break;
956 case 't': *q='\t'; break;
957 case 'v': *q='\v'; break;
958 case 'a': *q='a'; break;
959 case '?': *q='\?'; break;
960 default: *q=(unsigned char) (*p); break;
964 magic_info->length++;
968 if (LocaleNCompare(p,"&",5) == 0)
969 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
970 *q++=(unsigned char) (*p++);
971 magic_info->length++;
981 token=(char *) RelinquishMagickMemory(token);
986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990 + M a g i c C o m p o n e n t G e n e s i s %
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 % MagicComponentGenesis() instantiates the magic component.
998 % The format of the MagicComponentGenesis method is:
1000 % MagickBooleanType MagicComponentGenesis(void)
1003 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
1005 if (magic_semaphore == (SemaphoreInfo *) NULL)
1006 magic_semaphore=AcquireSemaphoreInfo();
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1015 + M a g i c C o m p o n e n t T e r m i n u s %
1019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1021 % MagicComponentTerminus() destroys the magic component.
1023 % The format of the MagicComponentTerminus method is:
1025 % MagicComponentTerminus(void)
1029 static void *DestroyMagicElement(void *magic_info)
1034 p=(MagicInfo *) magic_info;
1035 if (p->exempt == MagickFalse)
1037 if (p->path != (char *) NULL)
1038 p->path=DestroyString(p->path);
1039 if (p->name != (char *) NULL)
1040 p->name=DestroyString(p->name);
1041 if (p->target != (char *) NULL)
1042 p->target=DestroyString(p->target);
1043 if (p->magic != (unsigned char *) NULL)
1044 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1046 p=(MagicInfo *) RelinquishMagickMemory(p);
1047 return((void *) NULL);
1050 MagickPrivate void MagicComponentTerminus(void)
1052 if (magic_semaphore == (SemaphoreInfo *) NULL)
1053 ActivateSemaphoreInfo(&magic_semaphore);
1054 LockSemaphoreInfo(magic_semaphore);
1055 if (magic_cache != (LinkedListInfo *) NULL)
1056 magic_cache=DestroyLinkedList(magic_cache,DestroyMagicElement);
1057 UnlockSemaphoreInfo(magic_semaphore);
1058 RelinquishSemaphoreInfo(&magic_semaphore);