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