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