blob: f51399e6c25df53b7bd50af8cbe734433eb628fe [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
69 unsigned char
70 *magic;
71
72 size_t
73 length;
74
cristy50931922009-10-15 18:59:59 +000075 MagickOffsetType
cristy1ca3eb32009-10-15 18:41:54 +000076 offset;
77} MagicMapInfo;
78
79#define MagicTransform(name,offset,magic) \
cristy50931922009-10-15 18:59:59 +000080 { name, (unsigned char *) magic, sizeof(magic)-1, offset }
cristy1ca3eb32009-10-15 18:41:54 +000081
82static const MagicMapInfo
83 MagicMap[] =
84 {
85 MagicTransform("AVI", 0, "RIFF"),
86 MagicTransform("8BIMWTEXT", 0, "8\000B\000I\000M\000#"),
87 MagicTransform("8BIMTEXT", 0, "8BIM#"),
88 MagicTransform("8BIM", 0, "8BIM"),
89 MagicTransform("BMP", 0, "BA"),
90 MagicTransform("BMP", 0, "BM"),
91 MagicTransform("BMP", 0, "CI"),
92 MagicTransform("BMP", 0, "CP"),
93 MagicTransform("BMP", 0, "IC"),
94 MagicTransform("BMP", 0, "PI"),
95 MagicTransform("CALS", 21, "version: MIL-STD-1840"),
96 MagicTransform("CALS", 0, "srcdocid:"),
97 MagicTransform("CALS", 9, "srcdocid:"),
98 MagicTransform("CALS", 8, "rorient:"),
99 MagicTransform("CGM", 0, "BEGMF"),
100 MagicTransform("CIN", 0, "\200\052\137\327"),
101 MagicTransform("CRW", 0, "II\x1a\x00\x00\x00HEAPCCDR"),
102 MagicTransform("DCM", 128, "DICM"),
103 MagicTransform("DCX", 0, "\261\150\336\72"),
104 MagicTransform("DIB", 0, "\050\000"),
105 MagicTransform("DDS", 0, "DDS "),
106 MagicTransform("DJVU", 0, "AT&TFORM"),
107 MagicTransform("DOT", 0, "digraph"),
108 MagicTransform("DPX", 0, "SDPX"),
109 MagicTransform("DPX", 0, "XPDS"),
110 MagicTransform("EMF", 40, "\040\105\115\106\000\000\001\000"),
111 MagicTransform("EPT", 0, "\305\320\323\306"),
112 MagicTransform("EXR", 0, "\166\057\061\001"),
113 MagicTransform("FAX", 0, "DFAX"),
114 MagicTransform("FIG", 0, "#FIG"),
115 MagicTransform("FITS", 0, "IT0"),
116 MagicTransform("FITS", 0, "SIMPLE"),
117 MagicTransform("FPX", 0, "\320\317\021\340"),
118 MagicTransform("GIF", 0, "GIF8"),
119 MagicTransform("GPLT", 0, "#!/usr/local/bin/gnuplot"),
120 MagicTransform("HDF", 1, "HDF"),
121 MagicTransform("HPGL", 0, "IN;"),
122 MagicTransform("HPGL", 0, "\033E\033"),
123 MagicTransform("HTML", 1, "HTML"),
124 MagicTransform("HTML", 1, "html"),
125 MagicTransform("ILBM", 8, "ILBM"),
126 MagicTransform("IPTCWTEXT", 0, "\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000"),
127 MagicTransform("IPTCTEXT", 0, "2#0=\042�\042"),
128 MagicTransform("IPTC", 0, "\034\002"),
129 MagicTransform("JNG", 0, "\213JNG\r\n\032\n"),
130 MagicTransform("JPEG", 0, "\377\330\377"),
131 MagicTransform("JPC", 0, "\377\117"),
132 MagicTransform("JP2", 4, "\152\120\040\040\015"),
133 MagicTransform("MIFF", 0, "Id=ImageMagick"),
134 MagicTransform("MIFF", 0, "id=ImageMagick"),
135 MagicTransform("MNG", 0, "\212MNG\r\n\032\n"),
136 MagicTransform("MPC", 0, "id=MagickCache"),
137 MagicTransform("MPEG", 0, "\000\000\001\263"),
138 MagicTransform("MRW", 0, "\x00MRM"),
139 MagicTransform("MVG", 0, "push graphic-context"),
140 MagicTransform("ORF", 0, "IIRO\x08\x00\x00\x00"),
141 MagicTransform("PCD", 2048, "PCD_"),
142 MagicTransform("PCL", 0, "\033E\033"),
143 MagicTransform("PCX", 0, "\012\002"),
144 MagicTransform("PCX", 0, "\012\005"),
145 MagicTransform("PDB", 60, "vIMGView"),
146 MagicTransform("PDF", 0, "%PDF-"),
147 MagicTransform("PFA", 0, "%!PS-AdobeFont-1.0"),
148 MagicTransform("PFB", 6, "%!PS-AdobeFont-1.0"),
149 MagicTransform("PGX", 0, "\050\107\020\115\046"),
150 MagicTransform("PICT", 522, "\000\021\002\377\014\000"),
151 MagicTransform("PNG", 0, "\211PNG\r\n\032\n"),
152 MagicTransform("PNM", 0, "P1"),
153 MagicTransform("PNM", 0, "P2"),
154 MagicTransform("PNM", 0, "P3"),
155 MagicTransform("PNM", 0, "P4"),
156 MagicTransform("PNM", 0, "P5"),
157 MagicTransform("PNM", 0, "P6"),
158 MagicTransform("PNM", 0, "P7"),
159 MagicTransform("PNM", 0, "PF"),
160 MagicTransform("PNM", 0, "Pf"),
161 MagicTransform("PS", 0, "%!"),
162 MagicTransform("PS", 0, "\004%!"),
163 MagicTransform("PS", 0, "\305\320\323\306"),
164 MagicTransform("PSD", 0, "8BPS"),
165 MagicTransform("PWP", 0, "SFW95"),
166 MagicTransform("RAF", 0, "FUJIFILMCCD-RAW "),
167 MagicTransform("RAD", 0, "#?RADIANCE"),
168 MagicTransform("RAD", 0, "VIEW= "),
169 MagicTransform("RLE", 0, "\122\314"),
170 MagicTransform("SCT", 0, "CT"),
171 MagicTransform("SFW", 0, "SFW94"),
172 MagicTransform("SGI", 0, "\001\332"),
173 MagicTransform("SUN", 0, "\131\246\152\225"),
174 MagicTransform("SVG", 1, "?XML"),
175 MagicTransform("SVG", 1, "?xml"),
176 MagicTransform("TIFF", 0, "\115\115\000\052"),
177 MagicTransform("TIFF", 0, "\111\111\052\000"),
178 MagicTransform("TIFF64", 0, "\115\115\000\053\000\010\000\000"),
179 MagicTransform("TIFF64", 0, "\111\111\053\000\010\000\000\000"),
180 MagicTransform("TXT", 0, "# ImageMagick pixel enumeration:"),
181 MagicTransform("VICAR", 0, "LBLSIZE"),
182 MagicTransform("VICAR", 0, "NJPL1I"),
183 MagicTransform("VIFF", 0, "\253\001"),
184 MagicTransform("WMF", 0, "\327\315\306\232"),
185 MagicTransform("WMF", 0, "\001\000\011\000"),
186 MagicTransform("WPG", 0, "\377WPC"),
187 MagicTransform("XBM", 0, "#define"),
188 MagicTransform("XCF", 0, "gimp xcf"),
189 MagicTransform("XEF", 0, "FOVb"),
190 MagicTransform("XPM", 1, "* XPM *"),
191 MagicTransform("XWD", 4, "\007\000\000"),
192 MagicTransform("XWD", 5, "\000\000\007"),
193 MagicTransform((const char *) NULL, 0, (const char *) NULL)
194 };
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% %
217+ D e s t r o y M a g i c L i s t %
218% %
219% %
220% %
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222%
223% DestroyMagicList() deallocates memory associated with the magic list.
224%
225% The format of the DestroyMagicList method is:
226%
227% DestroyMagicList(void)
228%
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
252MagickExport void DestroyMagicList(void)
253{
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%
353% o number_aliases: This integer returns the number of aliases in the
354% list.
355%
356% o exception: return any errors or warnings in this structure.
357%
358*/
359
360#if defined(__cplusplus) || defined(c_plusplus)
361extern "C" {
362#endif
363
364static int MagicInfoCompare(const void *x,const void *y)
365{
366 const MagicInfo
367 **p,
368 **q;
369
370 p=(const MagicInfo **) x,
371 q=(const MagicInfo **) y;
372 if (LocaleCompare((*p)->path,(*q)->path) == 0)
373 return(LocaleCompare((*p)->name,(*q)->name));
374 return(LocaleCompare((*p)->path,(*q)->path));
375}
376
377#if defined(__cplusplus) || defined(c_plusplus)
378}
379#endif
380
381MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
382 unsigned long *number_aliases,ExceptionInfo *exception)
383{
384 const MagicInfo
385 **aliases;
386
387 register const MagicInfo
388 *p;
389
390 register long
391 i;
392
393 /*
394 Allocate magic list.
395 */
396 assert(pattern != (char *) NULL);
397 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
398 assert(number_aliases != (unsigned long *) NULL);
399 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000400 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000401 if (p == (const MagicInfo *) NULL)
402 return((const MagicInfo **) NULL);
403 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
404 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
405 if (aliases == (const MagicInfo **) NULL)
406 return((const MagicInfo **) NULL);
407 /*
408 Generate magic list.
409 */
410 AcquireSemaphoreInfo(&magic_semaphore);
411 ResetLinkedListIterator(magic_list);
412 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
413 for (i=0; p != (const MagicInfo *) NULL; )
414 {
415 if ((p->stealth == MagickFalse) &&
416 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
417 aliases[i++]=p;
418 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
419 }
420 RelinquishSemaphoreInfo(magic_semaphore);
421 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
422 aliases[i]=(MagicInfo *) NULL;
423 *number_aliases=(unsigned long) i;
424 return(aliases);
425}
426
427/*
428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429% %
430% %
431% %
432% G e t M a g i c L i s t %
433% %
434% %
435% %
436%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437%
438% GetMagicList() returns any image format aliases that match the specified
439% pattern.
440%
441% The format of the GetMagicList function is:
442%
443% char **GetMagicList(const char *pattern,unsigned long *number_aliases,
444% ExceptionInfo *exception)
445%
446% A description of each parameter follows:
447%
448% o pattern: Specifies a pointer to a text string containing a pattern.
449%
450% o number_aliases: This integer returns the number of image format aliases
451% in the list.
452%
453% o exception: return any errors or warnings in this structure.
454%
455*/
456
457#if defined(__cplusplus) || defined(c_plusplus)
458extern "C" {
459#endif
460
461static int MagicCompare(const void *x,const void *y)
462{
463 register const char
464 *p,
465 *q;
466
467 p=(const char *) x;
468 q=(const char *) y;
469 return(LocaleCompare(p,q));
470}
471
472#if defined(__cplusplus) || defined(c_plusplus)
473}
474#endif
475
476MagickExport char **GetMagicList(const char *pattern,
477 unsigned long *number_aliases,ExceptionInfo *exception)
478{
479 char
480 **aliases;
481
482 register const MagicInfo
483 *p;
484
485 register long
486 i;
487
488 /*
489 Allocate configure list.
490 */
491 assert(pattern != (char *) NULL);
492 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
493 assert(number_aliases != (unsigned long *) NULL);
494 *number_aliases=0;
cristy1ca3eb32009-10-15 18:41:54 +0000495 p=GetMagicInfo((const unsigned char *) NULL,0,exception);
cristy3ed852e2009-09-05 21:47:34 +0000496 if (p == (const MagicInfo *) NULL)
497 return((char **) NULL);
498 aliases=(char **) AcquireQuantumMemory((size_t)
499 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
500 if (aliases == (char **) NULL)
501 return((char **) NULL);
502 AcquireSemaphoreInfo(&magic_semaphore);
503 ResetLinkedListIterator(magic_list);
504 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
505 for (i=0; p != (const MagicInfo *) NULL; )
506 {
507 if ((p->stealth == MagickFalse) &&
508 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
509 aliases[i++]=ConstantString(p->name);
510 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
511 }
512 RelinquishSemaphoreInfo(magic_semaphore);
513 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
514 aliases[i]=(char *) NULL;
515 *number_aliases=(unsigned long) i;
516 return(aliases);
517}
518
519/*
520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521% %
522% %
523% %
524% G e t M a g i c N a m e %
525% %
526% %
527% %
528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
529%
530% GetMagicName() returns the name associated with the magic.
531%
532% The format of the GetMagicName method is:
533%
534% const char *GetMagicName(const MagicInfo *magic_info)
535%
536% A description of each parameter follows:
537%
538% o magic_info: The magic info.
539%
540*/
541MagickExport const char *GetMagicName(const MagicInfo *magic_info)
542{
543 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
544 assert(magic_info != (MagicInfo *) NULL);
545 assert(magic_info->signature == MagickSignature);
546 return(magic_info->name);
547}
548
549/*
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551% %
552% %
553% %
554+ I n i t i a l i z e M a g i c L i s t %
555% %
556% %
557% %
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559%
560% InitializeMagicList() initializes the magic list.
561%
562% The format of the InitializeMagicList method is:
563%
564% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
565%
566% A description of each parameter follows.
567%
568% o exception: return any errors or warnings in this structure.
569%
570*/
571static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
572{
573 if ((magic_list == (LinkedListInfo *) NULL) &&
574 (instantiate_magic == MagickFalse))
575 {
576 AcquireSemaphoreInfo(&magic_semaphore);
577 if ((magic_list == (LinkedListInfo *) NULL) &&
578 (instantiate_magic == MagickFalse))
579 {
580 (void) LoadMagicLists(MagicFilename,exception);
581 instantiate_magic=MagickTrue;
582 }
583 RelinquishSemaphoreInfo(magic_semaphore);
584 }
585 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
586}
587
588/*
589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590% %
591% %
592% %
593% L i s t M a g i c I n f o %
594% %
595% %
596% %
597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598%
599% ListMagicInfo() lists the magic info to a file.
600%
601% The format of the ListMagicInfo method is:
602%
603% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
604%
605% A description of each parameter follows.
606%
607% o file: An pointer to a FILE.
608%
609% o exception: return any errors or warnings in this structure.
610%
611*/
612MagickExport MagickBooleanType ListMagicInfo(FILE *file,
613 ExceptionInfo *exception)
614{
615 const char
616 *path;
617
618 const MagicInfo
619 **magic_info;
620
621 long
622 j;
623
624 register long
625 i;
626
627 unsigned long
628 number_aliases;
629
630 if (file == (const FILE *) NULL)
631 file=stdout;
632 magic_info=GetMagicInfoList("*",&number_aliases,exception);
633 if (magic_info == (const MagicInfo **) NULL)
634 return(MagickFalse);
635 j=0;
636 path=(const char *) NULL;
637 for (i=0; i < (long) number_aliases; i++)
638 {
639 if (magic_info[i]->stealth != MagickFalse)
640 continue;
641 if ((path == (const char *) NULL) ||
642 (LocaleCompare(path,magic_info[i]->path) != 0))
643 {
644 if (magic_info[i]->path != (char *) NULL)
645 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
646 (void) fprintf(file,"Name Offset Target\n");
647 (void) fprintf(file,"-------------------------------------------------"
648 "------------------------------\n");
649 }
650 path=magic_info[i]->path;
651 (void) fprintf(file,"%s",magic_info[i]->name);
652 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
653 (void) fprintf(file," ");
654 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
655 if (magic_info[i]->target != (char *) NULL)
cristy1ca3eb32009-10-15 18:41:54 +0000656 {
657 register long
658 j;
659
660 for (j=0; magic_info[i]->target[j] != '\0'; j++)
661 if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
662 (void) fprintf(file,"%c",magic_info[i]->target[j]);
663 else
cristy50931922009-10-15 18:59:59 +0000664 (void) fprintf(file,"\\%03o",(unsigned int)
665 ((unsigned char) magic_info[i]->target[j]));
cristy1ca3eb32009-10-15 18:41:54 +0000666 }
cristy3ed852e2009-09-05 21:47:34 +0000667 (void) fprintf(file,"\n");
668 }
669 (void) fflush(file);
670 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
671 return(MagickTrue);
672}
673
674/*
675%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676% %
677% %
678% %
679+ L o a d M a g i c L i s t %
680% %
681% %
682% %
683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684%
685% LoadMagicList() loads the magic configuration file which provides a mapping
686% between magic attributes and a magic name.
687%
688% The format of the LoadMagicList method is:
689%
690% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
691% const unsigned long depth,ExceptionInfo *exception)
692%
693% A description of each parameter follows:
694%
cristy1ca3eb32009-10-15 18:41:54 +0000695% o xml: The magic list in XML format.
cristy3ed852e2009-09-05 21:47:34 +0000696%
cristy1ca3eb32009-10-15 18:41:54 +0000697% o filename: The magic list filename.
cristy3ed852e2009-09-05 21:47:34 +0000698%
699% o depth: depth of <include /> statements.
700%
701% o exception: return any errors or warnings in this structure.
702%
703*/
704static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
705 const unsigned long depth,ExceptionInfo *exception)
706{
707 char
708 keyword[MaxTextExtent],
709 *token;
710
711 const char
712 *q;
713
714 MagickBooleanType
715 status;
716
717 MagicInfo
718 *magic_info;
719
720 /*
721 Load the magic map file.
722 */
723 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
724 "Loading magic configure file \"%s\" ...",filename);
725 if (xml == (char *) NULL)
726 return(MagickFalse);
727 if (magic_list == (LinkedListInfo *) NULL)
728 magic_list=NewLinkedList(0);
729 status=MagickTrue;
730 magic_info=(MagicInfo *) NULL;
731 token=AcquireString(xml);
732 for (q=(char *) xml; *q != '\0'; )
733 {
734 /*
735 Interpret XML.
736 */
737 GetMagickToken(q,&q,token);
738 if (*token == '\0')
739 break;
740 (void) CopyMagickString(keyword,token,MaxTextExtent);
741 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
742 {
743 /*
744 Doctype element.
745 */
746 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
747 GetMagickToken(q,&q,token);
748 continue;
749 }
750 if (LocaleNCompare(keyword,"<!--",4) == 0)
751 {
752 /*
753 Comment element.
754 */
755 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
756 GetMagickToken(q,&q,token);
757 continue;
758 }
759 if (LocaleCompare(keyword,"<include") == 0)
760 {
761 /*
762 Include element.
763 */
764 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
765 {
766 (void) CopyMagickString(keyword,token,MaxTextExtent);
767 GetMagickToken(q,&q,token);
768 if (*token != '=')
769 continue;
770 GetMagickToken(q,&q,token);
771 if (LocaleCompare(keyword,"file") == 0)
772 {
773 if (depth > 200)
774 (void) ThrowMagickException(exception,GetMagickModule(),
775 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
776 else
777 {
778 char
779 path[MaxTextExtent],
780 *xml;
781
782 GetPathComponent(filename,HeadPath,path);
783 if (*path != '\0')
784 (void) ConcatenateMagickString(path,DirectorySeparator,
785 MaxTextExtent);
786 if (*token == *DirectorySeparator)
787 (void) CopyMagickString(path,token,MaxTextExtent);
788 else
789 (void) ConcatenateMagickString(path,token,MaxTextExtent);
790 xml=FileToString(path,~0,exception);
791 if (xml != (char *) NULL)
792 {
793 status=LoadMagicList(xml,path,depth+1,exception);
794 xml=(char *) RelinquishMagickMemory(xml);
795 }
796 }
797 }
798 }
799 continue;
800 }
801 if (LocaleCompare(keyword,"<magic") == 0)
802 {
803 /*
804 Magic element.
805 */
806 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
807 if (magic_info == (MagicInfo *) NULL)
808 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
809 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
810 magic_info->path=ConstantString(filename);
811 magic_info->signature=MagickSignature;
812 continue;
813 }
814 if (magic_info == (MagicInfo *) NULL)
815 continue;
816 if (LocaleCompare(keyword,"/>") == 0)
817 {
818 status=AppendValueToLinkedList(magic_list,magic_info);
819 if (status == MagickFalse)
820 (void) ThrowMagickException(exception,GetMagickModule(),
821 ResourceLimitError,"MemoryAllocationFailed","`%s'",
822 magic_info->name);
823 magic_info=(MagicInfo *) NULL;
824 }
825 GetMagickToken(q,(const char **) NULL,token);
826 if (*token != '=')
827 continue;
828 GetMagickToken(q,&q,token);
829 GetMagickToken(q,&q,token);
830 switch (*keyword)
831 {
832 case 'N':
833 case 'n':
834 {
835 if (LocaleCompare((char *) keyword,"name") == 0)
836 {
837 magic_info->name=ConstantString(token);
838 break;
839 }
840 break;
841 }
842 case 'O':
843 case 'o':
844 {
845 if (LocaleCompare((char *) keyword,"offset") == 0)
846 {
847 magic_info->offset=(MagickOffsetType) atol(token);
848 break;
849 }
850 break;
851 }
852 case 'S':
853 case 's':
854 {
855 if (LocaleCompare((char *) keyword,"stealth") == 0)
856 {
857 magic_info->stealth=IsMagickTrue(token);
858 break;
859 }
860 break;
861 }
862 case 'T':
863 case 't':
864 {
865 if (LocaleCompare((char *) keyword,"target") == 0)
866 {
867 char
868 *p;
869
870 register unsigned char
871 *q;
872
873 size_t
874 length;
875
876 length=strlen(token);
877 magic_info->target=ConstantString(token);
878 magic_info->magic=(unsigned char *) ConstantString(token);
879 q=magic_info->magic;
880 for (p=magic_info->target; *p != '\0'; )
881 {
882 if (*p == '\\')
883 {
884 p++;
885 if (isdigit((int) ((unsigned char) *p)) != 0)
886 {
887 char
888 *end;
889
890 *q++=(unsigned char) strtol(p,&end,8);
891 p+=(end-p);
892 magic_info->length++;
893 continue;
894 }
895 switch (*p)
896 {
897 case 'b': *q='\b'; break;
898 case 'f': *q='\f'; break;
899 case 'n': *q='\n'; break;
900 case 'r': *q='\r'; break;
901 case 't': *q='\t'; break;
902 case 'v': *q='\v'; break;
903 case 'a': *q='a'; break;
904 case '?': *q='\?'; break;
905 default: *q=(unsigned char) (*p); break;
906 }
907 p++;
908 q++;
909 magic_info->length++;
910 continue;
911 }
912 else
913 if (LocaleNCompare(p,"&amp;",5) == 0)
914 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
915 *q++=(unsigned char) (*p++);
916 magic_info->length++;
917 }
918 break;
919 }
920 break;
921 }
922 default:
923 break;
924 }
925 }
926 token=(char *) RelinquishMagickMemory(token);
927 return(status);
928}
929
930/*
931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932% %
933% %
934% %
935% L o a d M a g i c L i s t s %
936% %
937% %
938% %
939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940%
941% LoadMagicLists() loads one or more magic configuration file which provides a
942% mapping between magic attributes and a magic name.
943%
944% The format of the LoadMagicLists method is:
945%
946% MagickBooleanType LoadMagicLists(const char *filename,
947% ExceptionInfo *exception)
948%
949% A description of each parameter follows:
950%
951% o filename: the font file name.
952%
953% o exception: return any errors or warnings in this structure.
954%
955*/
956static MagickBooleanType LoadMagicLists(const char *filename,
957 ExceptionInfo *exception)
958{
959#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
960 return(LoadMagicList(MagicMap,"built-in",0,exception));
961#else
962 char
963 path[MaxTextExtent];
964
965 const StringInfo
966 *option;
967
968 LinkedListInfo
969 *options;
970
971 MagickStatusType
972 status;
973
cristy1ca3eb32009-10-15 18:41:54 +0000974 register const MagicMapInfo
975 *p;
976
977 /*
978 Load built-in magic map.
979 */
cristy3ed852e2009-09-05 21:47:34 +0000980 status=MagickFalse;
cristy1ca3eb32009-10-15 18:41:54 +0000981 if (magic_list == (LinkedListInfo *) NULL)
982 magic_list=NewLinkedList(0);
983 for (p=MagicMap; p->name != (const char *) NULL; p++)
984 {
985 MagicInfo
986 *magic_info;
987
988 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
989 if (magic_info == (MagicInfo *) NULL)
990 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
991 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
992 magic_info->path="[built-in]";
993 magic_info->name=(char *) p->name;
994 magic_info->offset=p->offset;
995 magic_info->target=(char *) p->magic;
996 magic_info->magic=p->magic;
997 magic_info->length=p->length;
998 magic_info->exempt=MagickTrue;
999 magic_info->signature=MagickSignature;
1000 status=AppendValueToLinkedList(magic_list,magic_info);
1001 if (status == MagickFalse)
1002 (void) ThrowMagickException(exception,GetMagickModule(),
1003 ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
1004 }
1005 /*
1006 Load external magic map.
1007 */
cristy3ed852e2009-09-05 21:47:34 +00001008 *path='\0';
1009 options=GetConfigureOptions(filename,exception);
1010 option=(const StringInfo *) GetNextValueInLinkedList(options);
1011 while (option != (const StringInfo *) NULL)
1012 {
1013 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
1014 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
1015 GetStringInfoPath(option),0,exception);
1016 option=(const StringInfo *) GetNextValueInLinkedList(options);
1017 }
1018 options=DestroyConfigureOptions(options);
cristy3ed852e2009-09-05 21:47:34 +00001019 return(status != 0 ? MagickTrue : MagickFalse);
1020#endif
1021}