blob: 0c6b5a646c2e52bfba740f98c2e1ed6f722492be [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% %
cristydf1cc5f2009-10-19 16:02:33 +0000217+ D e s t r o y M a g i c C o m p o n e n t %
cristy3ed852e2009-09-05 21:47:34 +0000218% %
219% %
220% %
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222%
cristydf1cc5f2009-10-19 16:02:33 +0000223% DestroyMagicComponent() destroys the magic component.
cristy3ed852e2009-09-05 21:47:34 +0000224%
cristydf1cc5f2009-10-19 16:02:33 +0000225% The format of the DestroyMagicComponent method is:
cristy3ed852e2009-09-05 21:47:34 +0000226%
cristydf1cc5f2009-10-19 16:02:33 +0000227% DestroyMagicComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000228%
229*/
230
231static void *DestroyMagicElement(void *magic_info)
232{
233 register MagicInfo
234 *p;
235
236 p=(MagicInfo *) magic_info;
cristy1ca3eb32009-10-15 18:41:54 +0000237 if (p->exempt == MagickFalse)
238 {
239 if (p->path != (char *) NULL)
240 p->path=DestroyString(p->path);
241 if (p->name != (char *) NULL)
242 p->name=DestroyString(p->name);
243 if (p->target != (char *) NULL)
244 p->target=DestroyString(p->target);
245 if (p->magic != (unsigned char *) NULL)
246 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
247 }
cristy3ed852e2009-09-05 21:47:34 +0000248 p=(MagicInfo *) RelinquishMagickMemory(p);
249 return((void *) NULL);
250}
251
cristydf1cc5f2009-10-19 16:02:33 +0000252MagickExport void DestroyMagicComponent(void)
cristy3ed852e2009-09-05 21:47:34 +0000253{
254 AcquireSemaphoreInfo(&magic_semaphore);
255 if (magic_list != (LinkedListInfo *) NULL)
256 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
257 instantiate_magic=MagickFalse;
258 RelinquishSemaphoreInfo(magic_semaphore);
259 DestroySemaphoreInfo(&magic_semaphore);
260}
261
262/*
263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264% %
265% %
266% %
267+ G e t M a g i c I n f o %
268% %
269% %
270% %
271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272%
273% GetMagicInfo() searches the magic list for the specified name and if found
274% returns attributes for that magic.
275%
276% The format of the GetMagicInfo method is:
277%
278% const MagicInfo *GetMagicInfo(const unsigned char *magic,
279% const size_t length,ExceptionInfo *exception)
280%
281% A description of each parameter follows:
282%
283% o magic: A binary string generally representing the first few characters
284% of the image file or blob.
285%
286% o length: the length of the binary signature.
287%
288% o exception: return any errors or warnings in this structure.
289%
290*/
291MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
292 const size_t length,ExceptionInfo *exception)
293{
294 register const MagicInfo
295 *p;
296
297 assert(exception != (ExceptionInfo *) NULL);
298 if ((magic_list == (LinkedListInfo *) NULL) ||
299 (instantiate_magic == MagickFalse))
300 if (InitializeMagicList(exception) == MagickFalse)
301 return((const MagicInfo *) NULL);
302 if ((magic_list == (LinkedListInfo *) NULL) ||
303 (IsLinkedListEmpty(magic_list) != MagickFalse))
304 return((const MagicInfo *) NULL);
305 if (magic == (const unsigned char *) NULL)
306 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
307 if (length == 0)
308 return((const MagicInfo *) NULL);
309 /*
310 Search for magic tag.
311 */
312 AcquireSemaphoreInfo(&magic_semaphore);
313 ResetLinkedListIterator(magic_list);
314 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
315 while (p != (const MagicInfo *) NULL)
316 {
317 assert(p->offset >= 0);
318 if (((size_t) (p->offset+p->length) <= length) &&
319 (memcmp(magic+p->offset,p->magic,p->length) == 0))
320 break;
321 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
322 }
323 if (p != (const MagicInfo *) NULL)
324 (void) InsertValueInLinkedList(magic_list,0,
325 RemoveElementByValueFromLinkedList(magic_list,p));
326 RelinquishSemaphoreInfo(magic_semaphore);
327 return(p);
328}
329
330/*
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332% %
333% %
334% %
335% G e t M a g i c I n f o L i s t %
336% %
337% %
338% %
339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340%
341% GetMagicInfoList() returns any image aliases that match the specified
342% pattern.
343%
344% The magic of the GetMagicInfoList function is:
345%
346% const MagicInfo **GetMagicInfoList(const char *pattern,
347% unsigned long *number_aliases,ExceptionInfo *exception)
348%
349% A description of each parameter follows:
350%
351% o pattern: Specifies a pointer to a text string containing a pattern.
352%
cristyfc0d1122009-10-17 20:22:37 +0000353% o number_aliases: This integer returns the number of aliases in the list.
cristy3ed852e2009-09-05 21:47:34 +0000354%
355% o exception: return any errors or warnings in this structure.
356%
357*/
358
359#if defined(__cplusplus) || defined(c_plusplus)
360extern "C" {
361#endif
362
363static int MagicInfoCompare(const void *x,const void *y)
364{
365 const MagicInfo
366 **p,
367 **q;
368
369 p=(const MagicInfo **) x,
370 q=(const MagicInfo **) y;
371 if (LocaleCompare((*p)->path,(*q)->path) == 0)
372 return(LocaleCompare((*p)->name,(*q)->name));
373 return(LocaleCompare((*p)->path,(*q)->path));
374}
375
376#if defined(__cplusplus) || defined(c_plusplus)
377}
378#endif
379
380MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
381 unsigned long *number_aliases,ExceptionInfo *exception)
382{
383 const MagicInfo
384 **aliases;
385
386 register const MagicInfo
387 *p;
388
389 register long
390 i;
391
392 /*
393 Allocate magic list.
394 */
395 assert(pattern != (char *) NULL);
396 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
397 assert(number_aliases != (unsigned long *) NULL);
398 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000399 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000400 if (p == (const MagicInfo *) NULL)
401 return((const MagicInfo **) NULL);
402 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
403 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
404 if (aliases == (const MagicInfo **) NULL)
405 return((const MagicInfo **) NULL);
406 /*
407 Generate magic list.
408 */
409 AcquireSemaphoreInfo(&magic_semaphore);
410 ResetLinkedListIterator(magic_list);
411 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
412 for (i=0; p != (const MagicInfo *) NULL; )
413 {
414 if ((p->stealth == MagickFalse) &&
415 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
416 aliases[i++]=p;
417 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
418 }
419 RelinquishSemaphoreInfo(magic_semaphore);
420 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
421 aliases[i]=(MagicInfo *) NULL;
422 *number_aliases=(unsigned long) i;
423 return(aliases);
424}
425
426/*
427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428% %
429% %
430% %
431% G e t M a g i c L i s t %
432% %
433% %
434% %
435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
436%
437% GetMagicList() returns any image format aliases that match the specified
438% pattern.
439%
440% The format of the GetMagicList function is:
441%
442% char **GetMagicList(const char *pattern,unsigned long *number_aliases,
443% ExceptionInfo *exception)
444%
445% A description of each parameter follows:
446%
447% o pattern: Specifies a pointer to a text string containing a pattern.
448%
449% o number_aliases: This integer returns the number of image format aliases
450% in the list.
451%
452% o exception: return any errors or warnings in this structure.
453%
454*/
455
456#if defined(__cplusplus) || defined(c_plusplus)
457extern "C" {
458#endif
459
460static int MagicCompare(const void *x,const void *y)
461{
462 register const char
463 *p,
464 *q;
465
466 p=(const char *) x;
467 q=(const char *) y;
468 return(LocaleCompare(p,q));
469}
470
471#if defined(__cplusplus) || defined(c_plusplus)
472}
473#endif
474
475MagickExport char **GetMagicList(const char *pattern,
476 unsigned long *number_aliases,ExceptionInfo *exception)
477{
478 char
479 **aliases;
480
481 register const MagicInfo
482 *p;
483
484 register long
485 i;
486
487 /*
488 Allocate configure list.
489 */
490 assert(pattern != (char *) NULL);
491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
492 assert(number_aliases != (unsigned long *) NULL);
493 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000494 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000495 if (p == (const MagicInfo *) NULL)
496 return((char **) NULL);
497 aliases=(char **) AcquireQuantumMemory((size_t)
498 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
499 if (aliases == (char **) NULL)
500 return((char **) NULL);
501 AcquireSemaphoreInfo(&magic_semaphore);
502 ResetLinkedListIterator(magic_list);
503 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
504 for (i=0; p != (const MagicInfo *) NULL; )
505 {
506 if ((p->stealth == MagickFalse) &&
507 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
508 aliases[i++]=ConstantString(p->name);
509 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
510 }
511 RelinquishSemaphoreInfo(magic_semaphore);
512 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
513 aliases[i]=(char *) NULL;
514 *number_aliases=(unsigned long) i;
515 return(aliases);
516}
517
518/*
519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520% %
521% %
522% %
523% G e t M a g i c N a m e %
524% %
525% %
526% %
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528%
529% GetMagicName() returns the name associated with the magic.
530%
531% The format of the GetMagicName method is:
532%
533% const char *GetMagicName(const MagicInfo *magic_info)
534%
535% A description of each parameter follows:
536%
537% o magic_info: The magic info.
538%
539*/
540MagickExport const char *GetMagicName(const MagicInfo *magic_info)
541{
542 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
543 assert(magic_info != (MagicInfo *) NULL);
544 assert(magic_info->signature == MagickSignature);
545 return(magic_info->name);
546}
547
548/*
549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550% %
551% %
552% %
553+ I n i t i a l i z e M a g i c L i s t %
554% %
555% %
556% %
557%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
558%
559% InitializeMagicList() initializes the magic list.
560%
561% The format of the InitializeMagicList method is:
562%
563% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
564%
565% A description of each parameter follows.
566%
567% o exception: return any errors or warnings in this structure.
568%
569*/
570static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
571{
572 if ((magic_list == (LinkedListInfo *) NULL) &&
573 (instantiate_magic == MagickFalse))
574 {
575 AcquireSemaphoreInfo(&magic_semaphore);
576 if ((magic_list == (LinkedListInfo *) NULL) &&
577 (instantiate_magic == MagickFalse))
578 {
579 (void) LoadMagicLists(MagicFilename,exception);
580 instantiate_magic=MagickTrue;
581 }
582 RelinquishSemaphoreInfo(magic_semaphore);
583 }
584 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
585}
586
587/*
588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589% %
590% %
591% %
cristydf1cc5f2009-10-19 16:02:33 +0000592+ I n s t a n t i a t e M a g i c C o m p o n e n t %
cristy41c3c772009-10-19 02:17:37 +0000593% %
594% %
595% %
596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597%
cristydf1cc5f2009-10-19 16:02:33 +0000598% InstantiateMagicComponent() instantiates the magic component.
cristy41c3c772009-10-19 02:17:37 +0000599%
cristydf1cc5f2009-10-19 16:02:33 +0000600% The format of the InstantiateMagicComponent method is:
cristy41c3c772009-10-19 02:17:37 +0000601%
cristydf1cc5f2009-10-19 16:02:33 +0000602% MagickBooleanType InstantiateMagicComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000603%
604*/
cristydf1cc5f2009-10-19 16:02:33 +0000605MagickExport MagickBooleanType InstantiateMagicComponent(void)
cristy41c3c772009-10-19 02:17:37 +0000606{
607 AcquireSemaphoreInfo(&magic_semaphore);
608 RelinquishSemaphoreInfo(magic_semaphore);
609 return(MagickTrue);
610}
611
612/*
613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614% %
615% %
616% %
cristy3ed852e2009-09-05 21:47:34 +0000617% L i s t M a g i c I n f o %
618% %
619% %
620% %
621%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622%
623% ListMagicInfo() lists the magic info to a file.
624%
625% The format of the ListMagicInfo method is:
626%
627% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
628%
629% A description of each parameter follows.
630%
631% o file: An pointer to a FILE.
632%
633% o exception: return any errors or warnings in this structure.
634%
635*/
636MagickExport MagickBooleanType ListMagicInfo(FILE *file,
637 ExceptionInfo *exception)
638{
639 const char
640 *path;
641
642 const MagicInfo
643 **magic_info;
644
645 long
646 j;
647
648 register long
649 i;
650
651 unsigned long
652 number_aliases;
653
654 if (file == (const FILE *) NULL)
655 file=stdout;
656 magic_info=GetMagicInfoList("*",&number_aliases,exception);
657 if (magic_info == (const MagicInfo **) NULL)
658 return(MagickFalse);
659 j=0;
660 path=(const char *) NULL;
661 for (i=0; i < (long) number_aliases; i++)
662 {
663 if (magic_info[i]->stealth != MagickFalse)
664 continue;
665 if ((path == (const char *) NULL) ||
666 (LocaleCompare(path,magic_info[i]->path) != 0))
667 {
668 if (magic_info[i]->path != (char *) NULL)
669 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
670 (void) fprintf(file,"Name Offset Target\n");
671 (void) fprintf(file,"-------------------------------------------------"
672 "------------------------------\n");
673 }
674 path=magic_info[i]->path;
675 (void) fprintf(file,"%s",magic_info[i]->name);
676 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
677 (void) fprintf(file," ");
678 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
679 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000680 {
681 register long
682 j;
683
684 for (j=0; magic_info[i]->target[j] != '\0'; j++)
685 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
686 (void) fprintf(file,"%c",magic_info[i]->target[j]);
687 else
cristy50931922009-10-15 18:59:59 +0000688 (void) fprintf(file,"\\%03o",(unsigned int)
689 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000690 }
cristy3ed852e2009-09-05 21:47:34 +0000691 (void) fprintf(file,"\n");
692 }
693 (void) fflush(file);
694 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
695 return(MagickTrue);
696}
697
698/*
699%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700% %
701% %
702% %
703+ L o a d M a g i c L i s t %
704% %
705% %
706% %
707%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708%
709% LoadMagicList() loads the magic configuration file which provides a mapping
710% between magic attributes and a magic name.
711%
712% The format of the LoadMagicList method is:
713%
714% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
715% const unsigned long depth,ExceptionInfo *exception)
716%
717% A description of each parameter follows:
718%
cristy1ca3eb32009-10-15 18:41:54 +0000719% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000720%
cristy1ca3eb32009-10-15 18:41:54 +0000721% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000722%
723% o depth: depth of <include /> statements.
724%
725% o exception: return any errors or warnings in this structure.
726%
727*/
728static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
729 const unsigned long depth,ExceptionInfo *exception)
730{
731 char
732 keyword[MaxTextExtent],
733 *token;
734
735 const char
736 *q;
737
738 MagickBooleanType
739 status;
740
741 MagicInfo
742 *magic_info;
743
744 /*
745 Load the magic map file.
746 */
747 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
748 "Loading magic configure file \"%s\" ...",filename);
749 if (xml == (char *) NULL)
750 return(MagickFalse);
751 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000752 {
753 magic_list=NewLinkedList(0);
754 if (magic_list == (LinkedListInfo *) NULL)
755 {
756 ThrowFileException(exception,ResourceLimitError,
757 "MemoryAllocationFailed",filename);
758 return(MagickFalse);
759 }
760 }
cristy3ed852e2009-09-05 21:47:34 +0000761 status=MagickTrue;
762 magic_info=(MagicInfo *) NULL;
763 token=AcquireString(xml);
764 for (q=(char *) xml; *q != '\0'; )
765 {
766 /*
767 Interpret XML.
768 */
769 GetMagickToken(q,&q,token);
770 if (*token == '\0')
771 break;
772 (void) CopyMagickString(keyword,token,MaxTextExtent);
773 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
774 {
775 /*
776 Doctype element.
777 */
778 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
779 GetMagickToken(q,&q,token);
780 continue;
781 }
782 if (LocaleNCompare(keyword,"<!--",4) == 0)
783 {
784 /*
785 Comment element.
786 */
787 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
788 GetMagickToken(q,&q,token);
789 continue;
790 }
791 if (LocaleCompare(keyword,"<include") == 0)
792 {
793 /*
794 Include element.
795 */
796 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
797 {
798 (void) CopyMagickString(keyword,token,MaxTextExtent);
799 GetMagickToken(q,&q,token);
800 if (*token != '=')
801 continue;
802 GetMagickToken(q,&q,token);
803 if (LocaleCompare(keyword,"file") == 0)
804 {
805 if (depth > 200)
806 (void) ThrowMagickException(exception,GetMagickModule(),
807 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
808 else
809 {
810 char
811 path[MaxTextExtent],
812 *xml;
813
814 GetPathComponent(filename,HeadPath,path);
815 if (*path != '\0')
816 (void) ConcatenateMagickString(path,DirectorySeparator,
817 MaxTextExtent);
818 if (*token == *DirectorySeparator)
819 (void) CopyMagickString(path,token,MaxTextExtent);
820 else
821 (void) ConcatenateMagickString(path,token,MaxTextExtent);
822 xml=FileToString(path,~0,exception);
823 if (xml != (char *) NULL)
824 {
825 status=LoadMagicList(xml,path,depth+1,exception);
826 xml=(char *) RelinquishMagickMemory(xml);
827 }
828 }
829 }
830 }
831 continue;
832 }
833 if (LocaleCompare(keyword,"<magic") == 0)
834 {
835 /*
836 Magic element.
837 */
838 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
839 if (magic_info == (MagicInfo *) NULL)
840 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
841 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
842 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000843 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000844 magic_info->signature=MagickSignature;
845 continue;
846 }
847 if (magic_info == (MagicInfo *) NULL)
848 continue;
849 if (LocaleCompare(keyword,"/>") == 0)
850 {
851 status=AppendValueToLinkedList(magic_list,magic_info);
852 if (status == MagickFalse)
853 (void) ThrowMagickException(exception,GetMagickModule(),
854 ResourceLimitError,"MemoryAllocationFailed","`%s'",
855 magic_info->name);
856 magic_info=(MagicInfo *) NULL;
857 }
858 GetMagickToken(q,(const char **) NULL,token);
859 if (*token != '=')
860 continue;
861 GetMagickToken(q,&q,token);
862 GetMagickToken(q,&q,token);
863 switch (*keyword)
864 {
865 case 'N':
866 case 'n':
867 {
868 if (LocaleCompare((char *) keyword,"name") == 0)
869 {
870 magic_info->name=ConstantString(token);
871 break;
872 }
873 break;
874 }
875 case 'O':
876 case 'o':
877 {
878 if (LocaleCompare((char *) keyword,"offset") == 0)
879 {
880 magic_info->offset=(MagickOffsetType) atol(token);
881 break;
882 }
883 break;
884 }
885 case 'S':
886 case 's':
887 {
888 if (LocaleCompare((char *) keyword,"stealth") == 0)
889 {
890 magic_info->stealth=IsMagickTrue(token);
891 break;
892 }
893 break;
894 }
895 case 'T':
896 case 't':
897 {
898 if (LocaleCompare((char *) keyword,"target") == 0)
899 {
900 char
901 *p;
902
903 register unsigned char
904 *q;
905
906 size_t
907 length;
908
909 length=strlen(token);
910 magic_info->target=ConstantString(token);
911 magic_info->magic=(unsigned char *) ConstantString(token);
912 q=magic_info->magic;
913 for (p=magic_info->target; *p != '\0'; )
914 {
915 if (*p == '\\')
916 {
917 p++;
918 if (isdigit((int) ((unsigned char) *p)) != 0)
919 {
920 char
921 *end;
922
923 *q++=(unsigned char) strtol(p,&end,8);
924 p+=(end-p);
925 magic_info->length++;
926 continue;
927 }
928 switch (*p)
929 {
930 case 'b': *q='\b'; break;
931 case 'f': *q='\f'; break;
932 case 'n': *q='\n'; break;
933 case 'r': *q='\r'; break;
934 case 't': *q='\t'; break;
935 case 'v': *q='\v'; break;
936 case 'a': *q='a'; break;
937 case '?': *q='\?'; break;
938 default: *q=(unsigned char) (*p); break;
939 }
940 p++;
941 q++;
942 magic_info->length++;
943 continue;
944 }
945 else
946 if (LocaleNCompare(p,"&amp;",5) == 0)
947 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
948 *q++=(unsigned char) (*p++);
949 magic_info->length++;
950 }
951 break;
952 }
953 break;
954 }
955 default:
956 break;
957 }
958 }
959 token=(char *) RelinquishMagickMemory(token);
960 return(status);
961}
962
963/*
964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965% %
966% %
967% %
968% L o a d M a g i c L i s t s %
969% %
970% %
971% %
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973%
974% LoadMagicLists() loads one or more magic configuration file which provides a
975% mapping between magic attributes and a magic name.
976%
977% The format of the LoadMagicLists method is:
978%
979% MagickBooleanType LoadMagicLists(const char *filename,
980% ExceptionInfo *exception)
981%
982% A description of each parameter follows:
983%
984% o filename: the font file name.
985%
986% o exception: return any errors or warnings in this structure.
987%
988*/
989static MagickBooleanType LoadMagicLists(const char *filename,
990 ExceptionInfo *exception)
991{
cristy3ed852e2009-09-05 21:47:34 +0000992 char
993 path[MaxTextExtent];
994
995 const StringInfo
996 *option;
997
998 LinkedListInfo
999 *options;
1000
1001 MagickStatusType
1002 status;
1003
cristy54a531d2009-10-21 17:58:01 +00001004 register long
1005 i;
cristy1ca3eb32009-10-15 18:41:54 +00001006
1007 /*
1008 Load built-in magic map.
1009 */
cristy3ed852e2009-09-05 21:47:34 +00001010 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +00001011 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +00001012 {
1013 magic_list=NewLinkedList(0);
1014 if (magic_list == (LinkedListInfo *) NULL)
1015 {
1016 ThrowFileException(exception,ResourceLimitError,
1017 "MemoryAllocationFailed",filename);
1018 return(MagickFalse);
1019 }
1020 }
cristy54a531d2009-10-21 17:58:01 +00001021 for (i=0; i < (long) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
cristy1ca3eb32009-10-15 18:41:54 +00001022 {
1023 MagicInfo
1024 *magic_info;
1025
cristy54a531d2009-10-21 17:58:01 +00001026 register const MagicMapInfo
1027 *p;
1028
1029 p=MagicMap+i;
cristy1ca3eb32009-10-15 18:41:54 +00001030 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
1031 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +00001032 {
1033 (void) ThrowMagickException(exception,GetMagickModule(),
1034 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1035 continue;
1036 }
cristy1ca3eb32009-10-15 18:41:54 +00001037 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
cristy38b8ed92009-10-16 01:20:21 +00001038 magic_info->path=(char *) "[built-in]";
cristy1ca3eb32009-10-15 18:41:54 +00001039 magic_info->name=(char *) p->name;
1040 magic_info->offset=p->offset;
1041 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +00001042 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +00001043 magic_info->length=p->length;
1044 magic_info->exempt=MagickTrue;
1045 magic_info->signature=MagickSignature;
1046 status=AppendValueToLinkedList(magic_list,magic_info);
1047 if (status == MagickFalse)
1048 (void) ThrowMagickException(exception,GetMagickModule(),
1049 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1050 }
1051 /*
1052 Load external magic map.
1053 */
cristy3ed852e2009-09-05 21:47:34 +00001054 *path='\0';
1055 options=GetConfigureOptions(filename,exception);
1056 option=(const StringInfo *) GetNextValueInLinkedList(options);
1057 while (option != (const StringInfo *) NULL)
1058 {
1059 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1060 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
1061 GetStringInfoPath(option),0,exception);
1062 option=(const StringInfo *) GetNextValueInLinkedList(options);
1063 }
1064 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001065 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001066}