2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % M M AAA GGGG IIIII CCCC %
7 % M M M AAAAA G GGG I C %
9 % M M A A GGGG IIIII CCCC %
12 % MagickCore Image Magic Methods %
19 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
25 % http://www.imagemagick.org/script/license.php %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 #include "magick/studio.h"
42 #include "magick/blob.h"
43 #include "magick/client.h"
44 #include "magick/configure.h"
45 #include "magick/exception.h"
46 #include "magick/exception-private.h"
47 #include "magick/hashmap.h"
48 #include "magick/magic.h"
49 #include "magick/memory_.h"
50 #include "magick/semaphore.h"
51 #include "magick/string_.h"
52 #include "magick/string-private.h"
53 #include "magick/token.h"
54 #include "magick/utility.h"
55 #include "magick/xml-tree.h"
60 #define MagicFilename "magic.xml"
61 #define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
66 typedef struct _MagicMapInfo
71 const MagickOffsetType
84 static const MagicMapInfo
87 { "AVI", 0, MagickString("RIFF") },
88 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
89 { "8BIMTEXT", 0, MagickString("8BIM#") },
90 { "8BIM", 0, MagickString("8BIM") },
91 { "BMP", 0, MagickString("BA") },
92 { "BMP", 0, MagickString("BM") },
93 { "BMP", 0, MagickString("CI") },
94 { "BMP", 0, MagickString("CP") },
95 { "BMP", 0, MagickString("IC") },
96 { "BMP", 0, MagickString("PI") },
97 { "CALS", 21, MagickString("version: MIL-STD-1840") },
98 { "CALS", 0, MagickString("srcdocid:") },
99 { "CALS", 9, MagickString("srcdocid:") },
100 { "CALS", 8, MagickString("rorient:") },
101 { "CGM", 0, MagickString("BEGMF") },
102 { "CIN", 0, MagickString("\200\052\137\327") },
103 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
104 { "DCM", 128, MagickString("DICM") },
105 { "DCX", 0, MagickString("\261\150\336\72") },
106 { "DIB", 0, MagickString("\050\000") },
107 { "DDS", 0, MagickString("DDS ") },
108 { "DJVU", 0, MagickString("AT&TFORM") },
109 { "DOT", 0, MagickString("digraph") },
110 { "DPX", 0, MagickString("SDPX") },
111 { "DPX", 0, MagickString("XPDS") },
112 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
113 { "EPT", 0, MagickString("\305\320\323\306") },
114 { "EXR", 0, MagickString("\166\057\061\001") },
115 { "FAX", 0, MagickString("DFAX") },
116 { "FIG", 0, MagickString("#FIG") },
117 { "FITS", 0, MagickString("IT0") },
118 { "FITS", 0, MagickString("SIMPLE") },
119 { "FPX", 0, MagickString("\320\317\021\340") },
120 { "GIF", 0, MagickString("GIF8") },
121 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
122 { "HDF", 1, MagickString("HDF") },
123 { "HDR", 0, MagickString("#?RADIANCE") },
124 { "HDR", 0, MagickString("#?RGBE") },
125 { "HPGL", 0, MagickString("IN;") },
126 { "HTML", 1, MagickString("HTML") },
127 { "HTML", 1, MagickString("html") },
128 { "ILBM", 8, MagickString("ILBM") },
129 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
130 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
131 { "IPTC", 0, MagickString("\034\002") },
132 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
133 { "JPEG", 0, MagickString("\377\330\377") },
134 { "JPC", 0, MagickString("\377\117") },
135 { "JP2", 4, MagickString("\152\120\040\040\015") },
136 { "MAT", 0, MagickString("MATLAB 5.0 MAT-file,") },
137 { "MIFF", 0, MagickString("Id=ImageMagick") },
138 { "MIFF", 0, MagickString("id=ImageMagick") },
139 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
140 { "MPC", 0, MagickString("id=MagickCache") },
141 { "MPEG", 0, MagickString("\000\000\001\263") },
142 { "MRW", 0, MagickString("\x00MRM") },
143 { "MVG", 0, MagickString("push graphic-context") },
144 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
145 { "PCD", 2048, MagickString("PCD_") },
146 { "PCL", 0, MagickString("\033E\033") },
147 { "PCX", 0, MagickString("\012\002") },
148 { "PCX", 0, MagickString("\012\005") },
149 { "PDB", 60, MagickString("vIMGView") },
150 { "PDF", 0, MagickString("%PDF-") },
151 { "PES", 0, MagickString("#PES") },
152 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
153 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
154 { "PGX", 0, MagickString("\050\107\020\115\046") },
155 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
156 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
157 { "PBM", 0, MagickString("P1") },
158 { "PGM", 0, MagickString("P2") },
159 { "PPM", 0, MagickString("P3") },
160 { "PBM", 0, MagickString("P4") },
161 { "PGM", 0, MagickString("P5") },
162 { "PPM", 0, MagickString("P6") },
163 { "PAM", 0, MagickString("P7") },
164 { "PFM", 0, MagickString("PF") },
165 { "PFM", 0, MagickString("Pf") },
166 { "PS", 0, MagickString("%!") },
167 { "PS", 0, MagickString("\004%!") },
168 { "PS", 0, MagickString("\305\320\323\306") },
169 { "PSB", 0, MagickString("8BPB") },
170 { "PSD", 0, MagickString("8BPS") },
171 { "PWP", 0, MagickString("SFW95") },
172 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
173 { "RLE", 0, MagickString("\122\314") },
174 { "SCT", 0, MagickString("CT") },
175 { "SFW", 0, MagickString("SFW94") },
176 { "SGI", 0, MagickString("\001\332") },
177 { "SUN", 0, MagickString("\131\246\152\225") },
178 { "SVG", 1, MagickString("?XML") },
179 { "SVG", 1, MagickString("?xml") },
180 { "TIFF", 0, MagickString("\115\115\000\052") },
181 { "TIFF", 0, MagickString("\111\111\052\000") },
182 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
183 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
184 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
185 { "VICAR", 0, MagickString("LBLSIZE") },
186 { "VICAR", 0, MagickString("NJPL1I") },
187 { "VIFF", 0, MagickString("\253\001") },
188 { "WEBP", 8, MagickString("WEBP") },
189 { "WMF", 0, MagickString("\327\315\306\232") },
190 { "WMF", 0, MagickString("\001\000\011\000") },
191 { "WPG", 0, MagickString("\377WPC") },
192 { "XBM", 0, MagickString("#define") },
193 { "XCF", 0, MagickString("gimp xcf") },
194 { "XEF", 0, MagickString("FOVb") },
195 { "XPM", 1, MagickString("* XPM *") },
196 { "XWD", 4, MagickString("\007\000\000") },
197 { "XWD", 5, MagickString("\000\000\007") }
200 static LinkedListInfo
201 *magic_list = (LinkedListInfo *) NULL;
204 *magic_semaphore = (SemaphoreInfo *) NULL;
206 static volatile MagickBooleanType
207 instantiate_magic = MagickFalse;
210 Forward declarations.
212 static MagickBooleanType
213 InitializeMagicList(ExceptionInfo *),
214 LoadMagicLists(const char *,ExceptionInfo *);
217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 + G e t M a g i c I n f o %
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 % GetMagicInfo() searches the magic list for the specified name and if found
228 % returns attributes for that magic.
230 % The format of the GetMagicInfo method is:
232 % const MagicInfo *GetMagicInfo(const unsigned char *magic,
233 % const size_t length,ExceptionInfo *exception)
235 % A description of each parameter follows:
237 % o magic: A binary string generally representing the first few characters
238 % of the image file or blob.
240 % o length: the length of the binary signature.
242 % o exception: return any errors or warnings in this structure.
245 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
246 const size_t length,ExceptionInfo *exception)
248 register const MagicInfo
251 assert(exception != (ExceptionInfo *) NULL);
252 if ((magic_list == (LinkedListInfo *) NULL) ||
253 (instantiate_magic == MagickFalse))
254 if (InitializeMagicList(exception) == MagickFalse)
255 return((const MagicInfo *) NULL);
256 if ((magic_list == (LinkedListInfo *) NULL) ||
257 (IsLinkedListEmpty(magic_list) != MagickFalse))
258 return((const MagicInfo *) NULL);
259 if (magic == (const unsigned char *) NULL)
260 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
262 return((const MagicInfo *) NULL);
264 Search for magic tag.
266 LockSemaphoreInfo(magic_semaphore);
267 ResetLinkedListIterator(magic_list);
268 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
269 while (p != (const MagicInfo *) NULL)
271 assert(p->offset >= 0);
272 if (((size_t) (p->offset+p->length) <= length) &&
273 (memcmp(magic+p->offset,p->magic,p->length) == 0))
275 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
277 if (p != (const MagicInfo *) NULL)
278 (void) InsertValueInLinkedList(magic_list,0,
279 RemoveElementByValueFromLinkedList(magic_list,p));
280 UnlockSemaphoreInfo(magic_semaphore);
285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 % G e t M a g i c I n f o L i s t %
293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295 % GetMagicInfoList() returns any image aliases that match the specified
298 % The magic of the GetMagicInfoList function is:
300 % const MagicInfo **GetMagicInfoList(const char *pattern,
301 % size_t *number_aliases,ExceptionInfo *exception)
303 % A description of each parameter follows:
305 % o pattern: Specifies a pointer to a text string containing a pattern.
307 % o number_aliases: This integer returns the number of aliases in the list.
309 % o exception: return any errors or warnings in this structure.
313 #if defined(__cplusplus) || defined(c_plusplus)
317 static int MagicInfoCompare(const void *x,const void *y)
323 p=(const MagicInfo **) x,
324 q=(const MagicInfo **) y;
325 if (LocaleCompare((*p)->path,(*q)->path) == 0)
326 return(LocaleCompare((*p)->name,(*q)->name));
327 return(LocaleCompare((*p)->path,(*q)->path));
330 #if defined(__cplusplus) || defined(c_plusplus)
334 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
335 size_t *number_aliases,ExceptionInfo *exception)
340 register const MagicInfo
349 assert(pattern != (char *) NULL);
350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
351 assert(number_aliases != (size_t *) NULL);
353 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
354 if (p == (const MagicInfo *) NULL)
355 return((const MagicInfo **) NULL);
356 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
357 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
358 if (aliases == (const MagicInfo **) NULL)
359 return((const MagicInfo **) NULL);
363 LockSemaphoreInfo(magic_semaphore);
364 ResetLinkedListIterator(magic_list);
365 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
366 for (i=0; p != (const MagicInfo *) NULL; )
368 if ((p->stealth == MagickFalse) &&
369 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
371 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
373 UnlockSemaphoreInfo(magic_semaphore);
374 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
375 aliases[i]=(MagicInfo *) NULL;
376 *number_aliases=(size_t) i;
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % G e t M a g i c L i s t %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 % GetMagicList() returns any image format aliases that match the specified
394 % The format of the GetMagicList function is:
396 % char **GetMagicList(const char *pattern,size_t *number_aliases,
397 % ExceptionInfo *exception)
399 % A description of each parameter follows:
401 % o pattern: Specifies a pointer to a text string containing a pattern.
403 % o number_aliases: This integer returns the number of image format aliases
406 % o exception: return any errors or warnings in this structure.
410 #if defined(__cplusplus) || defined(c_plusplus)
414 static int MagicCompare(const void *x,const void *y)
422 return(LocaleCompare(p,q));
425 #if defined(__cplusplus) || defined(c_plusplus)
429 MagickExport char **GetMagicList(const char *pattern,
430 size_t *number_aliases,ExceptionInfo *exception)
435 register const MagicInfo
442 Allocate configure list.
444 assert(pattern != (char *) NULL);
445 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
446 assert(number_aliases != (size_t *) NULL);
448 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
449 if (p == (const MagicInfo *) NULL)
450 return((char **) NULL);
451 aliases=(char **) AcquireQuantumMemory((size_t)
452 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
453 if (aliases == (char **) NULL)
454 return((char **) NULL);
455 LockSemaphoreInfo(magic_semaphore);
456 ResetLinkedListIterator(magic_list);
457 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
458 for (i=0; p != (const MagicInfo *) NULL; )
460 if ((p->stealth == MagickFalse) &&
461 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
462 aliases[i++]=ConstantString(p->name);
463 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
465 UnlockSemaphoreInfo(magic_semaphore);
466 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
467 aliases[i]=(char *) NULL;
468 *number_aliases=(size_t) i;
473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 % G e t M a g i c N a m e %
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 % GetMagicName() returns the name associated with the magic.
485 % The format of the GetMagicName method is:
487 % const char *GetMagicName(const MagicInfo *magic_info)
489 % A description of each parameter follows:
491 % o magic_info: The magic info.
494 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
496 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
497 assert(magic_info != (MagicInfo *) NULL);
498 assert(magic_info->signature == MagickSignature);
499 return(magic_info->name);
503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 + I n i t i a l i z e M a g i c L i s t %
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 % InitializeMagicList() initializes the magic list.
515 % The format of the InitializeMagicList method is:
517 % MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
519 % A description of each parameter follows.
521 % o exception: return any errors or warnings in this structure.
524 static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
526 if ((magic_list == (LinkedListInfo *) NULL) &&
527 (instantiate_magic == MagickFalse))
529 if (magic_semaphore == (SemaphoreInfo *) NULL)
530 AcquireSemaphoreInfo(&magic_semaphore);
531 LockSemaphoreInfo(magic_semaphore);
532 if ((magic_list == (LinkedListInfo *) NULL) &&
533 (instantiate_magic == MagickFalse))
535 (void) LoadMagicLists(MagicFilename,exception);
536 instantiate_magic=MagickTrue;
538 UnlockSemaphoreInfo(magic_semaphore);
540 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548 % L i s t M a g i c I n f o %
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 % ListMagicInfo() lists the magic info to a file.
556 % The format of the ListMagicInfo method is:
558 % MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
560 % A description of each parameter follows.
562 % o file: An pointer to a FILE.
564 % o exception: return any errors or warnings in this structure.
567 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
568 ExceptionInfo *exception)
585 if (file == (const FILE *) NULL)
587 magic_info=GetMagicInfoList("*",&number_aliases,exception);
588 if (magic_info == (const MagicInfo **) NULL)
591 path=(const char *) NULL;
592 for (i=0; i < (ssize_t) number_aliases; i++)
594 if (magic_info[i]->stealth != MagickFalse)
596 if ((path == (const char *) NULL) ||
597 (LocaleCompare(path,magic_info[i]->path) != 0))
599 if (magic_info[i]->path != (char *) NULL)
600 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
601 (void) fprintf(file,"Name Offset Target\n");
602 (void) fprintf(file,"-------------------------------------------------"
603 "------------------------------\n");
605 path=magic_info[i]->path;
606 (void) fprintf(file,"%s",magic_info[i]->name);
607 for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
608 (void) fprintf(file," ");
609 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
610 if (magic_info[i]->target != (char *) NULL)
615 for (j=0; magic_info[i]->target[j] != '\0'; j++)
616 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
617 (void) fprintf(file,"%c",magic_info[i]->target[j]);
619 (void) fprintf(file,"\\%03o",(unsigned int)
620 ((unsigned char) magic_info[i]->target[j]));
622 (void) fprintf(file,"\n");
625 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634 + L o a d M a g i c L i s t %
638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 % LoadMagicList() loads the magic configuration file which provides a mapping
641 % between magic attributes and a magic name.
643 % The format of the LoadMagicList method is:
645 % MagickBooleanType LoadMagicList(const char *xml,const char *filename,
646 % const size_t depth,ExceptionInfo *exception)
648 % A description of each parameter follows:
650 % o xml: The magic list in XML format.
652 % o filename: The magic list filename.
654 % o depth: depth of <include /> statements.
656 % o exception: return any errors or warnings in this structure.
659 static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
660 const size_t depth,ExceptionInfo *exception)
663 keyword[MaxTextExtent],
676 Load the magic map file.
678 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
679 "Loading magic configure file \"%s\" ...",filename);
680 if (xml == (char *) NULL)
682 if (magic_list == (LinkedListInfo *) NULL)
684 magic_list=NewLinkedList(0);
685 if (magic_list == (LinkedListInfo *) NULL)
687 ThrowFileException(exception,ResourceLimitError,
688 "MemoryAllocationFailed",filename);
693 magic_info=(MagicInfo *) NULL;
694 token=AcquireString(xml);
695 for (q=(char *) xml; *q != '\0'; )
700 GetMagickToken(q,&q,token);
703 (void) CopyMagickString(keyword,token,MaxTextExtent);
704 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
709 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
710 GetMagickToken(q,&q,token);
713 if (LocaleNCompare(keyword,"<!--",4) == 0)
718 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
719 GetMagickToken(q,&q,token);
722 if (LocaleCompare(keyword,"<include") == 0)
727 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
729 (void) CopyMagickString(keyword,token,MaxTextExtent);
730 GetMagickToken(q,&q,token);
733 GetMagickToken(q,&q,token);
734 if (LocaleCompare(keyword,"file") == 0)
737 (void) ThrowMagickException(exception,GetMagickModule(),
738 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
745 GetPathComponent(filename,HeadPath,path);
747 (void) ConcatenateMagickString(path,DirectorySeparator,
749 if (*token == *DirectorySeparator)
750 (void) CopyMagickString(path,token,MaxTextExtent);
752 (void) ConcatenateMagickString(path,token,MaxTextExtent);
753 xml=FileToString(path,~0,exception);
754 if (xml != (char *) NULL)
756 status=LoadMagicList(xml,path,depth+1,exception);
757 xml=(char *) RelinquishMagickMemory(xml);
764 if (LocaleCompare(keyword,"<magic") == 0)
769 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
770 if (magic_info == (MagicInfo *) NULL)
771 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
772 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
773 magic_info->path=ConstantString(filename);
774 magic_info->exempt=MagickFalse;
775 magic_info->signature=MagickSignature;
778 if (magic_info == (MagicInfo *) NULL)
780 if (LocaleCompare(keyword,"/>") == 0)
782 status=AppendValueToLinkedList(magic_list,magic_info);
783 if (status == MagickFalse)
784 (void) ThrowMagickException(exception,GetMagickModule(),
785 ResourceLimitError,"MemoryAllocationFailed","`%s'",
787 magic_info=(MagicInfo *) NULL;
789 GetMagickToken(q,(const char **) NULL,token);
792 GetMagickToken(q,&q,token);
793 GetMagickToken(q,&q,token);
799 if (LocaleCompare((char *) keyword,"name") == 0)
801 magic_info->name=ConstantString(token);
809 if (LocaleCompare((char *) keyword,"offset") == 0)
811 magic_info->offset=(MagickOffsetType) StringToLong(token);
819 if (LocaleCompare((char *) keyword,"stealth") == 0)
821 magic_info->stealth=IsMagickTrue(token);
829 if (LocaleCompare((char *) keyword,"target") == 0)
834 register unsigned char
840 length=strlen(token);
841 magic_info->target=ConstantString(token);
842 magic_info->magic=(unsigned char *) ConstantString(token);
844 for (p=magic_info->target; *p != '\0'; )
849 if (isdigit((int) ((unsigned char) *p)) != 0)
854 *q++=(unsigned char) strtol(p,&end,8);
856 magic_info->length++;
861 case 'b': *q='\b'; break;
862 case 'f': *q='\f'; break;
863 case 'n': *q='\n'; break;
864 case 'r': *q='\r'; break;
865 case 't': *q='\t'; break;
866 case 'v': *q='\v'; break;
867 case 'a': *q='a'; break;
868 case '?': *q='\?'; break;
869 default: *q=(unsigned char) (*p); break;
873 magic_info->length++;
877 if (LocaleNCompare(p,"&",5) == 0)
878 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
879 *q++=(unsigned char) (*p++);
880 magic_info->length++;
890 token=(char *) RelinquishMagickMemory(token);
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 % L o a d M a g i c L i s t s %
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 % LoadMagicLists() loads one or more magic configuration file which provides a
906 % mapping between magic attributes and a magic name.
908 % The format of the LoadMagicLists method is:
910 % MagickBooleanType LoadMagicLists(const char *filename,
911 % ExceptionInfo *exception)
913 % A description of each parameter follows:
915 % o filename: the font file name.
917 % o exception: return any errors or warnings in this structure.
920 static MagickBooleanType LoadMagicLists(const char *filename,
921 ExceptionInfo *exception)
939 Load built-in magic map.
942 if (magic_list == (LinkedListInfo *) NULL)
944 magic_list=NewLinkedList(0);
945 if (magic_list == (LinkedListInfo *) NULL)
947 ThrowFileException(exception,ResourceLimitError,
948 "MemoryAllocationFailed",filename);
952 for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
957 register const MagicMapInfo
961 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
962 if (magic_info == (MagicInfo *) NULL)
964 (void) ThrowMagickException(exception,GetMagickModule(),
965 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
968 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
969 magic_info->path=(char *) "[built-in]";
970 magic_info->name=(char *) p->name;
971 magic_info->offset=p->offset;
972 magic_info->target=(char *) p->magic;
973 magic_info->magic=(unsigned char *) p->magic;
974 magic_info->length=p->length;
975 magic_info->exempt=MagickTrue;
976 magic_info->signature=MagickSignature;
977 status=AppendValueToLinkedList(magic_list,magic_info);
978 if (status == MagickFalse)
979 (void) ThrowMagickException(exception,GetMagickModule(),
980 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
983 Load external magic map.
986 options=GetConfigureOptions(filename,exception);
987 option=(const StringInfo *) GetNextValueInLinkedList(options);
988 while (option != (const StringInfo *) NULL)
990 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
991 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
992 GetStringInfoPath(option),0,exception);
993 option=(const StringInfo *) GetNextValueInLinkedList(options);
995 options=DestroyConfigureOptions(options);
996 return(status != 0 ? MagickTrue : MagickFalse);
1000 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 + M a g i c C o m p o n e n t G e n e s i s %
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010 % MagicComponentGenesis() instantiates the magic component.
1012 % The format of the MagicComponentGenesis method is:
1014 % MagickBooleanType MagicComponentGenesis(void)
1017 MagickExport MagickBooleanType MagicComponentGenesis(void)
1019 AcquireSemaphoreInfo(&magic_semaphore);
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1028 + M a g i c C o m p o n e n t T e r m i n u s %
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 % MagicComponentTerminus() destroys the magic component.
1036 % The format of the MagicComponentTerminus method is:
1038 % MagicComponentTerminus(void)
1042 static void *DestroyMagicElement(void *magic_info)
1047 p=(MagicInfo *) magic_info;
1048 if (p->exempt == MagickFalse)
1050 if (p->path != (char *) NULL)
1051 p->path=DestroyString(p->path);
1052 if (p->name != (char *) NULL)
1053 p->name=DestroyString(p->name);
1054 if (p->target != (char *) NULL)
1055 p->target=DestroyString(p->target);
1056 if (p->magic != (unsigned char *) NULL)
1057 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1059 p=(MagicInfo *) RelinquishMagickMemory(p);
1060 return((void *) NULL);
1063 MagickExport void MagicComponentTerminus(void)
1065 if (magic_semaphore == (SemaphoreInfo *) NULL)
1066 AcquireSemaphoreInfo(&magic_semaphore);
1067 LockSemaphoreInfo(magic_semaphore);
1068 if (magic_list != (LinkedListInfo *) NULL)
1069 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
1070 instantiate_magic=MagickFalse;
1071 UnlockSemaphoreInfo(magic_semaphore);
1072 DestroySemaphoreInfo(&magic_semaphore);