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