blob: 3300abb53633f0aefca55566c92e607473752d79 [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"
60
61/*
62 Static declarations.
63*/
cristy1ca3eb32009-10-15 18:41:54 +000064typedef struct _MagicMapInfo
65{
66 const char
67 *name;
68
cristye3e77a12009-10-16 00:47:21 +000069 const MagickOffsetType
70 offset;
71
cristybcdce3d2009-10-15 20:04:49 +000072 const unsigned char
cristy1ca3eb32009-10-15 18:41:54 +000073 *magic;
74
cristye3e77a12009-10-16 00:47:21 +000075 const size_t
cristy1ca3eb32009-10-15 18:41:54 +000076 length;
cristy1ca3eb32009-10-15 18:41:54 +000077} MagicMapInfo;
78
cristye3e77a12009-10-16 00:47:21 +000079#define MagickString(magic) (const unsigned char *) (magic), sizeof(magic)-1
cristy1ca3eb32009-10-15 18:41:54 +000080
81static const MagicMapInfo
82 MagicMap[] =
83 {
cristye3e77a12009-10-16 00:47:21 +000084 { "AVI", 0, MagickString("RIFF") },
85 { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
86 { "8BIMTEXT", 0, MagickString("8BIM#") },
87 { "8BIM", 0, MagickString("8BIM") },
88 { "BMP", 0, MagickString("BA") },
89 { "BMP", 0, MagickString("BM") },
90 { "BMP", 0, MagickString("CI") },
91 { "BMP", 0, MagickString("CP") },
92 { "BMP", 0, MagickString("IC") },
93 { "BMP", 0, MagickString("PI") },
94 { "CALS", 21, MagickString("version: MIL-STD-1840") },
95 { "CALS", 0, MagickString("srcdocid:") },
96 { "CALS", 9, MagickString("srcdocid:") },
97 { "CALS", 8, MagickString("rorient:") },
98 { "CGM", 0, MagickString("BEGMF") },
99 { "CIN", 0, MagickString("\200\052\137\327") },
100 { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
101 { "DCM", 128, MagickString("DICM") },
102 { "DCX", 0, MagickString("\261\150\336\72") },
103 { "DIB", 0, MagickString("\050\000") },
104 { "DDS", 0, MagickString("DDS ") },
105 { "DJVU", 0, MagickString("AT&TFORM") },
106 { "DOT", 0, MagickString("digraph") },
107 { "DPX", 0, MagickString("SDPX") },
108 { "DPX", 0, MagickString("XPDS") },
109 { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
110 { "EPT", 0, MagickString("\305\320\323\306") },
111 { "EXR", 0, MagickString("\166\057\061\001") },
112 { "FAX", 0, MagickString("DFAX") },
113 { "FIG", 0, MagickString("#FIG") },
114 { "FITS", 0, MagickString("IT0") },
115 { "FITS", 0, MagickString("SIMPLE") },
116 { "FPX", 0, MagickString("\320\317\021\340") },
117 { "GIF", 0, MagickString("GIF8") },
118 { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
119 { "HDF", 1, MagickString("HDF") },
120 { "HPGL", 0, MagickString("IN;") },
121 { "HPGL", 0, MagickString("\033E\033") },
122 { "HTML", 1, MagickString("HTML") },
123 { "HTML", 1, MagickString("html") },
124 { "ILBM", 8, MagickString("ILBM") },
125 { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
126 { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
127 { "IPTC", 0, MagickString("\034\002") },
128 { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
129 { "JPEG", 0, MagickString("\377\330\377") },
130 { "JPC", 0, MagickString("\377\117") },
131 { "JP2", 4, MagickString("\152\120\040\040\015") },
132 { "MIFF", 0, MagickString("Id=ImageMagick") },
133 { "MIFF", 0, MagickString("id=ImageMagick") },
134 { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
135 { "MPC", 0, MagickString("id=MagickCache") },
136 { "MPEG", 0, MagickString("\000\000\001\263") },
137 { "MRW", 0, MagickString("\x00MRM") },
138 { "MVG", 0, MagickString("push graphic-context") },
139 { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
140 { "PCD", 2048, MagickString("PCD_") },
141 { "PCL", 0, MagickString("\033E\033") },
142 { "PCX", 0, MagickString("\012\002") },
143 { "PCX", 0, MagickString("\012\005") },
144 { "PDB", 60, MagickString("vIMGView") },
145 { "PDF", 0, MagickString("%PDF-") },
146 { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
147 { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
148 { "PGX", 0, MagickString("\050\107\020\115\046") },
149 { "PICT", 522, MagickString("\000\021\002\377\014\000") },
150 { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
151 { "PNM", 0, MagickString("P1") },
152 { "PNM", 0, MagickString("P2") },
153 { "PNM", 0, MagickString("P3") },
154 { "PNM", 0, MagickString("P4") },
155 { "PNM", 0, MagickString("P5") },
156 { "PNM", 0, MagickString("P6") },
157 { "PNM", 0, MagickString("P7") },
158 { "PNM", 0, MagickString("PF") },
159 { "PNM", 0, MagickString("Pf") },
160 { "PS", 0, MagickString("%!") },
161 { "PS", 0, MagickString("\004%!") },
162 { "PS", 0, MagickString("\305\320\323\306") },
163 { "PSD", 0, MagickString("8BPS") },
164 { "PWP", 0, MagickString("SFW95") },
165 { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
166 { "RAD", 0, MagickString("#?RADIANCE") },
167 { "RAD", 0, MagickString("VIEW= ") },
168 { "RLE", 0, MagickString("\122\314") },
169 { "SCT", 0, MagickString("CT") },
170 { "SFW", 0, MagickString("SFW94") },
171 { "SGI", 0, MagickString("\001\332") },
172 { "SUN", 0, MagickString("\131\246\152\225") },
173 { "SVG", 1, MagickString("?XML") },
174 { "SVG", 1, MagickString("?xml") },
175 { "TIFF", 0, MagickString("\115\115\000\052") },
176 { "TIFF", 0, MagickString("\111\111\052\000") },
177 { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
178 { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
179 { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
180 { "VICAR", 0, MagickString("LBLSIZE") },
181 { "VICAR", 0, MagickString("NJPL1I") },
182 { "VIFF", 0, MagickString("\253\001") },
183 { "WMF", 0, MagickString("\327\315\306\232") },
184 { "WMF", 0, MagickString("\001\000\011\000") },
185 { "WPG", 0, MagickString("\377WPC") },
186 { "XBM", 0, MagickString("#define") },
187 { "XCF", 0, MagickString("gimp xcf") },
188 { "XEF", 0, MagickString("FOVb") },
189 { "XPM", 1, MagickString("* XPM *") },
190 { "XWD", 4, MagickString("\007\000\000") },
191 { "XWD", 5, MagickString("\000\000\007") },
192 { (const char *) NULL, 0, MagickString((const char *) NULL) }
cristy1ca3eb32009-10-15 18:41:54 +0000193 };
cristy3ed852e2009-09-05 21:47:34 +0000194
195static LinkedListInfo
196 *magic_list = (LinkedListInfo *) NULL;
197
198static SemaphoreInfo
199 *magic_semaphore = (SemaphoreInfo *) NULL;
200
201static volatile MagickBooleanType
202 instantiate_magic = MagickFalse;
203
204/*
205 Forward declarations.
206*/
207static MagickBooleanType
208 InitializeMagicList(ExceptionInfo *),
209 LoadMagicLists(const char *,ExceptionInfo *);
210
211/*
212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213% %
214% %
215% %
216+ D e s t r o y M a g i c L i s t %
217% %
218% %
219% %
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221%
222% DestroyMagicList() deallocates memory associated with the magic list.
223%
224% The format of the DestroyMagicList method is:
225%
226% DestroyMagicList(void)
227%
228*/
229
230static void *DestroyMagicElement(void *magic_info)
231{
232 register MagicInfo
233 *p;
234
235 p=(MagicInfo *) magic_info;
cristy1ca3eb32009-10-15 18:41:54 +0000236 if (p->exempt == MagickFalse)
237 {
238 if (p->path != (char *) NULL)
239 p->path=DestroyString(p->path);
240 if (p->name != (char *) NULL)
241 p->name=DestroyString(p->name);
242 if (p->target != (char *) NULL)
243 p->target=DestroyString(p->target);
244 if (p->magic != (unsigned char *) NULL)
245 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
246 }
cristy3ed852e2009-09-05 21:47:34 +0000247 p=(MagicInfo *) RelinquishMagickMemory(p);
248 return((void *) NULL);
249}
250
251MagickExport void DestroyMagicList(void)
252{
253 AcquireSemaphoreInfo(&magic_semaphore);
254 if (magic_list != (LinkedListInfo *) NULL)
255 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
256 instantiate_magic=MagickFalse;
257 RelinquishSemaphoreInfo(magic_semaphore);
258 DestroySemaphoreInfo(&magic_semaphore);
259}
260
261/*
262%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263% %
264% %
265% %
266+ G e t M a g i c I n f o %
267% %
268% %
269% %
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271%
272% GetMagicInfo() searches the magic list for the specified name and if found
273% returns attributes for that magic.
274%
275% The format of the GetMagicInfo method is:
276%
277% const MagicInfo *GetMagicInfo(const unsigned char *magic,
278% const size_t length,ExceptionInfo *exception)
279%
280% A description of each parameter follows:
281%
282% o magic: A binary string generally representing the first few characters
283% of the image file or blob.
284%
285% o length: the length of the binary signature.
286%
287% o exception: return any errors or warnings in this structure.
288%
289*/
290MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
291 const size_t length,ExceptionInfo *exception)
292{
293 register const MagicInfo
294 *p;
295
296 assert(exception != (ExceptionInfo *) NULL);
297 if ((magic_list == (LinkedListInfo *) NULL) ||
298 (instantiate_magic == MagickFalse))
299 if (InitializeMagicList(exception) == MagickFalse)
300 return((const MagicInfo *) NULL);
301 if ((magic_list == (LinkedListInfo *) NULL) ||
302 (IsLinkedListEmpty(magic_list) != MagickFalse))
303 return((const MagicInfo *) NULL);
304 if (magic == (const unsigned char *) NULL)
305 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
306 if (length == 0)
307 return((const MagicInfo *) NULL);
308 /*
309 Search for magic tag.
310 */
311 AcquireSemaphoreInfo(&magic_semaphore);
312 ResetLinkedListIterator(magic_list);
313 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
314 while (p != (const MagicInfo *) NULL)
315 {
316 assert(p->offset >= 0);
317 if (((size_t) (p->offset+p->length) <= length) &&
318 (memcmp(magic+p->offset,p->magic,p->length) == 0))
319 break;
320 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
321 }
322 if (p != (const MagicInfo *) NULL)
323 (void) InsertValueInLinkedList(magic_list,0,
324 RemoveElementByValueFromLinkedList(magic_list,p));
325 RelinquishSemaphoreInfo(magic_semaphore);
326 return(p);
327}
328
329/*
330%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331% %
332% %
333% %
334% G e t M a g i c I n f o L i s t %
335% %
336% %
337% %
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339%
340% GetMagicInfoList() returns any image aliases that match the specified
341% pattern.
342%
343% The magic of the GetMagicInfoList function is:
344%
345% const MagicInfo **GetMagicInfoList(const char *pattern,
346% unsigned long *number_aliases,ExceptionInfo *exception)
347%
348% A description of each parameter follows:
349%
350% o pattern: Specifies a pointer to a text string containing a pattern.
351%
352% o number_aliases: This integer returns the number of aliases in the
353% list.
354%
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% %
592% L i s t M a g i c I n f o %
593% %
594% %
595% %
596%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
597%
598% ListMagicInfo() lists the magic info to a file.
599%
600% The format of the ListMagicInfo method is:
601%
602% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
603%
604% A description of each parameter follows.
605%
606% o file: An pointer to a FILE.
607%
608% o exception: return any errors or warnings in this structure.
609%
610*/
611MagickExport MagickBooleanType ListMagicInfo(FILE *file,
612 ExceptionInfo *exception)
613{
614 const char
615 *path;
616
617 const MagicInfo
618 **magic_info;
619
620 long
621 j;
622
623 register long
624 i;
625
626 unsigned long
627 number_aliases;
628
629 if (file == (const FILE *) NULL)
630 file=stdout;
631 magic_info=GetMagicInfoList("*",&number_aliases,exception);
632 if (magic_info == (const MagicInfo **) NULL)
633 return(MagickFalse);
634 j=0;
635 path=(const char *) NULL;
636 for (i=0; i < (long) number_aliases; i++)
637 {
638 if (magic_info[i]->stealth != MagickFalse)
639 continue;
640 if ((path == (const char *) NULL) ||
641 (LocaleCompare(path,magic_info[i]->path) != 0))
642 {
643 if (magic_info[i]->path != (char *) NULL)
644 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
645 (void) fprintf(file,"Name Offset Target\n");
646 (void) fprintf(file,"-------------------------------------------------"
647 "------------------------------\n");
648 }
649 path=magic_info[i]->path;
650 (void) fprintf(file,"%s",magic_info[i]->name);
651 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
652 (void) fprintf(file," ");
653 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
654 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000655 {
656 register long
657 j;
658
659 for (j=0; magic_info[i]->target[j] != '\0'; j++)
660 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
661 (void) fprintf(file,"%c",magic_info[i]->target[j]);
662 else
cristy50931922009-10-15 18:59:59 +0000663 (void) fprintf(file,"\\%03o",(unsigned int)
664 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000665 }
cristy3ed852e2009-09-05 21:47:34 +0000666 (void) fprintf(file,"\n");
667 }
668 (void) fflush(file);
669 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
670 return(MagickTrue);
671}
672
673/*
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675% %
676% %
677% %
678+ L o a d M a g i c L i s t %
679% %
680% %
681% %
682%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683%
684% LoadMagicList() loads the magic configuration file which provides a mapping
685% between magic attributes and a magic name.
686%
687% The format of the LoadMagicList method is:
688%
689% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
690% const unsigned long depth,ExceptionInfo *exception)
691%
692% A description of each parameter follows:
693%
cristy1ca3eb32009-10-15 18:41:54 +0000694% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000695%
cristy1ca3eb32009-10-15 18:41:54 +0000696% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000697%
698% o depth: depth of <include /> statements.
699%
700% o exception: return any errors or warnings in this structure.
701%
702*/
703static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
704 const unsigned long depth,ExceptionInfo *exception)
705{
706 char
707 keyword[MaxTextExtent],
708 *token;
709
710 const char
711 *q;
712
713 MagickBooleanType
714 status;
715
716 MagicInfo
717 *magic_info;
718
719 /*
720 Load the magic map file.
721 */
722 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
723 "Loading magic configure file \"%s\" ...",filename);
724 if (xml == (char *) NULL)
725 return(MagickFalse);
726 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000727 {
728 magic_list=NewLinkedList(0);
729 if (magic_list == (LinkedListInfo *) NULL)
730 {
731 ThrowFileException(exception,ResourceLimitError,
732 "MemoryAllocationFailed",filename);
733 return(MagickFalse);
734 }
735 }
cristy3ed852e2009-09-05 21:47:34 +0000736 status=MagickTrue;
737 magic_info=(MagicInfo *) NULL;
738 token=AcquireString(xml);
739 for (q=(char *) xml; *q != '\0'; )
740 {
741 /*
742 Interpret XML.
743 */
744 GetMagickToken(q,&q,token);
745 if (*token == '\0')
746 break;
747 (void) CopyMagickString(keyword,token,MaxTextExtent);
748 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
749 {
750 /*
751 Doctype element.
752 */
753 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
754 GetMagickToken(q,&q,token);
755 continue;
756 }
757 if (LocaleNCompare(keyword,"<!--",4) == 0)
758 {
759 /*
760 Comment element.
761 */
762 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
763 GetMagickToken(q,&q,token);
764 continue;
765 }
766 if (LocaleCompare(keyword,"<include") == 0)
767 {
768 /*
769 Include element.
770 */
771 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
772 {
773 (void) CopyMagickString(keyword,token,MaxTextExtent);
774 GetMagickToken(q,&q,token);
775 if (*token != '=')
776 continue;
777 GetMagickToken(q,&q,token);
778 if (LocaleCompare(keyword,"file") == 0)
779 {
780 if (depth > 200)
781 (void) ThrowMagickException(exception,GetMagickModule(),
782 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
783 else
784 {
785 char
786 path[MaxTextExtent],
787 *xml;
788
789 GetPathComponent(filename,HeadPath,path);
790 if (*path != '\0')
791 (void) ConcatenateMagickString(path,DirectorySeparator,
792 MaxTextExtent);
793 if (*token == *DirectorySeparator)
794 (void) CopyMagickString(path,token,MaxTextExtent);
795 else
796 (void) ConcatenateMagickString(path,token,MaxTextExtent);
797 xml=FileToString(path,~0,exception);
798 if (xml != (char *) NULL)
799 {
800 status=LoadMagicList(xml,path,depth+1,exception);
801 xml=(char *) RelinquishMagickMemory(xml);
802 }
803 }
804 }
805 }
806 continue;
807 }
808 if (LocaleCompare(keyword,"<magic") == 0)
809 {
810 /*
811 Magic element.
812 */
813 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
814 if (magic_info == (MagicInfo *) NULL)
815 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
816 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
817 magic_info->path=ConstantString(filename);
cristye3e77a12009-10-16 00:47:21 +0000818 magic_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000819 magic_info->signature=MagickSignature;
820 continue;
821 }
822 if (magic_info == (MagicInfo *) NULL)
823 continue;
824 if (LocaleCompare(keyword,"/>") == 0)
825 {
826 status=AppendValueToLinkedList(magic_list,magic_info);
827 if (status == MagickFalse)
828 (void) ThrowMagickException(exception,GetMagickModule(),
829 ResourceLimitError,"MemoryAllocationFailed","`%s'",
830 magic_info->name);
831 magic_info=(MagicInfo *) NULL;
832 }
833 GetMagickToken(q,(const char **) NULL,token);
834 if (*token != '=')
835 continue;
836 GetMagickToken(q,&q,token);
837 GetMagickToken(q,&q,token);
838 switch (*keyword)
839 {
840 case 'N':
841 case 'n':
842 {
843 if (LocaleCompare((char *) keyword,"name") == 0)
844 {
845 magic_info->name=ConstantString(token);
846 break;
847 }
848 break;
849 }
850 case 'O':
851 case 'o':
852 {
853 if (LocaleCompare((char *) keyword,"offset") == 0)
854 {
855 magic_info->offset=(MagickOffsetType) atol(token);
856 break;
857 }
858 break;
859 }
860 case 'S':
861 case 's':
862 {
863 if (LocaleCompare((char *) keyword,"stealth") == 0)
864 {
865 magic_info->stealth=IsMagickTrue(token);
866 break;
867 }
868 break;
869 }
870 case 'T':
871 case 't':
872 {
873 if (LocaleCompare((char *) keyword,"target") == 0)
874 {
875 char
876 *p;
877
878 register unsigned char
879 *q;
880
881 size_t
882 length;
883
884 length=strlen(token);
885 magic_info->target=ConstantString(token);
886 magic_info->magic=(unsigned char *) ConstantString(token);
887 q=magic_info->magic;
888 for (p=magic_info->target; *p != '\0'; )
889 {
890 if (*p == '\\')
891 {
892 p++;
893 if (isdigit((int) ((unsigned char) *p)) != 0)
894 {
895 char
896 *end;
897
898 *q++=(unsigned char) strtol(p,&end,8);
899 p+=(end-p);
900 magic_info->length++;
901 continue;
902 }
903 switch (*p)
904 {
905 case 'b': *q='\b'; break;
906 case 'f': *q='\f'; break;
907 case 'n': *q='\n'; break;
908 case 'r': *q='\r'; break;
909 case 't': *q='\t'; break;
910 case 'v': *q='\v'; break;
911 case 'a': *q='a'; break;
912 case '?': *q='\?'; break;
913 default: *q=(unsigned char) (*p); break;
914 }
915 p++;
916 q++;
917 magic_info->length++;
918 continue;
919 }
920 else
921 if (LocaleNCompare(p,"&amp;",5) == 0)
922 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
923 *q++=(unsigned char) (*p++);
924 magic_info->length++;
925 }
926 break;
927 }
928 break;
929 }
930 default:
931 break;
932 }
933 }
934 token=(char *) RelinquishMagickMemory(token);
935 return(status);
936}
937
938/*
939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940% %
941% %
942% %
943% L o a d M a g i c L i s t s %
944% %
945% %
946% %
947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948%
949% LoadMagicLists() loads one or more magic configuration file which provides a
950% mapping between magic attributes and a magic name.
951%
952% The format of the LoadMagicLists method is:
953%
954% MagickBooleanType LoadMagicLists(const char *filename,
955% ExceptionInfo *exception)
956%
957% A description of each parameter follows:
958%
959% o filename: the font file name.
960%
961% o exception: return any errors or warnings in this structure.
962%
963*/
964static MagickBooleanType LoadMagicLists(const char *filename,
965 ExceptionInfo *exception)
966{
967#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
968 return(LoadMagicList(MagicMap,"built-in",0,exception));
969#else
970 char
971 path[MaxTextExtent];
972
973 const StringInfo
974 *option;
975
976 LinkedListInfo
977 *options;
978
979 MagickStatusType
980 status;
981
cristy1ca3eb32009-10-15 18:41:54 +0000982 register const MagicMapInfo
983 *p;
984
985 /*
986 Load built-in magic map.
987 */
cristy3ed852e2009-09-05 21:47:34 +0000988 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +0000989 if (magic_list == (LinkedListInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +0000990 {
991 magic_list=NewLinkedList(0);
992 if (magic_list == (LinkedListInfo *) NULL)
993 {
994 ThrowFileException(exception,ResourceLimitError,
995 "MemoryAllocationFailed",filename);
996 return(MagickFalse);
997 }
998 }
cristy1ca3eb32009-10-15 18:41:54 +0000999 for (p=MagicMap; p->name != (const char *) NULL; p++)
1000 {
1001 MagicInfo
1002 *magic_info;
1003
1004 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
1005 if (magic_info == (MagicInfo *) NULL)
cristye3e77a12009-10-16 00:47:21 +00001006 {
1007 (void) ThrowMagickException(exception,GetMagickModule(),
1008 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1009 continue;
1010 }
cristy1ca3eb32009-10-15 18:41:54 +00001011 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
1012 magic_info->path="[built-in]";
1013 magic_info->name=(char *) p->name;
1014 magic_info->offset=p->offset;
1015 magic_info->target=(char *) p->magic;
cristye3e77a12009-10-16 00:47:21 +00001016 magic_info->magic=(unsigned char *) p->magic;
cristy1ca3eb32009-10-15 18:41:54 +00001017 magic_info->length=p->length;
1018 magic_info->exempt=MagickTrue;
1019 magic_info->signature=MagickSignature;
1020 status=AppendValueToLinkedList(magic_list,magic_info);
1021 if (status == MagickFalse)
1022 (void) ThrowMagickException(exception,GetMagickModule(),
1023 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1024 }
1025 /*
1026 Load external magic map.
1027 */
cristy3ed852e2009-09-05 21:47:34 +00001028 *path='\0';
1029 options=GetConfigureOptions(filename,exception);
1030 option=(const StringInfo *) GetNextValueInLinkedList(options);
1031 while (option != (const StringInfo *) NULL)
1032 {
1033 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1034 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
1035 GetStringInfoPath(option),0,exception);
1036 option=(const StringInfo *) GetNextValueInLinkedList(options);
1037 }
1038 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001039 return(status != 0 ? MagickTrue : MagickFalse);
1040#endif
1041}