]> granicus.if.org Git - imagemagick/blob - MagickCore/magic.c
sigmoidal-contrast: prevent argument out of range and remove unnecessary ClampToQuantum
[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-2012 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     { "BMP", 0, MagickString("PI") },
100     { "CALS", 21, MagickString("version: MIL-STD-1840") },
101     { "CALS", 0, MagickString("srcdocid:") },
102     { "CALS", 9, MagickString("srcdocid:") },
103     { "CALS", 8, MagickString("rorient:") },
104     { "CGM", 0, MagickString("BEGMF") },
105     { "CIN", 0, MagickString("\200\052\137\327") },
106     { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
107     { "DCM", 128, MagickString("DICM") },
108     { "DCX", 0, MagickString("\261\150\336\72") },
109     { "DIB", 0, MagickString("\050\000") },
110     { "DDS", 0, MagickString("DDS ") },
111     { "DJVU", 0, MagickString("AT&TFORM") },
112     { "DOT", 0, MagickString("digraph") },
113     { "DPX", 0, MagickString("SDPX") },
114     { "DPX", 0, MagickString("XPDS") },
115     { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
116     { "EPT", 0, MagickString("\305\320\323\306") },
117     { "EXR", 0, MagickString("\166\057\061\001") },
118     { "FAX", 0, MagickString("DFAX") },
119     { "FIG", 0, MagickString("#FIG") },
120     { "FITS", 0, MagickString("IT0") },
121     { "FITS", 0, MagickString("SIMPLE") },
122     { "FPX", 0, MagickString("\320\317\021\340") },
123     { "GIF", 0, MagickString("GIF8") },
124     { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
125     { "HDF", 1, MagickString("HDF") },
126     { "HDR", 0, MagickString("#?RADIANCE") },
127     { "HDR", 0, MagickString("#?RGBE") },
128     { "HPGL", 0, MagickString("IN;") },
129     { "HTML", 1, MagickString("HTML") },
130     { "HTML", 1, MagickString("html") },
131     { "ILBM", 8, MagickString("ILBM") },
132     { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
133     { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
134     { "IPTC", 0, MagickString("\034\002") },
135     { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
136     { "JPEG", 0, MagickString("\377\330\377") },
137     { "JPC", 0, MagickString("\377\117") },
138     { "JP2", 4, MagickString("\152\120\040\040\015") },
139     { "MAT", 0, MagickString("MATLAB 5.0 MAT-file,") },
140     { "MIFF", 0, MagickString("Id=ImageMagick") },
141     { "MIFF", 0, MagickString("id=ImageMagick") },
142     { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
143     { "MPC", 0, MagickString("id=MagickCache") },
144     { "MPEG", 0, MagickString("\000\000\001\263") },
145     { "MRW", 0, MagickString("\x00MRM") },
146     { "MVG", 0, MagickString("push graphic-context") },
147     { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
148     { "PCD", 2048, MagickString("PCD_") },
149     { "PCL", 0, MagickString("\033E\033") },
150     { "PCX", 0, MagickString("\012\002") },
151     { "PCX", 0, MagickString("\012\005") },
152     { "PDB", 60, MagickString("vIMGView") },
153     { "PDF", 0, MagickString("%PDF-") },
154     { "PES", 0, MagickString("#PES") },
155     { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
156     { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
157     { "PGX", 0, MagickString("\050\107\020\115\046") },
158     { "PICT", 522, MagickString("\000\021\002\377\014\000") },
159     { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
160     { "PBM", 0, MagickString("P1") },
161     { "PGM", 0, MagickString("P2") },
162     { "PPM", 0, MagickString("P3") },
163     { "PBM", 0, MagickString("P4") },
164     { "PGM", 0, MagickString("P5") },
165     { "PPM", 0, MagickString("P6") },
166     { "PAM", 0, MagickString("P7") },
167     { "PFM", 0, MagickString("PF") },
168     { "PFM", 0, MagickString("Pf") },
169     { "PS", 0, MagickString("%!") },
170     { "PS", 0, MagickString("\004%!") },
171     { "PS", 0, MagickString("\305\320\323\306") },
172     { "PSB", 0, MagickString("8BPB") },
173     { "PSD", 0, MagickString("8BPS") },
174     { "PWP", 0, MagickString("SFW95") },
175     { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
176     { "RLE", 0, MagickString("\122\314") },
177     { "SCT", 0, MagickString("CT") },
178     { "SFW", 0, MagickString("SFW94") },
179     { "SGI", 0, MagickString("\001\332") },
180     { "SUN", 0, MagickString("\131\246\152\225") },
181     { "SVG", 1, MagickString("?XML") },
182     { "SVG", 1, MagickString("?xml") },
183     { "TIFF", 0, MagickString("\115\115\000\052") },
184     { "TIFF", 0, MagickString("\111\111\052\000") },
185     { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
186     { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
187     { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
188     { "VICAR", 0, MagickString("LBLSIZE") },
189     { "VICAR", 0, MagickString("NJPL1I") },
190     { "VIFF", 0, MagickString("\253\001") },
191     { "WEBP", 8, MagickString("WEBP") },
192     { "WMF", 0, MagickString("\327\315\306\232") },
193     { "WMF", 0, MagickString("\001\000\011\000") },
194     { "WPG", 0, MagickString("\377WPC") },
195     { "XBM", 0, MagickString("#define") },
196     { "XCF", 0, MagickString("gimp xcf") },
197     { "XEF", 0, MagickString("FOVb") },
198     { "XPM", 1, MagickString("* XPM *") },
199     { "XWD", 4, MagickString("\007\000\000") },
200     { "XWD", 5, MagickString("\000\000\007") }
201  };
202
203 static LinkedListInfo
204   *magic_list = (LinkedListInfo *) NULL;
205
206 static SemaphoreInfo
207   *magic_semaphore = (SemaphoreInfo *) NULL;
208
209 static volatile MagickBooleanType
210   instantiate_magic = MagickFalse;
211 \f
212 /*
213   Forward declarations.
214 */
215 static MagickBooleanType
216   InitializeMagicList(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 ((magic_list == (LinkedListInfo *) NULL) ||
256       (instantiate_magic == MagickFalse))
257     if (InitializeMagicList(exception) == MagickFalse)
258       return((const MagicInfo *) NULL);
259   if ((magic_list == (LinkedListInfo *) NULL) ||
260       (IsLinkedListEmpty(magic_list) != MagickFalse))
261     return((const MagicInfo *) NULL);
262   if (magic == (const unsigned char *) NULL)
263     return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
264   if (length == 0)
265     return((const MagicInfo *) NULL);
266   /*
267     Search for magic tag.
268   */
269   LockSemaphoreInfo(magic_semaphore);
270   ResetLinkedListIterator(magic_list);
271   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
272   while (p != (const MagicInfo *) NULL)
273   {
274     assert(p->offset >= 0);
275     if (((size_t) (p->offset+p->length) <= length) &&
276         (memcmp(magic+p->offset,p->magic,p->length) == 0))
277       break;
278     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
279   }
280   if (p != (const MagicInfo *) NULL)
281     (void) InsertValueInLinkedList(magic_list,0,
282       RemoveElementByValueFromLinkedList(magic_list,p));
283   UnlockSemaphoreInfo(magic_semaphore);
284   return(p);
285 }
286 \f
287 /*
288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
289 %                                                                             %
290 %                                                                             %
291 %                                                                             %
292 %   G e t M a g i c I n f o L i s t                                           %
293 %                                                                             %
294 %                                                                             %
295 %                                                                             %
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 %
298 %  GetMagicInfoList() returns any image aliases that match the specified
299 %  pattern.
300 %
301 %  The magic of the GetMagicInfoList function is:
302 %
303 %      const MagicInfo **GetMagicInfoList(const char *pattern,
304 %        size_t *number_aliases,ExceptionInfo *exception)
305 %
306 %  A description of each parameter follows:
307 %
308 %    o pattern: Specifies a pointer to a text string containing a pattern.
309 %
310 %    o number_aliases:  This integer returns the number of aliases in the list.
311 %
312 %    o exception: return any errors or warnings in this structure.
313 %
314 */
315
316 #if defined(__cplusplus) || defined(c_plusplus)
317 extern "C" {
318 #endif
319
320 static int MagicInfoCompare(const void *x,const void *y)
321 {
322   const MagicInfo
323     **p,
324     **q;
325
326   p=(const MagicInfo **) x,
327   q=(const MagicInfo **) y;
328   if (LocaleCompare((*p)->path,(*q)->path) == 0)
329     return(LocaleCompare((*p)->name,(*q)->name));
330   return(LocaleCompare((*p)->path,(*q)->path));
331 }
332
333 #if defined(__cplusplus) || defined(c_plusplus)
334 }
335 #endif
336
337 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
338   size_t *number_aliases,ExceptionInfo *exception)
339 {
340   const MagicInfo
341     **aliases;
342
343   register const MagicInfo
344     *p;
345
346   register ssize_t
347     i;
348
349   /*
350     Allocate magic list.
351   */
352   assert(pattern != (char *) NULL);
353   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
354   assert(number_aliases != (size_t *) NULL);
355   *number_aliases=0;
356   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
357   if (p == (const MagicInfo *) NULL)
358     return((const MagicInfo **) NULL);
359   aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
360     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
361   if (aliases == (const MagicInfo **) NULL)
362     return((const MagicInfo **) NULL);
363   /*
364     Generate magic list.
365   */
366   LockSemaphoreInfo(magic_semaphore);
367   ResetLinkedListIterator(magic_list);
368   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
369   for (i=0; p != (const MagicInfo *) NULL; )
370   {
371     if ((p->stealth == MagickFalse) &&
372         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
373       aliases[i++]=p;
374     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
375   }
376   UnlockSemaphoreInfo(magic_semaphore);
377   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
378   aliases[i]=(MagicInfo *) NULL;
379   *number_aliases=(size_t) i;
380   return(aliases);
381 }
382 \f
383 /*
384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 %                                                                             %
386 %                                                                             %
387 %                                                                             %
388 %   G e t M a g i c L i s t                                                   %
389 %                                                                             %
390 %                                                                             %
391 %                                                                             %
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 %
394 %  GetMagicList() returns any image format aliases that match the specified
395 %  pattern.
396 %
397 %  The format of the GetMagicList function is:
398 %
399 %      char **GetMagicList(const char *pattern,size_t *number_aliases,
400 %        ExceptionInfo *exception)
401 %
402 %  A description of each parameter follows:
403 %
404 %    o pattern: Specifies a pointer to a text string containing a pattern.
405 %
406 %    o number_aliases:  This integer returns the number of image format aliases
407 %      in the list.
408 %
409 %    o exception: return any errors or warnings in this structure.
410 %
411 */
412
413 #if defined(__cplusplus) || defined(c_plusplus)
414 extern "C" {
415 #endif
416
417 static int MagicCompare(const void *x,const void *y)
418 {
419   register const char
420     *p,
421     *q;
422
423   p=(const char *) x;
424   q=(const char *) y;
425   return(LocaleCompare(p,q));
426 }
427
428 #if defined(__cplusplus) || defined(c_plusplus)
429 }
430 #endif
431
432 MagickExport char **GetMagicList(const char *pattern,
433   size_t *number_aliases,ExceptionInfo *exception)
434 {
435   char
436     **aliases;
437
438   register const MagicInfo
439     *p;
440
441   register ssize_t
442     i;
443
444   /*
445     Allocate configure list.
446   */
447   assert(pattern != (char *) NULL);
448   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
449   assert(number_aliases != (size_t *) NULL);
450   *number_aliases=0;
451   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
452   if (p == (const MagicInfo *) NULL)
453     return((char **) NULL);
454   aliases=(char **) AcquireQuantumMemory((size_t)
455     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
456   if (aliases == (char **) NULL)
457     return((char **) NULL);
458   LockSemaphoreInfo(magic_semaphore);
459   ResetLinkedListIterator(magic_list);
460   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
461   for (i=0; p != (const MagicInfo *) NULL; )
462   {
463     if ((p->stealth == MagickFalse) &&
464         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
465       aliases[i++]=ConstantString(p->name);
466     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
467   }
468   UnlockSemaphoreInfo(magic_semaphore);
469   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
470   aliases[i]=(char *) NULL;
471   *number_aliases=(size_t) i;
472   return(aliases);
473 }
474 \f
475 /*
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
477 %                                                                             %
478 %                                                                             %
479 %                                                                             %
480 %   G e t M a g i c N a m e                                                   %
481 %                                                                             %
482 %                                                                             %
483 %                                                                             %
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
485 %
486 %  GetMagicName() returns the name associated with the magic.
487 %
488 %  The format of the GetMagicName method is:
489 %
490 %      const char *GetMagicName(const MagicInfo *magic_info)
491 %
492 %  A description of each parameter follows:
493 %
494 %    o magic_info:  The magic info.
495 %
496 */
497 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
498 {
499   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
500   assert(magic_info != (MagicInfo *) NULL);
501   assert(magic_info->signature == MagickSignature);
502   return(magic_info->name);
503 }
504 \f
505 /*
506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
507 %                                                                             %
508 %                                                                             %
509 %                                                                             %
510 +   I n i t i a l i z e M a g i c L i s t                                     %
511 %                                                                             %
512 %                                                                             %
513 %                                                                             %
514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
515 %
516 %  InitializeMagicList() initializes the magic list.
517 %
518 %  The format of the InitializeMagicList method is:
519 %
520 %      MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
521 %
522 %  A description of each parameter follows.
523 %
524 %    o exception: return any errors or warnings in this structure.
525 %
526 */
527 static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
528 {
529   if ((magic_list == (LinkedListInfo *) NULL) &&
530       (instantiate_magic == MagickFalse))
531     {
532       if (magic_semaphore == (SemaphoreInfo *) NULL)
533         AcquireSemaphoreInfo(&magic_semaphore);
534       LockSemaphoreInfo(magic_semaphore);
535       if ((magic_list == (LinkedListInfo *) NULL) &&
536           (instantiate_magic == MagickFalse))
537         {
538           (void) LoadMagicLists(MagicFilename,exception);
539           instantiate_magic=MagickTrue;
540         }
541       UnlockSemaphoreInfo(magic_semaphore);
542     }
543   return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
544 }
545 \f
546 /*
547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
548 %                                                                             %
549 %                                                                             %
550 %                                                                             %
551 %  L i s t M a g i c I n f o                                                  %
552 %                                                                             %
553 %                                                                             %
554 %                                                                             %
555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 %
557 %  ListMagicInfo() lists the magic info to a file.
558 %
559 %  The format of the ListMagicInfo method is:
560 %
561 %      MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
562 %
563 %  A description of each parameter follows.
564 %
565 %    o file:  An pointer to a FILE.
566 %
567 %    o exception: return any errors or warnings in this structure.
568 %
569 */
570 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
571   ExceptionInfo *exception)
572 {
573   const char
574     *path;
575
576   const MagicInfo
577     **magic_info;
578
579   register ssize_t
580     i;
581
582   size_t
583     number_aliases;
584
585   ssize_t
586     j;
587
588   if (file == (const FILE *) NULL)
589     file=stdout;
590   magic_info=GetMagicInfoList("*",&number_aliases,exception);
591   if (magic_info == (const MagicInfo **) NULL)
592     return(MagickFalse);
593   j=0;
594   path=(const char *) NULL;
595   for (i=0; i < (ssize_t) number_aliases; i++)
596   {
597     if (magic_info[i]->stealth != MagickFalse)
598       continue;
599     if ((path == (const char *) NULL) ||
600         (LocaleCompare(path,magic_info[i]->path) != 0))
601       {
602         if (magic_info[i]->path != (char *) NULL)
603           (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
604         (void) FormatLocaleFile(file,"Name      Offset Target\n");
605         (void) FormatLocaleFile(file,
606           "-------------------------------------------------"
607           "------------------------------\n");
608       }
609     path=magic_info[i]->path;
610     (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
611     for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
612       (void) FormatLocaleFile(file," ");
613     (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
614     if (magic_info[i]->target != (char *) NULL)
615       {
616         register ssize_t
617           j;
618
619         for (j=0; magic_info[i]->target[j] != '\0'; j++)
620           if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
621             (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
622           else
623             (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
624               ((unsigned char) magic_info[i]->target[j]));
625       }
626     (void) FormatLocaleFile(file,"\n");
627   }
628   (void) fflush(file);
629   magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
630   return(MagickTrue);
631 }
632 \f
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 size_t 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 */
663 static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
664   const size_t 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     {
688       magic_list=NewLinkedList(0);
689       if (magic_list == (LinkedListInfo *) NULL)
690         {
691           ThrowFileException(exception,ResourceLimitError,
692             "MemoryAllocationFailed",filename);
693           return(MagickFalse);
694         }
695     }
696   status=MagickTrue;
697   magic_info=(MagicInfo *) NULL;
698   token=AcquireString(xml);
699   for (q=(char *) xml; *q != '\0'; )
700   {
701     /*
702       Interpret XML.
703     */
704     GetMagickToken(q,&q,token);
705     if (*token == '\0')
706       break;
707     (void) CopyMagickString(keyword,token,MaxTextExtent);
708     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
709       {
710         /*
711           Doctype element.
712         */
713         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
714           GetMagickToken(q,&q,token);
715         continue;
716       }
717     if (LocaleNCompare(keyword,"<!--",4) == 0)
718       {
719         /*
720           Comment element.
721         */
722         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
723           GetMagickToken(q,&q,token);
724         continue;
725       }
726     if (LocaleCompare(keyword,"<include") == 0)
727       {
728         /*
729           Include element.
730         */
731         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
732         {
733           (void) CopyMagickString(keyword,token,MaxTextExtent);
734           GetMagickToken(q,&q,token);
735           if (*token != '=')
736             continue;
737           GetMagickToken(q,&q,token);
738           if (LocaleCompare(keyword,"file") == 0)
739             {
740               if (depth > 200)
741                 (void) ThrowMagickException(exception,GetMagickModule(),
742                   ConfigureError,"IncludeElementNestedTooDeeply","'%s'",token);
743               else
744                 {
745                   char
746                     path[MaxTextExtent],
747                     *xml;
748
749                   GetPathComponent(filename,HeadPath,path);
750                   if (*path != '\0')
751                     (void) ConcatenateMagickString(path,DirectorySeparator,
752                       MaxTextExtent);
753                   if (*token == *DirectorySeparator)
754                     (void) CopyMagickString(path,token,MaxTextExtent);
755                   else
756                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
757                   xml=FileToString(path,~0,exception);
758                   if (xml != (char *) NULL)
759                     {
760                       status=LoadMagicList(xml,path,depth+1,exception);
761                       xml=(char *) RelinquishMagickMemory(xml);
762                     }
763                 }
764             }
765         }
766         continue;
767       }
768     if (LocaleCompare(keyword,"<magic") == 0)
769       {
770         /*
771           Magic element.
772         */
773         magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
774         if (magic_info == (MagicInfo *) NULL)
775           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
776         (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
777         magic_info->path=ConstantString(filename);
778         magic_info->exempt=MagickFalse;
779         magic_info->signature=MagickSignature;
780         continue;
781       }
782     if (magic_info == (MagicInfo *) NULL)
783       continue;
784     if (LocaleCompare(keyword,"/>") == 0)
785       {
786         status=AppendValueToLinkedList(magic_list,magic_info);
787         if (status == MagickFalse)
788           (void) ThrowMagickException(exception,GetMagickModule(),
789             ResourceLimitError,"MemoryAllocationFailed","'%s'",
790             magic_info->name);
791         magic_info=(MagicInfo *) NULL;
792       }
793     GetMagickToken(q,(const char **) NULL,token);
794     if (*token != '=')
795       continue;
796     GetMagickToken(q,&q,token);
797     GetMagickToken(q,&q,token);
798     switch (*keyword)
799     {
800       case 'N':
801       case 'n':
802       {
803         if (LocaleCompare((char *) keyword,"name") == 0)
804           {
805             magic_info->name=ConstantString(token);
806             break;
807           }
808         break;
809       }
810       case 'O':
811       case 'o':
812       {
813         if (LocaleCompare((char *) keyword,"offset") == 0)
814           {
815             magic_info->offset=(MagickOffsetType) StringToLong(token);
816             break;
817           }
818         break;
819       }
820       case 'S':
821       case 's':
822       {
823         if (LocaleCompare((char *) keyword,"stealth") == 0)
824           {
825             magic_info->stealth=IsStringTrue(token);
826             break;
827           }
828         break;
829       }
830       case 'T':
831       case 't':
832       {
833         if (LocaleCompare((char *) keyword,"target") == 0)
834           {
835             char
836               *p;
837
838             register unsigned char
839               *q;
840
841             size_t
842               length;
843
844             length=strlen(token);
845             magic_info->target=ConstantString(token);
846             magic_info->magic=(unsigned char *) ConstantString(token);
847             q=magic_info->magic;
848             for (p=magic_info->target; *p != '\0'; )
849             {
850               if (*p == '\\')
851                 {
852                   p++;
853                   if (isdigit((int) ((unsigned char) *p)) != 0)
854                     {
855                       char
856                         *end;
857
858                       *q++=(unsigned char) strtol(p,&end,8);
859                       p+=(end-p);
860                       magic_info->length++;
861                       continue;
862                     }
863                   switch (*p)
864                   {
865                     case 'b': *q='\b'; break;
866                     case 'f': *q='\f'; break;
867                     case 'n': *q='\n'; break;
868                     case 'r': *q='\r'; break;
869                     case 't': *q='\t'; break;
870                     case 'v': *q='\v'; break;
871                     case 'a': *q='a'; break;
872                     case '?': *q='\?'; break;
873                     default: *q=(unsigned char) (*p); break;
874                   }
875                   p++;
876                   q++;
877                   magic_info->length++;
878                   continue;
879                 }
880               else
881                 if (LocaleNCompare(p,"&amp;",5) == 0)
882                   (void) CopyMagickString(p+1,p+5,length-magic_info->length);
883               *q++=(unsigned char) (*p++);
884               magic_info->length++;
885             }
886             break;
887           }
888         break;
889       }
890       default:
891         break;
892     }
893   }
894   token=(char *) RelinquishMagickMemory(token);
895   return(status);
896 }
897 \f
898 /*
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900 %                                                                             %
901 %                                                                             %
902 %                                                                             %
903 %  L o a d M a g i c L i s t s                                                %
904 %                                                                             %
905 %                                                                             %
906 %                                                                             %
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 %
909 %  LoadMagicLists() loads one or more magic configuration file which provides a
910 %  mapping between magic attributes and a magic name.
911 %
912 %  The format of the LoadMagicLists method is:
913 %
914 %      MagickBooleanType LoadMagicLists(const char *filename,
915 %        ExceptionInfo *exception)
916 %
917 %  A description of each parameter follows:
918 %
919 %    o filename: the font file name.
920 %
921 %    o exception: return any errors or warnings in this structure.
922 %
923 */
924 static MagickBooleanType LoadMagicLists(const char *filename,
925   ExceptionInfo *exception)
926 {
927   char
928     path[MaxTextExtent];
929
930   const StringInfo
931     *option;
932
933   LinkedListInfo
934     *options;
935
936   MagickStatusType
937     status;
938
939   register ssize_t
940     i;
941
942   /*
943     Load built-in magic map.
944   */
945   status=MagickFalse;
946   if (magic_list == (LinkedListInfo *) NULL)
947     {
948       magic_list=NewLinkedList(0);
949       if (magic_list == (LinkedListInfo *) NULL)
950         {
951           ThrowFileException(exception,ResourceLimitError,
952             "MemoryAllocationFailed",filename);
953           return(MagickFalse);
954         }
955     }
956   for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
957   {
958     MagicInfo
959       *magic_info;
960
961     register const MagicMapInfo
962       *p;
963
964     p=MagicMap+i;
965     magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
966     if (magic_info == (MagicInfo *) NULL)
967       {
968         (void) ThrowMagickException(exception,GetMagickModule(),
969           ResourceLimitError,"MemoryAllocationFailed","'%s'",magic_info->name);
970         continue;
971       }
972     (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
973     magic_info->path=(char *) "[built-in]";
974     magic_info->name=(char *) p->name;
975     magic_info->offset=p->offset;
976     magic_info->target=(char *) p->magic;
977     magic_info->magic=(unsigned char *) p->magic;
978     magic_info->length=p->length;
979     magic_info->exempt=MagickTrue;
980     magic_info->signature=MagickSignature;
981     status=AppendValueToLinkedList(magic_list,magic_info);
982     if (status == MagickFalse)
983       (void) ThrowMagickException(exception,GetMagickModule(),
984         ResourceLimitError,"MemoryAllocationFailed","'%s'",magic_info->name);
985   }
986   /*
987     Load external magic map.
988   */
989   *path='\0';
990   options=GetConfigureOptions(filename,exception);
991   option=(const StringInfo *) GetNextValueInLinkedList(options);
992   while (option != (const StringInfo *) NULL)
993   {
994     (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
995     status|=LoadMagicList((const char *) GetStringInfoDatum(option),
996       GetStringInfoPath(option),0,exception);
997     option=(const StringInfo *) GetNextValueInLinkedList(options);
998   }
999   options=DestroyConfigureOptions(options);
1000   return(status != 0 ? MagickTrue : MagickFalse);
1001 }
1002 \f
1003 /*
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 %                                                                             %
1006 %                                                                             %
1007 %                                                                             %
1008 +   M a g i c C o m p o n e n t G e n e s i s                                 %
1009 %                                                                             %
1010 %                                                                             %
1011 %                                                                             %
1012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013 %
1014 %  MagicComponentGenesis() instantiates the magic component.
1015 %
1016 %  The format of the MagicComponentGenesis method is:
1017 %
1018 %      MagickBooleanType MagicComponentGenesis(void)
1019 %
1020 */
1021 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
1022 {
1023   AcquireSemaphoreInfo(&magic_semaphore);
1024   return(MagickTrue);
1025 }
1026 \f
1027 /*
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 %                                                                             %
1030 %                                                                             %
1031 %                                                                             %
1032 +   M a g i c C o m p o n e n t T e r m i n u s                               %
1033 %                                                                             %
1034 %                                                                             %
1035 %                                                                             %
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 %
1038 %  MagicComponentTerminus() destroys the magic component.
1039 %
1040 %  The format of the MagicComponentTerminus method is:
1041 %
1042 %      MagicComponentTerminus(void)
1043 %
1044 */
1045
1046 static void *DestroyMagicElement(void *magic_info)
1047 {
1048   register MagicInfo
1049     *p;
1050
1051   p=(MagicInfo *) magic_info;
1052   if (p->exempt == MagickFalse)
1053     {
1054       if (p->path != (char *) NULL)
1055         p->path=DestroyString(p->path);
1056       if (p->name != (char *) NULL)
1057         p->name=DestroyString(p->name);
1058       if (p->target != (char *) NULL)
1059         p->target=DestroyString(p->target);
1060       if (p->magic != (unsigned char *) NULL)
1061         p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1062     }
1063   p=(MagicInfo *) RelinquishMagickMemory(p);
1064   return((void *) NULL);
1065 }
1066
1067 MagickPrivate void MagicComponentTerminus(void)
1068 {
1069   if (magic_semaphore == (SemaphoreInfo *) NULL)
1070     AcquireSemaphoreInfo(&magic_semaphore);
1071   LockSemaphoreInfo(magic_semaphore);
1072   if (magic_list != (LinkedListInfo *) NULL)
1073     magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
1074   instantiate_magic=MagickFalse;
1075   UnlockSemaphoreInfo(magic_semaphore);
1076   DestroySemaphoreInfo(&magic_semaphore);
1077 }