blob: 271a05577b0b3eac05f6490e977fd46741f71a80 [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*/
64static const char
65 *MagicMap = (const char *)
66 "<?xml version=\"1.0\"?>"
67 "<magicmap>"
68 " <magic name=\"AVI\" offset=\"0\" target=\"RIFF\" />"
69 " <magic name=\"8BIMWTEXT\" offset=\"0\" target=\"8\\000B\\000I\\000M\\000#\" />"
70 " <magic name=\"8BIMTEXT\" offset=\"0\" target=\"8BIM#\" />"
71 " <magic name=\"8BIM\" offset=\"0\" target=\"8BIM\" />"
72 " <magic name=\"BMP\" offset=\"0\" target=\"BA\" />"
73 " <magic name=\"BMP\" offset=\"0\" target=\"BM\" />"
74 " <magic name=\"BMP\" offset=\"0\" target=\"CI\" />"
75 " <magic name=\"BMP\" offset=\"0\" target=\"CP\" />"
76 " <magic name=\"BMP\" offset=\"0\" target=\"IC\" />"
77 " <magic name=\"BMP\" offset=\"0\" target=\"PI\" />"
78 " <magic name=\"CIN\" offset=\"0\" target=\"\\200\\052\\137\\327\" />"
79 " <magic name=\"CGM\" offset=\"0\" target=\"BEGMF\" />"
80 " <magic name=\"DCM\" offset=\"128\" target=\"DICM\" />"
81 " <magic name=\"DCX\" offset=\"0\" target=\"\\261\\150\\336\\72\" />"
82 " <magic name=\"DDS\" offset=\"0\" target=\"DDS \" />"
83 " <magic name=\"DIB\" offset=\"0\" target=\"\\050\\000\" />"
84 " <magic name=\"DJVU\" offset=\"0\" target=\"AT&TFORM\" />"
85 " <magic name=\"DOT\" offset=\"0\" target=\"digraph\" />"
86 " <magic name=\"DPX\" offset=\"0\" target=\"SDPX\" />"
87 " <magic name=\"DPX\" offset=\"0\" target=\"XPDS\" />"
88 " <magic name=\"EMF\" offset=\"40\" target=\"\\040\\105\\115\\106\\000\\000\\001\\000\" />"
89 " <magic name=\"EPT\" offset=\"0\" target=\"\\305\\320\\323\\306\" />"
90 " <magic name=\"EXR\" offset=\"0\" target=\"\\166\\057\\061\\001\" />"
91 " <magic name=\"FAX\" offset=\"0\" target=\"DFAX\" />"
92 " <magic name=\"FIG\" offset=\"0\" target=\"#FIG\" />"
93 " <magic name=\"FITS\" offset=\"0\" target=\"IT0\" />"
94 " <magic name=\"FITS\" offset=\"0\" target=\"SIMPLE\" />"
95 " <magic name=\"FPX\" offset=\"0\" target=\"\\320\\317\\021\\340\" />"
96 " <magic name=\"GIF\" offset=\"0\" target=\"GIF8\" />"
97 " <magic name=\"GPLT\" offset=\"0\" target=\"#!/usr/local/bin/gnuplot\" />"
98 " <magic name=\"HDF\" offset=\"1\" target=\"HDF\" />"
99 " <magic name=\"HPGL\" offset=\"0\" target=\"IN;\" />"
100 " <magic name=\"HTML\" offset=\"1\" target=\"HTML\" />"
101 " <magic name=\"HTML\" offset=\"1\" target=\"html\" />"
102 " <magic name=\"ILBM\" offset=\"8\" target=\"ILBM\" />"
103 " <magic name=\"IPTCWTEXT\" offset=\"0\" target=\"\\062\\000#\\000\\060\\000=\\000\\042\\000&\\000#\\000\\060\\000;\\000&\\000#\\000\\062\\000;\\000\\042\\000\" />"
104 " <magic name=\"IPTCTEXT\" offset=\"0\" target=\"2#0=\\042&#0;&#2;\\042\" />"
105 " <magic name=\"IPTC\" offset=\"0\" target=\"\\034\\002\" />"
106 " <magic name=\"JNG\" offset=\"0\" target=\"\\213JNG\\r\\n\\032\\n\" />"
107 " <magic name=\"JPEG\" offset=\"0\" target=\"\\377\\330\\377\" />"
108 " <magic name=\"JPC\" offset=\"0\" target=\"\\377\\117\" />"
109 " <magic name=\"JP2\" offset=\"4\" target=\"\\152\\120\\040\\040\\015\" />"
110 " <magic name=\"MIFF\" offset=\"0\" target=\"Id=ImageMagick\" />"
111 " <magic name=\"MIFF\" offset=\"0\" target=\"id=ImageMagick\" />"
112 " <magic name=\"MNG\" offset=\"0\" target=\"\\212MNG\\r\\n\\032\\n\" />"
113 " <magic name=\"MPC\" offset=\"0\" target=\"id=MagickCache\" />"
114 " <magic name=\"MPEG\" offset=\"0\" target=\"\\000\\000\\001\\263\" />"
115 " <magic name=\"MVG\" offset=\"0\" target=\"push graphic-context\" />"
116 " <magic name=\"PCD\" offset=\"2048\" target=\"PCD_\" />"
117 " <magic name=\"PCL\" offset=\"0\" target=\"\\033E\\033\" />"
118 " <magic name=\"PCX\" offset=\"0\" target=\"\\012\\002\" />"
119 " <magic name=\"PCX\" offset=\"0\" target=\"\\012\\005\" />"
120 " <magic name=\"PDB\" offset=\"60\" target=\"vIMGView\" />"
121 " <magic name=\"PDF\" offset=\"0\" target=\"%PDF-\" />"
122 " <magic name=\"PFA\" offset=\"0\" target=\"%!PS-AdobeFont-1.0\" />"
123 " <magic name=\"PFB\" offset=\"6\" target=\"%!PS-AdobeFont-1.0\" />"
124 " <magic name=\"PGX\" offset=\"0\" target=\"\\050\\107\\020\\115\\046\" />"
125 " <magic name=\"PICT\" offset=\"522\" target=\"\\000\\021\\002\\377\\014\\000\" />"
126 " <magic name=\"PNG\" offset=\"0\" target=\"\\211PNG\\r\\n\\032\\n\" />"
127 " <magic name=\"PNM\" offset=\"0\" target=\"P1\" />"
128 " <magic name=\"PNM\" offset=\"0\" target=\"P2\" />"
129 " <magic name=\"PNM\" offset=\"0\" target=\"P3\" />"
130 " <magic name=\"PNM\" offset=\"0\" target=\"P4\" />"
131 " <magic name=\"PNM\" offset=\"0\" target=\"P5\" />"
132 " <magic name=\"PNM\" offset=\"0\" target=\"P6\" />"
133 " <magic name=\"PNM\" offset=\"0\" target=\"P7\" />"
134 " <magic name=\"PNM\" offset=\"0\" target=\"PF\" />"
135 " <magic name=\"PNM\" offset=\"0\" target=\"Pf\" />"
136 " <magic name=\"PS\" offset=\"0\" target=\"%!\" />"
137 " <magic name=\"PS\" offset=\"0\" target=\"\\004%!\" />"
138 " <magic name=\"PS\" offset=\"0\" target=\"\\305\\320\\323\\306\" />"
139 " <magic name=\"PSD\" offset=\"0\" target=\"8BPS\" />"
140 " <magic name=\"PWP\" offset=\"0\" target=\"SFW95\" />"
141 " <magic name=\"RAD\" offset=\"0\" target=\"#?RADIANCE\" />"
142 " <magic name=\"RAD\" offset=\"0\" target=\"VIEW= \" />"
143 " <magic name=\"RLE\" offset=\"0\" target=\"\\122\\314\" />"
144 " <magic name=\"SCT\" offset=\"0\" target=\"CT\" />"
145 " <magic name=\"SFW\" offset=\"0\" target=\"SFW94\" />"
146 " <magic name=\"SGI\" offset=\"0\" target=\"\\001\\332\" />"
147 " <magic name=\"SUN\" offset=\"0\" target=\"\\131\\246\\152\\225\" />"
148 " <magic name=\"SVG\" offset=\"1\" target=\"?XML\" />"
149 " <magic name=\"SVG\" offset=\"1\" target=\"?xml\" />"
150 " <magic name=\"TXT\" offset=\"0\" target=\"# ImageMagick pixel enumeration:\" />"
151 " <magic name=\"TIFF\" offset=\"0\" target=\"\\115\\115\\000\\052\" />"
152 " <magic name=\"TIFF\" offset=\"0\" target=\"\\111\\111\\052\\000\" />"
153 " <magic name=\"TIFF64\" offset=\"0\" target=\"\\115\\115\\000\\053\\000\\010\\000\\000\" />"
154 " <magic name=\"TIFF64\" offset=\"0\" target=\"\\115\\115\\000\\053\\000\\010\\000\\000\" />"
155 " <magic name=\"VICAR\" offset=\"0\" target=\"LBLSIZE\" />"
156 " <magic name=\"VICAR\" offset=\"0\" target=\"NJPL1I\" />"
157 " <magic name=\"VIFF\" offset=\"0\" target=\"\\253\\001\" />"
158 " <magic name=\"WMF\" offset=\"0\" target=\"\\327\\315\\306\\232\" />"
159 " <magic name=\"WMF\" offset=\"0\" target=\"\\001\\000\\011\\000\" />"
160 " <magic name=\"WPG\" offset=\"0\" target=\"\\377WPC\" />"
161 " <magic name=\"XBM\" offset=\"0\" target=\"#define\" />"
162 " <magic name=\"XCF\" offset=\"0\" target=\"gimp xcf\" />"
163 " <magic name=\"XPM\" offset=\"1\" target=\"* XPM *\" />"
164 " <magic name=\"XWD\" offset=\"4\" target=\"\\007\\000\\000\" />"
165 " <magic name=\"XWD\" offset=\"5\" target=\"\\000\\000\\007\" />"
166 "</magicmap>";
167
168static LinkedListInfo
169 *magic_list = (LinkedListInfo *) NULL;
170
171static SemaphoreInfo
172 *magic_semaphore = (SemaphoreInfo *) NULL;
173
174static volatile MagickBooleanType
175 instantiate_magic = MagickFalse;
176
177/*
178 Forward declarations.
179*/
180static MagickBooleanType
181 InitializeMagicList(ExceptionInfo *),
182 LoadMagicLists(const char *,ExceptionInfo *);
183
184/*
185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186% %
187% %
188% %
189+ D e s t r o y M a g i c L i s t %
190% %
191% %
192% %
193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194%
195% DestroyMagicList() deallocates memory associated with the magic list.
196%
197% The format of the DestroyMagicList method is:
198%
199% DestroyMagicList(void)
200%
201*/
202
203static void *DestroyMagicElement(void *magic_info)
204{
205 register MagicInfo
206 *p;
207
208 p=(MagicInfo *) magic_info;
209 if (p->path != (char *) NULL)
210 p->path=DestroyString(p->path);
211 if (p->name != (char *) NULL)
212 p->name=DestroyString(p->name);
213 if (p->target != (char *) NULL)
214 p->target=DestroyString(p->target);
215 if (p->magic != (unsigned char *) NULL)
216 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
217 p=(MagicInfo *) RelinquishMagickMemory(p);
218 return((void *) NULL);
219}
220
221MagickExport void DestroyMagicList(void)
222{
223 AcquireSemaphoreInfo(&magic_semaphore);
224 if (magic_list != (LinkedListInfo *) NULL)
225 magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
226 instantiate_magic=MagickFalse;
227 RelinquishSemaphoreInfo(magic_semaphore);
228 DestroySemaphoreInfo(&magic_semaphore);
229}
230
231/*
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233% %
234% %
235% %
236+ G e t M a g i c I n f o %
237% %
238% %
239% %
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%
242% GetMagicInfo() searches the magic list for the specified name and if found
243% returns attributes for that magic.
244%
245% The format of the GetMagicInfo method is:
246%
247% const MagicInfo *GetMagicInfo(const unsigned char *magic,
248% const size_t length,ExceptionInfo *exception)
249%
250% A description of each parameter follows:
251%
252% o magic: A binary string generally representing the first few characters
253% of the image file or blob.
254%
255% o length: the length of the binary signature.
256%
257% o exception: return any errors or warnings in this structure.
258%
259*/
260MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
261 const size_t length,ExceptionInfo *exception)
262{
263 register const MagicInfo
264 *p;
265
266 assert(exception != (ExceptionInfo *) NULL);
267 if ((magic_list == (LinkedListInfo *) NULL) ||
268 (instantiate_magic == MagickFalse))
269 if (InitializeMagicList(exception) == MagickFalse)
270 return((const MagicInfo *) NULL);
271 if ((magic_list == (LinkedListInfo *) NULL) ||
272 (IsLinkedListEmpty(magic_list) != MagickFalse))
273 return((const MagicInfo *) NULL);
274 if (magic == (const unsigned char *) NULL)
275 return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
276 if (length == 0)
277 return((const MagicInfo *) NULL);
278 /*
279 Search for magic tag.
280 */
281 AcquireSemaphoreInfo(&magic_semaphore);
282 ResetLinkedListIterator(magic_list);
283 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
284 while (p != (const MagicInfo *) NULL)
285 {
286 assert(p->offset >= 0);
287 if (((size_t) (p->offset+p->length) <= length) &&
288 (memcmp(magic+p->offset,p->magic,p->length) == 0))
289 break;
290 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
291 }
292 if (p != (const MagicInfo *) NULL)
293 (void) InsertValueInLinkedList(magic_list,0,
294 RemoveElementByValueFromLinkedList(magic_list,p));
295 RelinquishSemaphoreInfo(magic_semaphore);
296 return(p);
297}
298
299/*
300%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301% %
302% %
303% %
304% G e t M a g i c I n f o L i s t %
305% %
306% %
307% %
308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309%
310% GetMagicInfoList() returns any image aliases that match the specified
311% pattern.
312%
313% The magic of the GetMagicInfoList function is:
314%
315% const MagicInfo **GetMagicInfoList(const char *pattern,
316% unsigned long *number_aliases,ExceptionInfo *exception)
317%
318% A description of each parameter follows:
319%
320% o pattern: Specifies a pointer to a text string containing a pattern.
321%
322% o number_aliases: This integer returns the number of aliases in the
323% list.
324%
325% o exception: return any errors or warnings in this structure.
326%
327*/
328
329#if defined(__cplusplus) || defined(c_plusplus)
330extern "C" {
331#endif
332
333static int MagicInfoCompare(const void *x,const void *y)
334{
335 const MagicInfo
336 **p,
337 **q;
338
339 p=(const MagicInfo **) x,
340 q=(const MagicInfo **) y;
341 if (LocaleCompare((*p)->path,(*q)->path) == 0)
342 return(LocaleCompare((*p)->name,(*q)->name));
343 return(LocaleCompare((*p)->path,(*q)->path));
344}
345
346#if defined(__cplusplus) || defined(c_plusplus)
347}
348#endif
349
350MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
351 unsigned long *number_aliases,ExceptionInfo *exception)
352{
353 const MagicInfo
354 **aliases;
355
356 register const MagicInfo
357 *p;
358
359 register long
360 i;
361
362 /*
363 Allocate magic list.
364 */
365 assert(pattern != (char *) NULL);
366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
367 assert(number_aliases != (unsigned long *) NULL);
368 *number_aliases=0;
369 p=GetMagicInfo((const unsigned char *) "*",0,exception);
370 if (p == (const MagicInfo *) NULL)
371 return((const MagicInfo **) NULL);
372 aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
373 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
374 if (aliases == (const MagicInfo **) NULL)
375 return((const MagicInfo **) NULL);
376 /*
377 Generate magic list.
378 */
379 AcquireSemaphoreInfo(&magic_semaphore);
380 ResetLinkedListIterator(magic_list);
381 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
382 for (i=0; p != (const MagicInfo *) NULL; )
383 {
384 if ((p->stealth == MagickFalse) &&
385 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
386 aliases[i++]=p;
387 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
388 }
389 RelinquishSemaphoreInfo(magic_semaphore);
390 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
391 aliases[i]=(MagicInfo *) NULL;
392 *number_aliases=(unsigned long) i;
393 return(aliases);
394}
395
396/*
397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398% %
399% %
400% %
401% G e t M a g i c L i s t %
402% %
403% %
404% %
405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406%
407% GetMagicList() returns any image format aliases that match the specified
408% pattern.
409%
410% The format of the GetMagicList function is:
411%
412% char **GetMagicList(const char *pattern,unsigned long *number_aliases,
413% ExceptionInfo *exception)
414%
415% A description of each parameter follows:
416%
417% o pattern: Specifies a pointer to a text string containing a pattern.
418%
419% o number_aliases: This integer returns the number of image format aliases
420% in the list.
421%
422% o exception: return any errors or warnings in this structure.
423%
424*/
425
426#if defined(__cplusplus) || defined(c_plusplus)
427extern "C" {
428#endif
429
430static int MagicCompare(const void *x,const void *y)
431{
432 register const char
433 *p,
434 *q;
435
436 p=(const char *) x;
437 q=(const char *) y;
438 return(LocaleCompare(p,q));
439}
440
441#if defined(__cplusplus) || defined(c_plusplus)
442}
443#endif
444
445MagickExport char **GetMagicList(const char *pattern,
446 unsigned long *number_aliases,ExceptionInfo *exception)
447{
448 char
449 **aliases;
450
451 register const MagicInfo
452 *p;
453
454 register long
455 i;
456
457 /*
458 Allocate configure list.
459 */
460 assert(pattern != (char *) NULL);
461 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
462 assert(number_aliases != (unsigned long *) NULL);
463 *number_aliases=0;
464 p=GetMagicInfo((const unsigned char *) "*",0,exception);
465 if (p == (const MagicInfo *) NULL)
466 return((char **) NULL);
467 aliases=(char **) AcquireQuantumMemory((size_t)
468 GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
469 if (aliases == (char **) NULL)
470 return((char **) NULL);
471 AcquireSemaphoreInfo(&magic_semaphore);
472 ResetLinkedListIterator(magic_list);
473 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
474 for (i=0; p != (const MagicInfo *) NULL; )
475 {
476 if ((p->stealth == MagickFalse) &&
477 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
478 aliases[i++]=ConstantString(p->name);
479 p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
480 }
481 RelinquishSemaphoreInfo(magic_semaphore);
482 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
483 aliases[i]=(char *) NULL;
484 *number_aliases=(unsigned long) i;
485 return(aliases);
486}
487
488/*
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490% %
491% %
492% %
493% G e t M a g i c N a m e %
494% %
495% %
496% %
497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498%
499% GetMagicName() returns the name associated with the magic.
500%
501% The format of the GetMagicName method is:
502%
503% const char *GetMagicName(const MagicInfo *magic_info)
504%
505% A description of each parameter follows:
506%
507% o magic_info: The magic info.
508%
509*/
510MagickExport const char *GetMagicName(const MagicInfo *magic_info)
511{
512 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
513 assert(magic_info != (MagicInfo *) NULL);
514 assert(magic_info->signature == MagickSignature);
515 return(magic_info->name);
516}
517
518/*
519%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520% %
521% %
522% %
523+ I n i t i a l i z e M a g i c L i s t %
524% %
525% %
526% %
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528%
529% InitializeMagicList() initializes the magic list.
530%
531% The format of the InitializeMagicList method is:
532%
533% MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
534%
535% A description of each parameter follows.
536%
537% o exception: return any errors or warnings in this structure.
538%
539*/
540static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
541{
542 if ((magic_list == (LinkedListInfo *) NULL) &&
543 (instantiate_magic == MagickFalse))
544 {
545 AcquireSemaphoreInfo(&magic_semaphore);
546 if ((magic_list == (LinkedListInfo *) NULL) &&
547 (instantiate_magic == MagickFalse))
548 {
549 (void) LoadMagicLists(MagicFilename,exception);
550 instantiate_magic=MagickTrue;
551 }
552 RelinquishSemaphoreInfo(magic_semaphore);
553 }
554 return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
555}
556
557/*
558%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559% %
560% %
561% %
562% L i s t M a g i c I n f o %
563% %
564% %
565% %
566%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567%
568% ListMagicInfo() lists the magic info to a file.
569%
570% The format of the ListMagicInfo method is:
571%
572% MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
573%
574% A description of each parameter follows.
575%
576% o file: An pointer to a FILE.
577%
578% o exception: return any errors or warnings in this structure.
579%
580*/
581MagickExport MagickBooleanType ListMagicInfo(FILE *file,
582 ExceptionInfo *exception)
583{
584 const char
585 *path;
586
587 const MagicInfo
588 **magic_info;
589
590 long
591 j;
592
593 register long
594 i;
595
596 unsigned long
597 number_aliases;
598
599 if (file == (const FILE *) NULL)
600 file=stdout;
601 magic_info=GetMagicInfoList("*",&number_aliases,exception);
602 if (magic_info == (const MagicInfo **) NULL)
603 return(MagickFalse);
604 j=0;
605 path=(const char *) NULL;
606 for (i=0; i < (long) number_aliases; i++)
607 {
608 if (magic_info[i]->stealth != MagickFalse)
609 continue;
610 if ((path == (const char *) NULL) ||
611 (LocaleCompare(path,magic_info[i]->path) != 0))
612 {
613 if (magic_info[i]->path != (char *) NULL)
614 (void) fprintf(file,"\nPath: %s\n\n",magic_info[i]->path);
615 (void) fprintf(file,"Name Offset Target\n");
616 (void) fprintf(file,"-------------------------------------------------"
617 "------------------------------\n");
618 }
619 path=magic_info[i]->path;
620 (void) fprintf(file,"%s",magic_info[i]->name);
621 for (j=(long) strlen(magic_info[i]->name); j <= 9; j++)
622 (void) fprintf(file," ");
623 (void) fprintf(file,"%6ld ",(long) magic_info[i]->offset);
624 if (magic_info[i]->target != (char *) NULL)
625 (void) fprintf(file,"%s",magic_info[i]->target);
626 (void) fprintf(file,"\n");
627 }
628 (void) fflush(file);
629 magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
630 return(MagickTrue);
631}
632
633/*
634%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635% %
636% %
637% %
638+ L o a d M a g i c L i s t %
639% %
640% %
641% %
642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643%
644% LoadMagicList() loads the magic configuration file which provides a mapping
645% between magic attributes and a magic name.
646%
647% The format of the LoadMagicList method is:
648%
649% MagickBooleanType LoadMagicList(const char *xml,const char *filename,
650% const unsigned long depth,ExceptionInfo *exception)
651%
652% A description of each parameter follows:
653%
654% o xml: The magic list in XML format.
655%
656% o filename: The magic list filename.
657%
658% o depth: depth of <include /> statements.
659%
660% o exception: return any errors or warnings in this structure.
661%
662*/
663static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
664 const unsigned long depth,ExceptionInfo *exception)
665{
666 char
667 keyword[MaxTextExtent],
668 *token;
669
670 const char
671 *q;
672
673 MagickBooleanType
674 status;
675
676 MagicInfo
677 *magic_info;
678
679 /*
680 Load the magic map file.
681 */
682 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
683 "Loading magic configure file \"%s\" ...",filename);
684 if (xml == (char *) NULL)
685 return(MagickFalse);
686 if (magic_list == (LinkedListInfo *) NULL)
687 magic_list=NewLinkedList(0);
688 status=MagickTrue;
689 magic_info=(MagicInfo *) NULL;
690 token=AcquireString(xml);
691 for (q=(char *) xml; *q != '\0'; )
692 {
693 /*
694 Interpret XML.
695 */
696 GetMagickToken(q,&q,token);
697 if (*token == '\0')
698 break;
699 (void) CopyMagickString(keyword,token,MaxTextExtent);
700 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
701 {
702 /*
703 Doctype element.
704 */
705 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
706 GetMagickToken(q,&q,token);
707 continue;
708 }
709 if (LocaleNCompare(keyword,"<!--",4) == 0)
710 {
711 /*
712 Comment element.
713 */
714 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
715 GetMagickToken(q,&q,token);
716 continue;
717 }
718 if (LocaleCompare(keyword,"<include") == 0)
719 {
720 /*
721 Include element.
722 */
723 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
724 {
725 (void) CopyMagickString(keyword,token,MaxTextExtent);
726 GetMagickToken(q,&q,token);
727 if (*token != '=')
728 continue;
729 GetMagickToken(q,&q,token);
730 if (LocaleCompare(keyword,"file") == 0)
731 {
732 if (depth > 200)
733 (void) ThrowMagickException(exception,GetMagickModule(),
734 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
735 else
736 {
737 char
738 path[MaxTextExtent],
739 *xml;
740
741 GetPathComponent(filename,HeadPath,path);
742 if (*path != '\0')
743 (void) ConcatenateMagickString(path,DirectorySeparator,
744 MaxTextExtent);
745 if (*token == *DirectorySeparator)
746 (void) CopyMagickString(path,token,MaxTextExtent);
747 else
748 (void) ConcatenateMagickString(path,token,MaxTextExtent);
749 xml=FileToString(path,~0,exception);
750 if (xml != (char *) NULL)
751 {
752 status=LoadMagicList(xml,path,depth+1,exception);
753 xml=(char *) RelinquishMagickMemory(xml);
754 }
755 }
756 }
757 }
758 continue;
759 }
760 if (LocaleCompare(keyword,"<magic") == 0)
761 {
762 /*
763 Magic element.
764 */
765 magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
766 if (magic_info == (MagicInfo *) NULL)
767 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
768 (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
769 magic_info->path=ConstantString(filename);
770 magic_info->signature=MagickSignature;
771 continue;
772 }
773 if (magic_info == (MagicInfo *) NULL)
774 continue;
775 if (LocaleCompare(keyword,"/>") == 0)
776 {
777 status=AppendValueToLinkedList(magic_list,magic_info);
778 if (status == MagickFalse)
779 (void) ThrowMagickException(exception,GetMagickModule(),
780 ResourceLimitError,"MemoryAllocationFailed","`%s'",
781 magic_info->name);
782 magic_info=(MagicInfo *) NULL;
783 }
784 GetMagickToken(q,(const char **) NULL,token);
785 if (*token != '=')
786 continue;
787 GetMagickToken(q,&q,token);
788 GetMagickToken(q,&q,token);
789 switch (*keyword)
790 {
791 case 'N':
792 case 'n':
793 {
794 if (LocaleCompare((char *) keyword,"name") == 0)
795 {
796 magic_info->name=ConstantString(token);
797 break;
798 }
799 break;
800 }
801 case 'O':
802 case 'o':
803 {
804 if (LocaleCompare((char *) keyword,"offset") == 0)
805 {
806 magic_info->offset=(MagickOffsetType) atol(token);
807 break;
808 }
809 break;
810 }
811 case 'S':
812 case 's':
813 {
814 if (LocaleCompare((char *) keyword,"stealth") == 0)
815 {
816 magic_info->stealth=IsMagickTrue(token);
817 break;
818 }
819 break;
820 }
821 case 'T':
822 case 't':
823 {
824 if (LocaleCompare((char *) keyword,"target") == 0)
825 {
826 char
827 *p;
828
829 register unsigned char
830 *q;
831
832 size_t
833 length;
834
835 length=strlen(token);
836 magic_info->target=ConstantString(token);
837 magic_info->magic=(unsigned char *) ConstantString(token);
838 q=magic_info->magic;
839 for (p=magic_info->target; *p != '\0'; )
840 {
841 if (*p == '\\')
842 {
843 p++;
844 if (isdigit((int) ((unsigned char) *p)) != 0)
845 {
846 char
847 *end;
848
849 *q++=(unsigned char) strtol(p,&end,8);
850 p+=(end-p);
851 magic_info->length++;
852 continue;
853 }
854 switch (*p)
855 {
856 case 'b': *q='\b'; break;
857 case 'f': *q='\f'; break;
858 case 'n': *q='\n'; break;
859 case 'r': *q='\r'; break;
860 case 't': *q='\t'; break;
861 case 'v': *q='\v'; break;
862 case 'a': *q='a'; break;
863 case '?': *q='\?'; break;
864 default: *q=(unsigned char) (*p); break;
865 }
866 p++;
867 q++;
868 magic_info->length++;
869 continue;
870 }
871 else
872 if (LocaleNCompare(p,"&amp;",5) == 0)
873 (void) CopyMagickString(p+1,p+5,length-magic_info->length);
874 *q++=(unsigned char) (*p++);
875 magic_info->length++;
876 }
877 break;
878 }
879 break;
880 }
881 default:
882 break;
883 }
884 }
885 token=(char *) RelinquishMagickMemory(token);
886 return(status);
887}
888
889/*
890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891% %
892% %
893% %
894% L o a d M a g i c L i s t s %
895% %
896% %
897% %
898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899%
900% LoadMagicLists() loads one or more magic configuration file which provides a
901% mapping between magic attributes and a magic name.
902%
903% The format of the LoadMagicLists method is:
904%
905% MagickBooleanType LoadMagicLists(const char *filename,
906% ExceptionInfo *exception)
907%
908% A description of each parameter follows:
909%
910% o filename: the font file name.
911%
912% o exception: return any errors or warnings in this structure.
913%
914*/
915static MagickBooleanType LoadMagicLists(const char *filename,
916 ExceptionInfo *exception)
917{
918#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
919 return(LoadMagicList(MagicMap,"built-in",0,exception));
920#else
921 char
922 path[MaxTextExtent];
923
924 const StringInfo
925 *option;
926
927 LinkedListInfo
928 *options;
929
930 MagickStatusType
931 status;
932
933 status=MagickFalse;
934 *path='\0';
935 options=GetConfigureOptions(filename,exception);
936 option=(const StringInfo *) GetNextValueInLinkedList(options);
937 while (option != (const StringInfo *) NULL)
938 {
939 (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
940 status|=LoadMagicList((const char *) GetStringInfoDatum(option),
941 GetStringInfoPath(option),0,exception);
942 option=(const StringInfo *) GetNextValueInLinkedList(options);
943 }
944 options=DestroyConfigureOptions(options);
945 if ((magic_list == (LinkedListInfo *) NULL) ||
946 (IsLinkedListEmpty(magic_list) != MagickFalse))
947 {
948 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
949 "UnableToOpenConfigureFile","`%s'",path);
950 status|=LoadMagicList(MagicMap,"built-in",0,exception);
951 }
952 return(status != 0 ? MagickTrue : MagickFalse);
953#endif
954}