MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
mime.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % M M IIIII M M EEEEE %
6 % MM MM I MM MM E %
7 % M M M I M M M EEE %
8 % M M I M M E %
9 % M M IIIII M M EEEEE %
10 % %
11 % %
12 % MagickCore Mime Methods %
13 % %
14 % Software Design %
15 % July 2000 %
16 % %
17 % %
18 % Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
19 % dedicated to making software imaging solutions freely available. %
20 % %
21 % You may not use this file except in compliance with the License. You may %
22 % obtain a copy of the License at %
23 % %
24 % https://imagemagick.org/script/license.php %
25 % %
26 % Unless required by applicable law or agreed to in writing, software %
27 % distributed under the License is distributed on an "AS IS" BASIS, %
28 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
29 % See the License for the specific language governing permissions and %
30 % limitations under the License. %
31 % %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 %
34 %
35 */
36 
37 /*
38  Include declarations.
39 */
40 #include "MagickCore/studio.h"
41 #include "MagickCore/blob.h"
42 #include "MagickCore/client.h"
43 #include "MagickCore/configure.h"
44 #include "MagickCore/configure-private.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/linked-list.h"
48 #include "MagickCore/linked-list-private.h"
49 #include "MagickCore/memory_.h"
50 #include "MagickCore/mime.h"
51 #include "MagickCore/mime-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/semaphore.h"
54 #include "MagickCore/string_.h"
55 #include "MagickCore/token.h"
56 #include "MagickCore/utility.h"
57 #include "MagickCore/utility-private.h"
58 #include "MagickCore/xml-tree.h"
59 #include "MagickCore/xml-tree-private.h"
60 
61 /*
62  Define declarations.
63 */
64 #define MimeFilename "mime.xml"
65 
66 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
67 # if !defined(strcasecmp)
68 # define strcasecmp _stricmp
69 # endif
70 #endif
71 
72 /*
73  Typedef declaration.
74 */
75 struct _MimeInfo
76 {
77  char
78  *path,
79  *type,
80  *description,
81  *pattern;
82 
83  ssize_t
84  priority;
85 
86  MagickOffsetType
87  offset;
88 
89  size_t
90  extent;
91 
92  DataType
93  data_type;
94 
95  ssize_t
96  mask,
97  value;
98 
99  EndianType
100  endian;
101 
102  size_t
103  length;
104 
105  unsigned char
106  *magic;
107 
108  MagickBooleanType
109  stealth;
110 
111  size_t
112  signature;
113 };
114 
115 /*
116  Static declarations.
117 */
118 static LinkedListInfo
119  *mime_cache = (LinkedListInfo *) NULL;
120 
121 static SemaphoreInfo
122  *mime_semaphore = (SemaphoreInfo *) NULL;
123 
124 /*
125  Forward declarations.
126 */
127 static MagickBooleanType
128  IsMimeCacheInstantiated(ExceptionInfo *);
129 
130 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
131 static MagickBooleanType
132  LoadMimeCache(LinkedListInfo *,const char *,const char *,const size_t,
133  ExceptionInfo *);
134 #endif
135 
136 /*
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
138 % %
139 % %
140 % %
141 % A c q u i r e M i m e C a c h e %
142 % %
143 % %
144 % %
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 %
147 % AcquireMimeCache() caches one or more magic configurations which provides
148 % a mapping between magic attributes and a magic name.
149 %
150 % The format of the AcquireMimeCache method is:
151 %
152 % LinkedListInfo *AcquireMimeCache(const char *filename,
153 % ExceptionInfo *exception)
154 %
155 % A description of each parameter follows:
156 %
157 % o filename: the font file name.
158 %
159 % o exception: return any errors or warnings in this structure.
160 %
161 */
162 MagickExport LinkedListInfo *AcquireMimeCache(const char *filename,
163  ExceptionInfo *exception)
164 {
166  *cache;
167 
168  cache=NewLinkedList(0);
169 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
170  {
171  const StringInfo
172  *option;
173 
175  *options;
176 
177  options=GetConfigureOptions(filename,exception);
178  option=(const StringInfo *) GetNextValueInLinkedList(options);
179  while (option != (const StringInfo *) NULL)
180  {
181  (void) LoadMimeCache(cache,(const char *)
182  GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
183  option=(const StringInfo *) GetNextValueInLinkedList(options);
184  }
185  options=DestroyConfigureOptions(options);
186  }
187 #else
188  magick_unreferenced(filename);
189  magick_unreferenced(exception);
190 #endif
191  return(cache);
192 }
193 
194 /*
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % %
197 % %
198 % %
199 + G e t M i m e I n f o %
200 % %
201 % %
202 % %
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 %
205 % GetMimeInfo() attempts to classify the content to identify which mime type
206 % is associated with the content, if any.
207 %
208 % The format of the GetMimeInfo method is:
209 %
210 % const MimeInfo *GetMimeInfo(const char *filename,
211 % const unsigned char *magic,const size_t length,
212 % ExceptionInfo *exception)
213 %
214 % A description of each parameter follows:
215 %
216 % o filename: If we cannot not classify the string, we attempt to classify
217 % based on the filename (e.g. *.pdf returns application/pdf).
218 %
219 % o magic: A binary string generally representing the first few characters
220 % of the image file or blob.
221 %
222 % o length: the length of the binary signature.
223 %
224 % o exception: return any errors or warnings in this structure.
225 %
226 */
227 MagickExport const MimeInfo *GetMimeInfo(const char *filename,
228  const unsigned char *magic,const size_t length,ExceptionInfo *exception)
229 {
231  *element_info,
232  *p;
233 
234  EndianType
235  endian;
236 
237  const unsigned char
238  *r;
239 
240  ssize_t
241  i;
242 
243  ssize_t
244  value;
245 
246  unsigned long
247  lsb_first;
248 
249  assert(exception != (ExceptionInfo *) NULL);
250  if (IsMimeCacheInstantiated(exception) == MagickFalse)
251  return((const MimeInfo *) NULL);
252  /*
253  Search for mime tag.
254  */
255  lsb_first=1;
256  LockSemaphoreInfo(mime_semaphore);
257  p=GetHeadElementInLinkedList(mime_cache);
258  if ((magic == (const unsigned char *) NULL) || (length == 0))
259  {
260  UnlockSemaphoreInfo(mime_semaphore);
261  if (p != (ElementInfo *) NULL)
262  return((const MimeInfo *) p->value);
263  return((const MimeInfo *) NULL);
264  }
265  element_info=(ElementInfo *) NULL;
266  while (p != (ElementInfo *) NULL)
267  {
268  const MimeInfo
269  *q;
270 
271  q=(const MimeInfo *) p->value;
272  assert(q->offset >= 0);
273  if (element_info != (const ElementInfo *) NULL)
274  if (q->priority > ((const MimeInfo *) element_info->value)->priority)
275  {
276  p=p->next;
277  continue;
278  }
279  if ((q->pattern != (char *) NULL) && (filename != (char *) NULL))
280  {
281  if (GlobExpression(filename,q->pattern,MagickFalse) != MagickFalse)
282  element_info=p;
283  p=p->next;
284  continue;
285  }
286  switch (q->data_type)
287  {
288  case ByteData:
289  {
290  if ((size_t) (q->offset+4) > length)
291  break;
292  r=magic+q->offset;
293  value=(ssize_t) (*r++);
294  if (q->mask == 0)
295  {
296  if (q->value == value)
297  element_info=p;
298  }
299  else
300  {
301  if ((q->value & q->mask) == value)
302  element_info=p;
303  }
304  break;
305  }
306  case ShortData:
307  {
308  if ((size_t) (q->offset+4) > length)
309  break;
310  r=magic+q->offset;
311  endian=q->endian;
312  if (q->endian == UndefinedEndian)
313  endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
314  if (endian == LSBEndian)
315  {
316  value=(ssize_t) (*r++);
317  value|=(*r++) << 8;
318  }
319  else
320  {
321  value=(ssize_t) (*r++) << 8;
322  value|=(*r++);
323  }
324  if (q->mask == 0)
325  {
326  if (q->value == value)
327  element_info=p;
328  }
329  else
330  {
331  if ((q->value & q->mask) == value)
332  element_info=p;
333  }
334  break;
335  }
336  case LongData:
337  {
338  if ((size_t) (q->offset+4) > length)
339  break;
340  r=magic+q->offset;
341  endian=q->endian;
342  if (q->endian == UndefinedEndian)
343  endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
344  if (endian == LSBEndian)
345  {
346  value=(ssize_t) (*r++);
347  value|=((ssize_t) *r++) << 8;
348  value|=((ssize_t) *r++) << 16;
349  value|=((ssize_t) *r++) << 24;
350  }
351  else
352  {
353  value=(ssize_t) (*r++) << 24;
354  value|=((ssize_t) *r++) << 16;
355  value|=((ssize_t) *r++) << 8;
356  value|=((ssize_t) *r++);
357  }
358  if (q->mask == 0)
359  {
360  if (q->value == value)
361  element_info=p;
362  }
363  else
364  {
365  if ((q->value & q->mask) == value)
366  element_info=p;
367  }
368  break;
369  }
370  case StringData:
371  default:
372  {
373  for (i=0; i <= (ssize_t) q->extent; i++)
374  {
375  if ((size_t) (q->offset+i+(ssize_t) q->length) > length)
376  break;
377  if (memcmp(magic+q->offset+i,q->magic,q->length) == 0)
378  {
379  element_info=p;
380  break;
381  }
382  }
383  break;
384  }
385  }
386  p=p->next;
387  }
388  if (element_info != (ElementInfo *) NULL)
389  SetHeadElementInLinkedList(mime_cache,element_info);
390  UnlockSemaphoreInfo(mime_semaphore);
391  if (element_info == (ElementInfo *) NULL)
392  return((const MimeInfo *) NULL);
393  return((const MimeInfo *) element_info->value);
394 }
395 
396 /*
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % %
399 % %
400 % %
401 % G e t M i m e I n f o L i s t %
402 % %
403 % %
404 % %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 %
407 % GetMimeInfoList() returns any image aliases that match the specified
408 % pattern.
409 %
410 % The magic of the GetMimeInfoList function is:
411 %
412 % const MimeInfo **GetMimeInfoList(const char *pattern,
413 % size_t *number_aliases,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 magics in the
420 % list.
421 %
422 % o exception: return any errors or warnings in this structure.
423 %
424 */
425 
426 #if defined(__cplusplus) || defined(c_plusplus)
427 extern "C" {
428 #endif
429 
430 static int MimeInfoCompare(const void *x,const void *y)
431 {
432  const MimeInfo
433  **p,
434  **q;
435 
436  p=(const MimeInfo **) x,
437  q=(const MimeInfo **) y;
438  if (strcasecmp((*p)->path,(*q)->path) == 0)
439  return(strcasecmp((*p)->type,(*q)->type));
440  return(strcasecmp((*p)->path,(*q)->path));
441 }
442 
443 #if defined(__cplusplus) || defined(c_plusplus)
444 }
445 #endif
446 
447 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern,
448  size_t *number_aliases,ExceptionInfo *exception)
449 {
450  const MimeInfo
451  **aliases;
452 
454  *p;
455 
456  ssize_t
457  i;
458 
459  assert(pattern != (char *) NULL);
460  assert(number_aliases != (size_t *) NULL);
461  if (IsEventLogging() != MagickFalse)
462  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
463  *number_aliases=0;
464  if (IsMimeCacheInstantiated(exception) == MagickFalse)
465  return((const MimeInfo **) NULL);
466  aliases=(const MimeInfo **) AcquireQuantumMemory((size_t)
467  GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
468  if (aliases == (const MimeInfo **) NULL)
469  return((const MimeInfo **) NULL);
470  LockSemaphoreInfo(mime_semaphore);
471  p=GetHeadElementInLinkedList(mime_cache);
472  for (i=0; p != (ElementInfo *) NULL; )
473  {
474  MimeInfo
475  *mime_info;
476 
477  mime_info=(MimeInfo *) p->value;
478  if ((mime_info->stealth == MagickFalse) &&
479  (GlobExpression(mime_info->type,pattern,MagickFalse) != MagickFalse))
480  aliases[i++]=mime_info;
481  p=p->next;
482  }
483  UnlockSemaphoreInfo(mime_semaphore);
484  if (i == 0)
485  aliases=(const MimeInfo **) RelinquishMagickMemory((void *) aliases);
486  else
487  {
488  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare);
489  aliases[i]=(MimeInfo *) NULL;
490  }
491  *number_aliases=(size_t) i;
492  return(aliases);
493 }
494 
495 /*
496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497 % %
498 % %
499 % %
500 % G e t M i m e L i s t %
501 % %
502 % %
503 % %
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 %
506 % GetMimeList() returns any image format alias that matches the specified
507 % pattern.
508 %
509 % The format of the GetMimeList function is:
510 %
511 % char **GetMimeList(const char *pattern,size_t *number_aliases,
512 % ExceptionInfo *exception)
513 %
514 % A description of each parameter follows:
515 %
516 % o pattern: Specifies a pointer to a text string containing a pattern.
517 %
518 % o number_aliases: This integer returns the number of image format aliases
519 % in the list.
520 %
521 % o exception: return any errors or warnings in this structure.
522 %
523 */
524 
525 #if defined(__cplusplus) || defined(c_plusplus)
526 extern "C" {
527 #endif
528 
529 static int MimeCompare(const void *x,const void *y)
530 {
531  char
532  *p,
533  *q;
534 
535  p=(char *) x;
536  q=(char *) y;
537  return(strcasecmp(p,q));
538 }
539 
540 #if defined(__cplusplus) || defined(c_plusplus)
541 }
542 #endif
543 
544 MagickExport char **GetMimeList(const char *pattern,
545  size_t *number_aliases,ExceptionInfo *exception)
546 {
547  char
548  **aliases;
549 
551  *p;
552 
553  ssize_t
554  i;
555 
556  assert(pattern != (char *) NULL);
557  assert(number_aliases != (size_t *) NULL);
558  if (IsEventLogging() != MagickFalse)
559  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
560  *number_aliases=0;
561  if (IsMimeCacheInstantiated(exception) == MagickFalse)
562  return((char **) NULL);
563  aliases=(char **) AcquireQuantumMemory((size_t)
564  GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
565  if (aliases == (char **) NULL)
566  return((char **) NULL);
567  LockSemaphoreInfo(mime_semaphore);
568  p=GetHeadElementInLinkedList(mime_cache);
569  for (i=0; p != (ElementInfo *) NULL; )
570  {
571  const MimeInfo
572  *mime_info;
573 
574  mime_info=(const MimeInfo *) p->value;
575  if ((mime_info->stealth == MagickFalse) &&
576  (GlobExpression(mime_info->type,pattern,MagickFalse) != MagickFalse))
577  aliases[i++]=ConstantString(mime_info->type);
578  p=p->next;
579  }
580  UnlockSemaphoreInfo(mime_semaphore);
581  if (i == 0)
582  aliases=(char **) RelinquishMagickMemory(aliases);
583  else
584  {
585  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare);
586  aliases[i]=(char *) NULL;
587  }
588  *number_aliases=(size_t) i;
589  return(aliases);
590 }
591 
592 /*
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594 % %
595 % %
596 % %
597 % G e t M i m e D e s c r i p t i o n %
598 % %
599 % %
600 % %
601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602 %
603 % GetMimeDescription() returns the mime type description.
604 %
605 % The format of the GetMimeDescription method is:
606 %
607 % const char *GetMimeDescription(const MimeInfo *mime_info)
608 %
609 % A description of each parameter follows:
610 %
611 % o mime_info: The magic info.
612 %
613 */
614 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info)
615 {
616  assert(mime_info != (MimeInfo *) NULL);
617  assert(mime_info->signature == MagickCoreSignature);
618  if (IsEventLogging() != MagickFalse)
619  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
620  return(mime_info->description);
621 }
622 
623 /*
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 % %
626 % %
627 % %
628 % G e t M i m e T y p e %
629 % %
630 % %
631 % %
632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633 %
634 % GetMimeType() returns the mime type.
635 %
636 % The format of the GetMimeType method is:
637 %
638 % const char *GetMimeType(const MimeInfo *mime_info)
639 %
640 % A description of each parameter follows:
641 %
642 % o mime_info: The magic info.
643 %
644 */
645 MagickExport const char *GetMimeType(const MimeInfo *mime_info)
646 {
647  assert(mime_info != (MimeInfo *) NULL);
648  assert(mime_info->signature == MagickCoreSignature);
649  if (IsEventLogging() != MagickFalse)
650  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
651  return(mime_info->type);
652 }
653 
654 /*
655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 % %
657 % %
658 % %
659 + I s M i m e C a c h e I n s t a n t i a t e d %
660 % %
661 % %
662 % %
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 %
665 % IsMimeCacheInstantiated() determines if the mime list is instantiated. If
666 % not, it instantiates the list and returns it.
667 %
668 % The format of the IsMimeInstantiated method is:
669 %
670 % MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
671 %
672 % A description of each parameter follows.
673 %
674 % o exception: return any errors or warnings in this structure.
675 %
676 */
677 static MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
678 {
679  if (mime_cache == (LinkedListInfo *) NULL)
680  {
681  if (mime_semaphore == (SemaphoreInfo *) NULL)
682  ActivateSemaphoreInfo(&mime_semaphore);
683  LockSemaphoreInfo(mime_semaphore);
684  if (mime_cache == (LinkedListInfo *) NULL)
685  mime_cache=AcquireMimeCache(MimeFilename,exception);
686  UnlockSemaphoreInfo(mime_semaphore);
687  }
688  return(mime_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
689 }
690 
691 /*
692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 % %
694 % %
695 % %
696 % L i s t M i m e I n f o %
697 % %
698 % %
699 % %
700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701 %
702 % ListMimeInfo() lists the magic info to a file.
703 %
704 % The format of the ListMimeInfo method is:
705 %
706 % MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
707 %
708 % A description of each parameter follows.
709 %
710 % o file: An pointer to a FILE.
711 %
712 % o exception: return any errors or warnings in this structure.
713 %
714 */
715 MagickExport MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
716 {
717  const char
718  *path;
719 
720  const MimeInfo
721  **mime_info;
722 
723  ssize_t
724  i;
725 
726  size_t
727  number_aliases;
728 
729  ssize_t
730  j;
731 
732  if (file == (const FILE *) NULL)
733  file=stdout;
734  mime_info=GetMimeInfoList("*",&number_aliases,exception);
735  if (mime_info == (const MimeInfo **) NULL)
736  return(MagickFalse);
737  j=0;
738  path=(const char *) NULL;
739  for (i=0; i < (ssize_t) number_aliases; i++)
740  {
741  if (mime_info[i]->stealth != MagickFalse)
742  continue;
743  if ((path == (const char *) NULL) ||
744  (strcasecmp(path,mime_info[i]->path) != 0))
745  {
746  if (mime_info[i]->path != (char *) NULL)
747  (void) FormatLocaleFile(file,"\nPath: %s\n\n",mime_info[i]->path);
748  (void) FormatLocaleFile(file,"Type Description\n");
749  (void) FormatLocaleFile(file,
750  "-------------------------------------------------"
751  "------------------------------\n");
752  }
753  path=mime_info[i]->path;
754  (void) FormatLocaleFile(file,"%s",mime_info[i]->type);
755  if (strlen(mime_info[i]->type) <= 25)
756  {
757  for (j=(ssize_t) strlen(mime_info[i]->type); j <= 27; j++)
758  (void) FormatLocaleFile(file," ");
759  }
760  else
761  {
762  (void) FormatLocaleFile(file,"\n");
763  for (j=0; j <= 27; j++)
764  (void) FormatLocaleFile(file," ");
765  }
766  if (mime_info[i]->description != (char *) NULL)
767  (void) FormatLocaleFile(file,"%s",mime_info[i]->description);
768  (void) FormatLocaleFile(file,"\n");
769  }
770  (void) fflush(file);
771  mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info);
772  return(MagickTrue);
773 }
774 
775 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
776 /*
777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
778 % %
779 % %
780 % %
781 + L o a d M i m e C a c h e %
782 % %
783 % %
784 % %
785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786 %
787 % LoadMimeCache() loads the mime configurations which provides a mapping
788 % between mime attributes and a mime name.
789 %
790 % The format of the LoadMimeCache method is:
791 %
792 % MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
793 % const char *filename,const size_t depth,ExceptionInfo *exception)
794 %
795 % A description of each parameter follows:
796 %
797 % o xml: The mime list in XML format.
798 %
799 % o filename: The mime list filename.
800 %
801 % o depth: depth of <include /> statements.
802 %
803 % o exception: return any errors or warnings in this structure.
804 %
805 */
806 static MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
807  const char *filename,const size_t depth,ExceptionInfo *exception)
808 {
809  const char
810  *attribute;
811 
812  MimeInfo
813  *mime_info = (MimeInfo *) NULL;
814 
815  MagickStatusType
816  status;
817 
819  *mime,
820  *mime_map,
821  *include;
822 
823  /*
824  Load the mime map file.
825  */
826  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
827  "Loading mime map \"%s\" ...",filename);
828  if (xml == (const char *) NULL)
829  return(MagickFalse);
830  mime_map=NewXMLTree(xml,exception);
831  if (mime_map == (XMLTreeInfo *) NULL)
832  return(MagickFalse);
833  status=MagickTrue;
834  include=GetXMLTreeChild(mime_map,"include");
835  while (include != (XMLTreeInfo *) NULL)
836  {
837  /*
838  Process include element.
839  */
840  attribute=GetXMLTreeAttribute(include,"file");
841  if (attribute != (const char *) NULL)
842  {
843  if (depth > MagickMaxRecursionDepth)
844  (void) ThrowMagickException(exception,GetMagickModule(),
845  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",filename);
846  else
847  {
848  char
849  path[MagickPathExtent],
850  *file_xml;
851 
852  GetPathComponent(filename,HeadPath,path);
853  if (*path != '\0')
854  (void) ConcatenateMagickString(path,DirectorySeparator,
855  MagickPathExtent);
856  if (*attribute == *DirectorySeparator)
857  (void) CopyMagickString(path,attribute,MagickPathExtent);
858  else
859  (void) ConcatenateMagickString(path,attribute,MagickPathExtent);
860  file_xml=FileToXML(path,~0UL);
861  if (file_xml != (char *) NULL)
862  {
863  status&=(MagickStatusType) LoadMimeCache(cache,file_xml,path,
864  depth+1,exception);
865  file_xml=DestroyString(file_xml);
866  }
867  }
868  }
869  include=GetNextXMLTreeTag(include);
870  }
871  mime=GetXMLTreeChild(mime_map,"mime");
872  while (mime != (XMLTreeInfo *) NULL)
873  {
874  /*
875  Process mime element.
876  */
877  mime_info=(MimeInfo *) AcquireCriticalMemory(sizeof(*mime_info));
878  (void) memset(mime_info,0,sizeof(*mime_info));
879  mime_info->path=ConstantString(filename);
880  mime_info->signature=MagickCoreSignature;
881  attribute=GetXMLTreeAttribute(mime,"data-type");
882  if (attribute != (const char *) NULL)
883  mime_info->data_type=(DataType) ParseCommandOption(MagickDataTypeOptions,
884  MagickTrue,attribute);
885  attribute=GetXMLTreeAttribute(mime,"description");
886  if (attribute != (const char *) NULL)
887  mime_info->description=ConstantString(attribute);
888  attribute=GetXMLTreeAttribute(mime,"endian");
889  if (attribute != (const char *) NULL)
890  mime_info->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
891  MagickTrue,attribute);
892  attribute=GetXMLTreeAttribute(mime,"magic");
893  if (attribute != (const char *) NULL)
894  {
895  char
896  *token;
897 
898  const char
899  *p;
900 
901  unsigned char
902  *q;
903 
904  token=AcquireString(attribute);
905  (void) SubstituteString((char **) &token,"&lt;","<");
906  (void) SubstituteString((char **) &token,"&amp;","&");
907  (void) SubstituteString((char **) &token,"&quot;","\"");
908  (void) SubstituteString((char **) &token,"&apos;","'");
909  mime_info->magic=(unsigned char *) AcquireString(token);
910  q=mime_info->magic;
911  for (p=token; *p != '\0'; )
912  {
913  if (*p == '\\')
914  {
915  p++;
916  if (isdigit((int) ((unsigned char) *p)) != 0)
917  {
918  char
919  *end;
920 
921  *q++=(unsigned char) strtol(p,&end,8);
922  p+=(ptrdiff_t) (end-p);
923  mime_info->length++;
924  continue;
925  }
926  switch (*p)
927  {
928  case 'b': *q='\b'; break;
929  case 'f': *q='\f'; break;
930  case 'n': *q='\n'; break;
931  case 'r': *q='\r'; break;
932  case 't': *q='\t'; break;
933  case 'v': *q='\v'; break;
934  case 'a': *q='a'; break;
935  case '?': *q='\?'; break;
936  default: *q=(unsigned char) (*p); break;
937  }
938  p++;
939  q++;
940  mime_info->length++;
941  continue;
942  }
943  *q++=(unsigned char) (*p++);
944  mime_info->length++;
945  }
946  token=DestroyString(token);
947  if (mime_info->data_type != StringData)
948  mime_info->value=(ssize_t) strtoul((char *) mime_info->magic,
949  (char **) NULL,0);
950  }
951  attribute=GetXMLTreeAttribute(mime,"mask");
952  if (attribute != (const char *) NULL)
953  mime_info->mask=(ssize_t) strtoul(attribute,(char **) NULL,0);
954  attribute=GetXMLTreeAttribute(mime,"offset");
955  if (attribute != (const char *) NULL)
956  {
957  char
958  *c;
959 
960  mime_info->offset=(MagickOffsetType) strtol(attribute,&c,0);
961  if (*c == ':')
962  mime_info->extent=(size_t) strtol(c+1,(char **) NULL,0);
963  }
964  attribute=GetXMLTreeAttribute(mime,"pattern");
965  if (attribute != (const char *) NULL)
966  mime_info->pattern=ConstantString(attribute);
967  attribute=GetXMLTreeAttribute(mime,"priority");
968  if (attribute != (const char *) NULL)
969  mime_info->priority=(ssize_t) strtol(attribute,(char **) NULL,0);
970  attribute=GetXMLTreeAttribute(mime,"stealth");
971  if (attribute != (const char *) NULL)
972  mime_info->stealth=IsStringTrue(attribute);
973  attribute=GetXMLTreeAttribute(mime,"type");
974  if (attribute != (const char *) NULL)
975  mime_info->type=ConstantString(attribute);
976  status=AppendValueToLinkedList(cache,mime_info);
977  if (status == MagickFalse)
978  (void) ThrowMagickException(exception,GetMagickModule(),
979  ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
980  mime=GetNextXMLTreeTag(mime);
981  }
982  mime_map=DestroyXMLTree(mime_map);
983  return(status != 0 ? MagickTrue : MagickFalse);
984 }
985 #endif
986 
987 /*
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989 % %
990 % %
991 % %
992 + M a g i c k T o M i m e %
993 % %
994 % %
995 % %
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 %
998 % MagickToMime() returns the officially registered (or de facto) MIME
999 % media-type corresponding to a magick string. If there is no registered
1000 % media-type, then the string "image/x-magick" (all lower case) is returned.
1001 % The returned string must be deallocated by the user.
1002 %
1003 % The format of the MagickToMime method is:
1004 %
1005 % char *MagickToMime(const char *magick)
1006 %
1007 % A description of each parameter follows.
1008 %
1009 % o magick: ImageMagick format specification "magick" tag.
1010 %
1011 */
1012 MagickExport char *MagickToMime(const char *magick)
1013 {
1014  char
1015  filename[MagickPathExtent],
1016  media[MagickPathExtent];
1017 
1018  const MimeInfo
1019  *mime_info;
1020 
1022  *exception;
1023 
1024  (void) FormatLocaleString(filename,MagickPathExtent,"file.%s",magick);
1025  LocaleLower(filename);
1026  exception=AcquireExceptionInfo();
1027  mime_info=GetMimeInfo(filename,(unsigned char *) " ",1,exception);
1028  exception=DestroyExceptionInfo(exception);
1029  if (mime_info != (const MimeInfo *) NULL)
1030  return(ConstantString(GetMimeType(mime_info)));
1031  (void) FormatLocaleString(media,MagickPathExtent,"image/x-%s",magick);
1032  LocaleLower(media+8);
1033  return(ConstantString(media));
1034 }
1035 
1036 /*
1037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % %
1039 % %
1040 % %
1041 + M i m e C o m p o n e n t G e n e s i s %
1042 % %
1043 % %
1044 % %
1045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 %
1047 % MimeComponentGenesis() instantiates the mime component.
1048 %
1049 % The format of the MimeComponentGenesis method is:
1050 %
1051 % MagickBooleanType MimeComponentGenesis(void)
1052 %
1053 */
1054 MagickPrivate MagickBooleanType MimeComponentGenesis(void)
1055 {
1056  if (mime_semaphore == (SemaphoreInfo *) NULL)
1057  mime_semaphore=AcquireSemaphoreInfo();
1058  return(MagickTrue);
1059 }
1060 
1061 /*
1062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 % %
1064 % %
1065 % %
1066 + M i m e C o m p o n e n t T e r m i n u s %
1067 % %
1068 % %
1069 % %
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %
1072 % MimeComponentTerminus() destroys the mime component.
1073 %
1074 % The format of the MimeComponentTerminus method is:
1075 %
1076 % MimeComponentTerminus(void)
1077 %
1078 */
1079 
1080 static void *DestroyMimeElement(void *mime_info)
1081 {
1082  MimeInfo
1083  *p;
1084 
1085  p=(MimeInfo *) mime_info;
1086  if (p->magic != (unsigned char *) NULL)
1087  p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1088  if (p->pattern != (char *) NULL)
1089  p->pattern=DestroyString(p->pattern);
1090  if (p->description != (char *) NULL)
1091  p->description=DestroyString(p->description);
1092  if (p->type != (char *) NULL)
1093  p->type=DestroyString(p->type);
1094  if (p->path != (char *) NULL)
1095  p->path=DestroyString(p->path);
1096  p=(MimeInfo *) RelinquishMagickMemory(p);
1097  return((void *) NULL);
1098 }
1099 
1100 MagickPrivate void MimeComponentTerminus(void)
1101 {
1102  if (mime_semaphore == (SemaphoreInfo *) NULL)
1103  ActivateSemaphoreInfo(&mime_semaphore);
1104  LockSemaphoreInfo(mime_semaphore);
1105  if (mime_cache != (LinkedListInfo *) NULL)
1106  mime_cache=DestroyLinkedList(mime_cache,DestroyMimeElement);
1107  UnlockSemaphoreInfo(mime_semaphore);
1108  RelinquishSemaphoreInfo(&mime_semaphore);
1109 }
_XMLTreeInfo
Definition: xml-tree.c:77
SemaphoreInfo
Definition: semaphore.c:60
_LinkedListInfo
Definition: linked-list.c:60
_ElementInfo
Definition: draw.c:132
_ExceptionInfo
Definition: exception.h:101
_MimeInfo
Definition: mime.c:75
_StringInfo
Definition: string_.h:27