blob: 74b3902e8cd65259e019ae6ba5c12868de1fa5eb [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% M M AAA GGGG IIIII CCCC %
6% MM MM A A G I C %
7% M M M AAAAA G GGG I C %
8% M M A A G G I C %
9% M M A A GGGG IIIII CCCC %
10% %
11% %
12% MagickCore Image Magic Methods %
13% %
14% Software Design %
15% Bob Friesenhahn %
16% July 2000 %
17% %
18% %
19% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
20% dedicated to making software imaging solutions freely available. %
21% %
22% You may not use this file except in compliance with the License. You may %
23% obtain a copy of the License at %
24% %
25% http://www.imagemagick.org/script/license.php %
26% %
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. %
32% %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35%
36*/
37
38/*
39 Include declarations.
40*/
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/token.h"
53#include "magick/utility.h"
54#include "magick/xml-tree.h"
55
56/*
57 Define declarations.
58*/
59#define MagicFilename "magic.xml"
cristy54a531d2009-10-21 17:58:01 +000060#define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
cristy3ed852e2009-09-05 21:47:34 +000061
62/*
cristy54a531d2009-10-21 17:58:01 +000063 Typedef declarations.
cristy3ed852e2009-09-05 21:47:34 +000064*/
cristy1ca3eb32009-10-15 18:41:54 +000065typedef struct _MagicMapInfo
66{
67 const char
68 *name;
69
cristye3e77a12009-10-16 00:47:21 +000070 const MagickOffsetType
71 offset;
72
cristybcdce3d2009-10-15 20:04:49 +000073 const unsigned char
cristy1ca3eb32009-10-15 18:41:54 +000074 *magic;
75
cristye3e77a12009-10-16 00:47:21 +000076 const size_t
cristy1ca3eb32009-10-15 18:41:54 +000077 length;
cristy1ca3eb32009-10-15 18:41:54 +000078} MagicMapInfo;
cristy54a531d2009-10-21 17:58:01 +000079
80/*
81 Static declarations.
82*/
cristy1ca3eb32009-10-15 18:41:54 +000083static const MagicMapInfo
84 MagicMap[] =
85 {
cristye3e77a12009-10-16 00:47:21 +000086 { "AVI", 0, MagickString("RIFF") },
87 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
88 { "8BIMTEXT", 0, MagickString("8BIM#") },
89 { "8BIM", 0, MagickString("8BIM") },
90 { "BMP", 0, MagickString("BA") },
91 { "BMP", 0, MagickString("BM") },
92 { "BMP", 0, MagickString("CI") },
93 { "BMP", 0, MagickString("CP") },
94 { "BMP", 0, MagickString("IC") },
95 { "BMP", 0, MagickString("PI") },
96 { "CALS", 21, MagickString("version: MIL-STD-1840") },
97 { "CALS", 0, MagickString("srcdocid:") },
98 { "CALS", 9, MagickString("srcdocid:") },
99 { "CALS", 8, MagickString("rorient:") },
100 { "CGM", 0, MagickString("BEGMF") },
101 { "CIN", 0, MagickString("\200\052\137\327") },
102 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
103 { "DCM", 128, MagickString("DICM") },
104 { "DCX", 0, MagickString("\261\150\336\72") },
105 { "DIB", 0, MagickString("\050\000") },
106 { "DDS", 0, MagickString("DDS ") },
107 { "DJVU", 0, MagickString("AT&TFORM") },
108 { "DOT", 0, MagickString("digraph") },
109 { "DPX", 0, MagickString("SDPX") },
110 { "DPX", 0, MagickString("XPDS") },
111 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
112 { "EPT", 0, MagickString("\305\320\323\306") },
113 { "EXR", 0, MagickString("\166\057\061\001") },
114 { "FAX", 0, MagickString("DFAX") },
115 { "FIG", 0, MagickString("#FIG") },
116 { "FITS", 0, MagickString("IT0") },
117 { "FITS", 0, MagickString("SIMPLE") },
118 { "FPX", 0, MagickString("\320\317\021\340") },
119 { "GIF", 0, MagickString("GIF8") },
120 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
121 { "HDF", 1, MagickString("HDF") },
122 { "HPGL", 0, MagickString("IN;") },
123 { "HPGL", 0, MagickString("\033E\033") },
124 { "HTML", 1, MagickString("HTML") },
125 { "HTML", 1, MagickString("html") },
126 { "ILBM", 8, MagickString("ILBM") },
127 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
128 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
129 { "IPTC", 0, MagickString("\034\002") },
130 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
131 { "JPEG", 0, MagickString("\377\330\377") },
132 { "JPC", 0, MagickString("\377\117") },
133 { "JP2", 4, MagickString("\152\120\040\040\015") },
134 { "MIFF", 0, MagickString("Id=ImageMagick") },
135 { "MIFF", 0, MagickString("id=ImageMagick") },
136 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
137 { "MPC", 0, MagickString("id=MagickCache") },
138 { "MPEG", 0, MagickString("\000\000\001\263") },
139 { "MRW", 0, MagickString("\x00MRM") },
140 { "MVG", 0, MagickString("push graphic-context") },
141 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
142 { "PCD", 2048, MagickString("PCD_") },
143 { "PCL", 0, MagickString("\033E\033") },
144 { "PCX", 0, MagickString("\012\002") },
145 { "PCX", 0, MagickString("\012\005") },
146 { "PDB", 60, MagickString("vIMGView") },
147 { "PDF", 0, MagickString("%PDF-") },
148 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
149 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
150 { "PGX", 0, MagickString("\050\107\020\115\046") },
151 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
152 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
153 { "PNM", 0, MagickString("P1") },
154 { "PNM", 0, MagickString("P2") },
155 { "PNM", 0, MagickString("P3") },
156 { "PNM", 0, MagickString("P4") },
157 { "PNM", 0, MagickString("P5") },
158 { "PNM", 0, MagickString("P6") },
159 { "PNM", 0, MagickString("P7") },
160 { "PNM", 0, MagickString("PF") },
161 { "PNM", 0, MagickString("Pf") },
162 { "PS", 0, MagickString("%!") },
163 { "PS", 0, MagickString("\004%!") },
164 { "PS", 0, MagickString("\305\320\323\306") },
165 { "PSD", 0, MagickString("8BPS") },
166 { "PWP", 0, MagickString("SFW95") },
167 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
168 { "RAD", 0, MagickString("#?RADIANCE") },
169 { "RAD", 0, MagickString("VIEW= ") },
170 { "RLE", 0, MagickString("\122\314") },
171 { "SCT", 0, MagickString("CT") },
172 { "SFW", 0, MagickString("SFW94") },
173 { "SGI", 0, MagickString("\001\332") },
174 { "SUN", 0, MagickString("\131\246\152\225") },
175 { "SVG", 1, MagickString("?XML") },
176 { "SVG", 1, MagickString("?xml") },
177 { "TIFF", 0, MagickString("\115\115\000\052") },
178 { "TIFF", 0, MagickString("\111\111\052\000") },
179 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
180 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
181 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
182 { "VICAR", 0, MagickString("LBLSIZE") },
183 { "VICAR", 0, MagickString("NJPL1I") },
184 { "VIFF", 0, MagickString("\253\001") },
185 { "WMF", 0, MagickString("\327\315\306\232") },
186 { "WMF", 0, MagickString("\001\000\011\000") },
187 { "WPG", 0, MagickString("\377WPC") },
188 { "XBM", 0, MagickString("#define") },
189 { "XCF", 0, MagickString("gimp xcf") },
190 { "XEF", 0, MagickString("FOVb") },
191 { "XPM", 1, MagickString("* XPM *") },
192 { "XWD", 4, MagickString("\007\000\000") },
cristy54a531d2009-10-21 17:58:01 +0000193 { "XWD", 5, MagickString("\000\000\007") }
cristy1ca3eb32009-10-15 18:41:54 +0000194 };
cristy3ed852e2009-09-05 21:47:34 +0000195
196static LinkedListInfo
197 *magic_list = (LinkedListInfo *) NULL;
198
199static SemaphoreInfo
200 *magic_semaphore = (SemaphoreInfo *) NULL;
201
202static volatile MagickBooleanType
203 instantiate_magic = MagickFalse;
204
205/*
206 Forward declarations.
207*/
208static MagickBooleanType
209 InitializeMagicList(ExceptionInfo *),
210 LoadMagicLists(const char *,ExceptionInfo *);
211
212/*
213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214% %
215% %
216% %
cristy3ed852e2009-09-05 21:47:34 +0000217+ G e t M a g i c I n f o %
218% %
219% %
220% %
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222%
223% GetMagicInfo() searches the magic list for the specified name and if found
224% returns attributes for that magic.
225%
226% The format of the GetMagicInfo method is:
227%
228% const MagicInfo *GetMagicInfo(const unsigned char *magic,
229% const size_t length,ExceptionInfo *exception)
230%
231% A description of each parameter follows:
232%
233% o magic: A binary string generally representing the first few characters
234% of the image file or blob.
235%
236% o length: the length of the binary signature.
237%
238% o exception: return any errors or warnings in this structure.
239%
240*/
241MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
242 const size_t length,ExceptionInfo *exception)
243{
244 register const MagicInfo
245 *p;
246
247 assert(exception != (ExceptionInfo *) NULL);
248 if ((magic_list == (LinkedListInfo *) NULL) ||
249 (instantiate_magic == MagickFalse))
250 if (InitializeMagicList(exception) == MagickFalse)
251 return((const MagicInfo *) NULL);
252 if ((magic_list == (LinkedListInfo *) NULL) ||
253 (IsLinkedListEmpty(magic_list) != MagickFalse))
254 return((const MagicInfo *) NULL);
255 if (magic == (const unsigned char *) NULL)
256 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
257 if (length == 0)
258 return((const MagicInfo *) NULL);
259 /*
260 Search for magic tag.
261 */
cristy18b17442009-10-25 18:36:48 +0000262 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000263 ResetLinkedListIterator(magic_list);
264 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
265 while (p != (const MagicInfo *) NULL)
266 {
267 assert(p->offset >= 0);
268 if (((size_t) (p->offset+p->length) <= length) &&
269 (memcmp(magic+p->offset,p->magic,p->length) == 0))
270 break;
271 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
272 }
273 if (p != (const MagicInfo *) NULL)
274 (void) InsertValueInLinkedList(magic_list,0,
275 RemoveElementByValueFromLinkedList(magic_list,p));
cristy18b17442009-10-25 18:36:48 +0000276 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000277 return(p);
278}
279
280/*
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282% %
283% %
284% %
285% G e t M a g i c I n f o L i s t %
286% %
287% %
288% %
289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290%
291% GetMagicInfoList() returns any image aliases that match the specified
292% pattern.
293%
294% The magic of the GetMagicInfoList function is:
295%
296% const MagicInfo **GetMagicInfoList(const char *pattern,
297% unsigned long *number_aliases,ExceptionInfo *exception)
298%
299% A description of each parameter follows:
300%
301% o pattern: Specifies a pointer to a text string containing a pattern.
302%
cristyfc0d1122009-10-17 20:22:37 +0000303% o number_aliases: This integer returns the number of aliases in the list.
cristy3ed852e2009-09-05 21:47:34 +0000304%
305% o exception: return any errors or warnings in this structure.
306%
307*/
308
309#if defined(__cplusplus) || defined(c_plusplus)
310extern "C" {
311#endif
312
313static int MagicInfoCompare(const void *x,const void *y)
314{
315 const MagicInfo
316 **p,
317 **q;
318
319 p=(const MagicInfo **) x,
320 q=(const MagicInfo **) y;
321 if (LocaleCompare((*p)->path,(*q)->path) == 0)
322 return(LocaleCompare((*p)->name,(*q)->name));
323 return(LocaleCompare((*p)->path,(*q)->path));
324}
325
326#if defined(__cplusplus) || defined(c_plusplus)
327}
328#endif
329
330MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
331 unsigned long *number_aliases,ExceptionInfo *exception)
332{
333 const MagicInfo
334 **aliases;
335
336 register const MagicInfo
337 *p;
338
339 register long
340 i;
341
342 /*
343 Allocate magic list.
344 */
345 assert(pattern != (char *) NULL);
346 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
347 assert(number_aliases != (unsigned long *) NULL);
348 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000349 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000350 if (p == (const MagicInfo *) NULL)
351 return((const MagicInfo **) NULL);
352 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
353 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
354 if (aliases == (const MagicInfo **) NULL)
355 return((const MagicInfo **) NULL);
356 /*
357 Generate magic list.
358 */
cristy18b17442009-10-25 18:36:48 +0000359 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000360 ResetLinkedListIterator(magic_list);
361 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
362 for (i=0; p != (const MagicInfo *) NULL; )
363 {
364 if ((p->stealth == MagickFalse) &&
365 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
366 aliases[i++]=p;
367 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
368 }
cristy18b17442009-10-25 18:36:48 +0000369 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000370 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
371 aliases[i]=(MagicInfo *) NULL;
372 *number_aliases=(unsigned long) i;
373 return(aliases);
374}
375
376/*
377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378% %
379% %
380% %
381% G e t M a g i c L i s t %
382% %
383% %
384% %
385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386%
387% GetMagicList() returns any image format aliases that match the specified
388% pattern.
389%
390% The format of the GetMagicList function is:
391%
392% char **GetMagicList(const char *pattern,unsigned long *number_aliases,
393% ExceptionInfo *exception)
394%
395% A description of each parameter follows:
396%
397% o pattern: Specifies a pointer to a text string containing a pattern.
398%
399% o number_aliases: This integer returns the number of image format aliases
400% in the list.
401%
402% o exception: return any errors or warnings in this structure.
403%
404*/
405
406#if defined(__cplusplus) || defined(c_plusplus)
407extern "C" {
408#endif
409
410static int MagicCompare(const void *x,const void *y)
411{
412 register const char
413 *p,
414 *q;
415
416 p=(const char *) x;
417 q=(const char *) y;
418 return(LocaleCompare(p,q));
419}
420
421#if defined(__cplusplus) || defined(c_plusplus)
422}
423#endif
424
425MagickExport char **GetMagicList(const char *pattern,
426 unsigned long *number_aliases,ExceptionInfo *exception)
427{
428 char
429 **aliases;
430
431 register const MagicInfo
432 *p;
433
434 register long
435 i;
436
437 /*
438 Allocate configure list.
439 */
440 assert(pattern != (char *) NULL);
441 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
442 assert(number_aliases != (unsigned long *) NULL);
443 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000444 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000445 if (p == (const MagicInfo *) NULL)
446 return((char **) NULL);
447 aliases=(char **) AcquireQuantumMemory((size_t)
448 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
449 if (aliases == (char **) NULL)
450 return((char **) NULL);
cristy18b17442009-10-25 18:36:48 +0000451 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000452 ResetLinkedListIterator(magic_list);
453 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
454 for (i=0; p != (const MagicInfo *) NULL; )
455 {
456 if ((p->stealth == MagickFalse) &&
457 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
458 aliases[i++]=ConstantString(p->name);
459 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
460 }
cristy18b17442009-10-25 18:36:48 +0000461 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000462 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
463 aliases[i]=(char *) NULL;
464 *number_aliases=(unsigned long) i;
465 return(aliases);
466}
467
468/*
469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470% %
471% %
472% %
473% G e t M a g i c N a m e %
474% %
475% %
476% %
477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478%
479% GetMagicName() returns the name associated with the magic.
480%
481% The format of the GetMagicName method is:
482%
483% const char *GetMagicName(const MagicInfo *magic_info)
484%
485% A description of each parameter follows:
486%
487% o magic_info: The magic info.
488%
489*/
490MagickExport const char *GetMagicName(const MagicInfo *magic_info)
491{
492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
493 assert(magic_info != (MagicInfo *) NULL);
494 assert(magic_info->signature == MagickSignature);
495 return(magic_info->name);
496}
497
498/*
499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500% %
501% %
502% %
503+ I n i t i a l i z e M a g i c L i s t %
504% %
505% %
506% %
507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508%
509% InitializeMagicList() initializes the magic list.
510%
511% The format of the InitializeMagicList method is:
512%
513% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
514%
515% A description of each parameter follows.
516%
517% o exception: return any errors or warnings in this structure.
518%
519*/
520static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
521{
522 if ((magic_list == (LinkedListInfo *) NULL) &&
523 (instantiate_magic == MagickFalse))
524 {
cristy4e1dff62009-10-25 20:36:03 +0000525 if (magic_semaphore == (SemaphoreInfo *) NULL)
526 AcquireSemaphoreInfo(&magic_semaphore);
cristy18b17442009-10-25 18:36:48 +0000527 LockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000528 if ((magic_list == (LinkedListInfo *) NULL) &&
529 (instantiate_magic == MagickFalse))
530 {
531 (void) LoadMagicLists(MagicFilename,exception);
532 instantiate_magic=MagickTrue;
533 }
cristy18b17442009-10-25 18:36:48 +0000534 UnlockSemaphoreInfo(magic_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000535 }
536 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
537}
538
539/*
540%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541% %
542% %
543% %
544% L i s t M a g i c I n f o %
545% %
546% %
547% %
548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549%
550% ListMagicInfo() lists the magic info to a file.
551%
552% The format of the ListMagicInfo method is:
553%
554% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
555%
556% A description of each parameter follows.
557%
558% o file: An pointer to a FILE.
559%
560% o exception: return any errors or warnings in this structure.
561%
562*/
563MagickExport MagickBooleanType ListMagicInfo(FILE *file,
564 ExceptionInfo *exception)
565{
566 const char
567 *path;
568
569 const MagicInfo
570 **magic_info;
571
572 long
573 j;
574
575 register long
576 i;
577
578 unsigned long
579 number_aliases;
580
581 if (file == (const FILE *) NULL)
582 file=stdout;
583 magic_info=GetMagicInfoList("*",&number_aliases,exception);
584 if (magic_info == (const MagicInfo **) NULL)
585 return(MagickFalse);
586 j=0;
587 path=(const char *) NULL;
588 for (i=0; i < (long) number_aliases; i++)
589 {
590 if (magic_info[i]->stealth != MagickFalse)
591 continue;
592 if ((path == (const char *) NULL) ||
593 (LocaleCompare(path,magic_info[i]->path) != 0))
594 {
595 if (magic_info[i]->path != (char *) NULL)
596 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
597 (void) fprintf(file,"Name Offset Target\n");
598 (void) fprintf(file,"-------------------------------------------------"
599 "------------------------------\n");
600 }
601 path=magic_info[i]->path;
602 (void) fprintf(file,"%s",magic_info[i]->name);
603 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
604 (void) fprintf(file," ");
605 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
606 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000607 {
608 register long
609 j;
610
611 for (j=0; magic_info[i]->target[j] != '\0'; j++)
612 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
613 (void) fprintf(file,"%c",magic_info[i]->target[j]);
614 else
cristy50931922009-10-15 18:59:59 +0000615 (void) fprintf(file,"\\%03o",(unsigned int)
616 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000617 }
cristy3ed852e2009-09-05 21:47:34 +0000618 (void) fprintf(file,"\n");
619 }
620 (void) fflush(file);
621 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
622 return(MagickTrue);
623}
624
625/*
626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627% %
628% %
629% %
630+ L o a d M a g i c L i s t %
631% %
632% %
633% %
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635%
636% LoadMagicList() loads the magic configuration file which provides a mapping
637% between magic attributes and a magic name.
638%
639% The format of the LoadMagicList method is:
640%
641% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
642% const unsigned long depth,ExceptionInfo *exception)
643%
644% A description of each parameter follows:
645%
cristy1ca3eb32009-10-15 18:41:54 +0000646% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000647%
cristy1ca3eb32009-10-15 18:41:54 +0000648% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000649%
650% o depth: depth of <include /> statements.
651%
652% o exception: return any errors or warnings in this structure.
653%
654*/
655static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
656 const unsigned long depth,ExceptionInfo *exception)
657{
658 char
659 keyword[MaxTextExtent],
660 *token;
661
662 const char
663 *q;
664
665 MagickBooleanType
666 status;
667
668 MagicInfo
669 *magic_info;
670
671 /*
672 Load the magic map file.
673 */
674 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
675 "Loading magic configure file \"%s\" ...",filename);
676 if (xml == (char *) NULL)
677 return(MagickFalse);
678 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000679 {
680 magic_list=NewLinkedList(0);
681 if (magic_list == (LinkedListInfo *) NULL)
682 {
683 ThrowFileException(exception,ResourceLimitError,
684 "MemoryAllocationFailed",filename);
685 return(MagickFalse);
686 }
687 }
cristy3ed852e2009-09-05 21:47:34 +0000688 status=MagickTrue;
689 magic_info=(MagicInfo *) NULL;
690 token=AcquireString(xml);
691 for (q=(char *) xml; *q != '\0'; )
692 {
693 /*
694 Interpret XML.
695 */
696 GetMagickToken(q,&q,token);
697 if (*token == '\0')
698 break;
699 (void) CopyMagickString(keyword,token,MaxTextExtent);
700 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
701 {
702 /*
703 Doctype element.
704 */
705 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
706 GetMagickToken(q,&q,token);
707 continue;
708 }
709 if (LocaleNCompare(keyword,"<!--",4) == 0)
710 {
711 /*
712 Comment element.
713 */
714 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
715 GetMagickToken(q,&q,token);
716 continue;
717 }
718 if (LocaleCompare(keyword,"<include") == 0)
719 {
720 /*
721 Include element.
722 */
723 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
724 {
725 (void) CopyMagickString(keyword,token,MaxTextExtent);
726 GetMagickToken(q,&q,token);
727 if (*token != '=')
728 continue;
729 GetMagickToken(q,&q,token);
730 if (LocaleCompare(keyword,"file") == 0)
731 {
732 if (depth > 200)
733 (void) ThrowMagickException(exception,GetMagickModule(),
734 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
735 else
736 {
737 char
738 path[MaxTextExtent],
739 *xml;
740
741 GetPathComponent(filename,HeadPath,path);
742 if (*path != '\0')
743 (void) ConcatenateMagickString(path,DirectorySeparator,
744 MaxTextExtent);
745 if (*token == *DirectorySeparator)
746 (void) CopyMagickString(path,token,MaxTextExtent);
747 else
748 (void) ConcatenateMagickString(path,token,MaxTextExtent);
749 xml=FileToString(path,~0,exception);
750 if (xml != (char *) NULL)
751 {
752 status=LoadMagicList(xml,path,depth+1,exception);
753 xml=(char *) RelinquishMagickMemory(xml);
754 }
755 }
756 }
757 }
758 continue;
759 }
760 if (LocaleCompare(keyword,"<magic") == 0)
761 {
762 /*
763 Magic element.
764 */
765 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
766 if (magic_info == (MagicInfo *) NULL)
767 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
768 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
769 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000770 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000771 magic_info->signature=MagickSignature;
772 continue;
773 }
774 if (magic_info == (MagicInfo *) NULL)
775 continue;
776 if (LocaleCompare(keyword,"/>") == 0)
777 {
778 status=AppendValueToLinkedList(magic_list,magic_info);
779 if (status == MagickFalse)
780 (void) ThrowMagickException(exception,GetMagickModule(),
781 ResourceLimitError,"MemoryAllocationFailed","`%s'",
782 magic_info->name);
783 magic_info=(MagicInfo *) NULL;
784 }
785 GetMagickToken(q,(const char **) NULL,token);
786 if (*token != '=')
787 continue;
788 GetMagickToken(q,&q,token);
789 GetMagickToken(q,&q,token);
790 switch (*keyword)
791 {
792 case 'N':
793 case 'n':
794 {
795 if (LocaleCompare((char *) keyword,"name") == 0)
796 {
797 magic_info->name=ConstantString(token);
798 break;
799 }
800 break;
801 }
802 case 'O':
803 case 'o':
804 {
805 if (LocaleCompare((char *) keyword,"offset") == 0)
806 {
807 magic_info->offset=(MagickOffsetType) atol(token);
808 break;
809 }
810 break;
811 }
812 case 'S':
813 case 's':
814 {
815 if (LocaleCompare((char *) keyword,"stealth") == 0)
816 {
817 magic_info->stealth=IsMagickTrue(token);
818 break;
819 }
820 break;
821 }
822 case 'T':
823 case 't':
824 {
825 if (LocaleCompare((char *) keyword,"target") == 0)
826 {
827 char
828 *p;
829
830 register unsigned char
831 *q;
832
833 size_t
834 length;
835
836 length=strlen(token);
837 magic_info->target=ConstantString(token);
838 magic_info->magic=(unsigned char *) ConstantString(token);
839 q=magic_info->magic;
840 for (p=magic_info->target; *p != '\0'; )
841 {
842 if (*p == '\\')
843 {
844 p++;
845 if (isdigit((int) ((unsigned char) *p)) != 0)
846 {
847 char
848 *end;
849
850 *q++=(unsigned char) strtol(p,&end,8);
851 p+=(end-p);
852 magic_info->length++;
853 continue;
854 }
855 switch (*p)
856 {
857 case 'b': *q='\b'; break;
858 case 'f': *q='\f'; break;
859 case 'n': *q='\n'; break;
860 case 'r': *q='\r'; break;
861 case 't': *q='\t'; break;
862 case 'v': *q='\v'; break;
863 case 'a': *q='a'; break;
864 case '?': *q='\?'; break;
865 default: *q=(unsigned char) (*p); break;
866 }
867 p++;
868 q++;
869 magic_info->length++;
870 continue;
871 }
872 else
873 if (LocaleNCompare(p,"&amp;",5) == 0)
874 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
875 *q++=(unsigned char) (*p++);
876 magic_info->length++;
877 }
878 break;
879 }
880 break;
881 }
882 default:
883 break;
884 }
885 }
886 token=(char *) RelinquishMagickMemory(token);
887 return(status);
888}
889
890/*
891%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892% %
893% %
894% %
895% L o a d M a g i c L i s t s %
896% %
897% %
898% %
899%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900%
901% LoadMagicLists() loads one or more magic configuration file which provides a
902% mapping between magic attributes and a magic name.
903%
904% The format of the LoadMagicLists method is:
905%
906% MagickBooleanType LoadMagicLists(const char *filename,
907% ExceptionInfo *exception)
908%
909% A description of each parameter follows:
910%
911% o filename: the font file name.
912%
913% o exception: return any errors or warnings in this structure.
914%
915*/
916static MagickBooleanType LoadMagicLists(const char *filename,
917 ExceptionInfo *exception)
918{
cristy3ed852e2009-09-05 21:47:34 +0000919 char
920 path[MaxTextExtent];
921
922 const StringInfo
923 *option;
924
925 LinkedListInfo
926 *options;
927
928 MagickStatusType
929 status;
930
cristy54a531d2009-10-21 17:58:01 +0000931 register long
932 i;
cristy1ca3eb32009-10-15 18:41:54 +0000933
934 /*
935 Load built-in magic map.
936 */
cristy3ed852e2009-09-05 21:47:34 +0000937 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +0000938 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000939 {
940 magic_list=NewLinkedList(0);
941 if (magic_list == (LinkedListInfo *) NULL)
942 {
943 ThrowFileException(exception,ResourceLimitError,
944 "MemoryAllocationFailed",filename);
945 return(MagickFalse);
946 }
947 }
cristy54a531d2009-10-21 17:58:01 +0000948 for (i=0; i < (long) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
cristy1ca3eb32009-10-15 18:41:54 +0000949 {
950 MagicInfo
951 *magic_info;
952
cristy54a531d2009-10-21 17:58:01 +0000953 register const MagicMapInfo
954 *p;
955
956 p=MagicMap+i;
cristy1ca3eb32009-10-15 18:41:54 +0000957 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
958 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000959 {
960 (void) ThrowMagickException(exception,GetMagickModule(),
961 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
962 continue;
963 }
cristy1ca3eb32009-10-15 18:41:54 +0000964 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
cristy38b8ed92009-10-16 01:20:21 +0000965 magic_info->path=(char *) "[built-in]";
cristy1ca3eb32009-10-15 18:41:54 +0000966 magic_info->name=(char *) p->name;
967 magic_info->offset=p->offset;
968 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +0000969 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +0000970 magic_info->length=p->length;
971 magic_info->exempt=MagickTrue;
972 magic_info->signature=MagickSignature;
973 status=AppendValueToLinkedList(magic_list,magic_info);
974 if (status == MagickFalse)
975 (void) ThrowMagickException(exception,GetMagickModule(),
976 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
977 }
978 /*
979 Load external magic map.
980 */
cristy3ed852e2009-09-05 21:47:34 +0000981 *path='\0';
982 options=GetConfigureOptions(filename,exception);
983 option=(const StringInfo *) GetNextValueInLinkedList(options);
984 while (option != (const StringInfo *) NULL)
985 {
986 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
987 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
988 GetStringInfoPath(option),0,exception);
989 option=(const StringInfo *) GetNextValueInLinkedList(options);
990 }
991 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +0000992 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +0000993}
cristyf34a1452009-10-24 22:29:27 +0000994
995/*
996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997% %
998% %
999% %
1000+ M a g i c C o m p o n e n t G e n e s i s %
1001% %
1002% %
1003% %
1004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005%
1006% MagicComponentGenesis() instantiates the magic component.
1007%
1008% The format of the MagicComponentGenesis method is:
1009%
1010% MagickBooleanType MagicComponentGenesis(void)
1011%
1012*/
1013MagickExport MagickBooleanType MagicComponentGenesis(void)
1014{
cristy18b17442009-10-25 18:36:48 +00001015 assert(magic_semaphore == (SemaphoreInfo *) NULL);
1016 magic_semaphore=AllocateSemaphoreInfo();
cristyf34a1452009-10-24 22:29:27 +00001017 return(MagickTrue);
1018}
1019
1020/*
1021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022% %
1023% %
1024% %
1025+ M a g i c C o m p o n e n t T e r m i n u s %
1026% %
1027% %
1028% %
1029%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030%
1031% MagicComponentTerminus() destroys the magic component.
1032%
1033% The format of the MagicComponentTerminus method is:
1034%
1035% MagicComponentTerminus(void)
1036%
1037*/
1038
1039static void *DestroyMagicElement(void *magic_info)
1040{
1041 register MagicInfo
1042 *p;
1043
1044 p=(MagicInfo *) magic_info;
1045 if (p->exempt == MagickFalse)
1046 {
1047 if (p->path != (char *) NULL)
1048 p->path=DestroyString(p->path);
1049 if (p->name != (char *) NULL)
1050 p->name=DestroyString(p->name);
1051 if (p->target != (char *) NULL)
1052 p->target=DestroyString(p->target);
1053 if (p->magic != (unsigned char *) NULL)
1054 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1055 }
1056 p=(MagicInfo *) RelinquishMagickMemory(p);
1057 return((void *) NULL);
1058}
1059
1060MagickExport void MagicComponentTerminus(void)
1061{
cristy18b17442009-10-25 18:36:48 +00001062 if (magic_semaphore == (SemaphoreInfo *) NULL)
1063 AcquireSemaphoreInfo(&magic_semaphore);
1064 LockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001065 if (magic_list != (LinkedListInfo *) NULL)
1066 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
1067 instantiate_magic=MagickFalse;
cristy18b17442009-10-25 18:36:48 +00001068 UnlockSemaphoreInfo(magic_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001069 DestroySemaphoreInfo(&magic_semaphore);
1070}