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