MagickCore  7.0.9
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-2019 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"
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 LinkedListInfo
114 
115 static SemaphoreInfo
117 
118 /*
119  Forward declarations.
120 */
121 static MagickBooleanType
123  LoadMimeCache(LinkedListInfo *,const char *,const char *,const size_t,
124  ExceptionInfo *);
125 
126 /*
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 % %
129 % %
130 % %
131 % A c q u i r e M i m e C a c h e %
132 % %
133 % %
134 % %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 %
137 % AcquireMimeCache() caches one or more magic configurations which provides
138 % a mapping between magic attributes and a magic name.
139 %
140 % The format of the AcquireMimeCache method is:
141 %
142 % LinkedListInfo *AcquireMimeCache(const char *filename,
143 % ExceptionInfo *exception)
144 %
145 % A description of each parameter follows:
146 %
147 % o filename: the font file name.
148 %
149 % o exception: return any errors or warnings in this structure.
150 %
151 */
153  ExceptionInfo *exception)
154 {
156  *cache;
157 
159  status;
160 
161  cache=NewLinkedList(0);
162  status=MagickTrue;
163 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
164  {
165  const StringInfo
166  *option;
167 
169  *options;
170 
171  options=GetConfigureOptions(filename,exception);
172  option=(const StringInfo *) GetNextValueInLinkedList(options);
173  while (option != (const StringInfo *) NULL)
174  {
175  status&=LoadMimeCache(cache,(const char *)
176  GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
177  option=(const StringInfo *) GetNextValueInLinkedList(options);
178  }
179  options=DestroyConfigureOptions(options);
180  }
181 #endif
182  return(cache);
183 }
184 
185 /*
186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 % %
188 % %
189 % %
190 + G e t M i m e I n f o %
191 % %
192 % %
193 % %
194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
195 %
196 % GetMimeInfo() attempts to classify the content to identify which mime type
197 % is associated with the content, if any.
198 %
199 % The format of the GetMimeInfo method is:
200 %
201 % const MimeInfo *GetMimeInfo(const char *filename,
202 % const unsigned char *magic,const size_t length,
203 % ExceptionInfo *exception)
204 %
205 % A description of each parameter follows:
206 %
207 % o filename: If we cannot not classify the string, we attempt to classify
208 % based on the filename (e.g. *.pdf returns application/pdf).
209 %
210 % o magic: A binary string generally representing the first few characters
211 % of the image file or blob.
212 %
213 % o length: the length of the binary signature.
214 %
215 % o exception: return any errors or warnings in this structure.
216 %
217 */
218 MagickExport const MimeInfo *GetMimeInfo(const char *filename,
219  const unsigned char *magic,const size_t length,ExceptionInfo *exception)
220 {
221  const MimeInfo
222  *mime_info;
223 
224  EndianType
225  endian;
226 
227  register const MimeInfo
228  *p;
229 
230  register const unsigned char
231  *q;
232 
233  register ssize_t
234  i;
235 
236  ssize_t
237  value;
238 
239  unsigned long
240  lsb_first;
241 
242  assert(exception != (ExceptionInfo *) NULL);
243  if (IsMimeCacheInstantiated(exception) == MagickFalse)
244  return((const MimeInfo *) NULL);
245  /*
246  Search for mime tag.
247  */
248  mime_info=(const MimeInfo *) NULL;
249  lsb_first=1;
253  if ((magic == (const unsigned char *) NULL) || (length == 0))
254  {
256  return(p);
257  }
258  while (p != (const MimeInfo *) NULL)
259  {
260  assert(p->offset >= 0);
261  if (mime_info != (const MimeInfo *) NULL)
262  if (p->priority > mime_info->priority)
263  {
265  continue;
266  }
267  if ((p->pattern != (char *) NULL) && (filename != (char *) NULL))
268  {
269  if (GlobExpression(filename,p->pattern,MagickFalse) != MagickFalse)
270  mime_info=p;
272  continue;
273  }
274  switch (p->data_type)
275  {
276  case ByteData:
277  {
278  if ((size_t) (p->offset+4) > length)
279  break;
280  q=magic+p->offset;
281  value=(ssize_t) (*q++);
282  if (p->mask == 0)
283  {
284  if (p->value == value)
285  mime_info=p;
286  }
287  else
288  {
289  if ((p->value & p->mask) == value)
290  mime_info=p;
291  }
292  break;
293  }
294  case ShortData:
295  {
296  if ((size_t) (p->offset+4) > length)
297  break;
298  q=magic+p->offset;
299  endian=p->endian;
300  if (p->endian == UndefinedEndian)
301  endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
302  if (endian == LSBEndian)
303  {
304  value=(ssize_t) (*q++);
305  value|=(*q++) << 8;
306  }
307  else
308  {
309  value=(ssize_t) (*q++) << 8;
310  value|=(*q++);
311  }
312  if (p->mask == 0)
313  {
314  if (p->value == value)
315  mime_info=p;
316  }
317  else
318  {
319  if ((p->value & p->mask) == value)
320  mime_info=p;
321  }
322  break;
323  }
324  case LongData:
325  {
326  if ((size_t) (p->offset+4) > length)
327  break;
328  q=magic+p->offset;
329  endian=p->endian;
330  if (p->endian == UndefinedEndian)
331  endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
332  if (endian == LSBEndian)
333  {
334  value=(ssize_t) (*q++);
335  value|=((ssize_t) *q++) << 8;
336  value|=((ssize_t) *q++) << 16;
337  value|=((ssize_t) *q++) << 24;
338  }
339  else
340  {
341  value=(ssize_t) (*q++) << 24;
342  value|=((ssize_t) *q++) << 16;
343  value|=((ssize_t) *q++) << 8;
344  value|=((ssize_t) *q++);
345  }
346  if (p->mask == 0)
347  {
348  if (p->value == value)
349  mime_info=p;
350  }
351  else
352  {
353  if ((p->value & p->mask) == value)
354  mime_info=p;
355  }
356  break;
357  }
358  case StringData:
359  default:
360  {
361  for (i=0; i <= (ssize_t) p->extent; i++)
362  {
363  if ((size_t) (p->offset+i+p->length) > length)
364  break;
365  if (memcmp(magic+p->offset+i,p->magic,p->length) == 0)
366  {
367  mime_info=p;
368  break;
369  }
370  }
371  break;
372  }
373  }
375  }
376  if (mime_info != (const MimeInfo *) NULL)
380  return(mime_info);
381 }
382 
383 /*
384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
385 % %
386 % %
387 % %
388 % G e t M i m e I n f o L i s t %
389 % %
390 % %
391 % %
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
393 %
394 % GetMimeInfoList() returns any image aliases that match the specified
395 % pattern.
396 %
397 % The magic of the GetMimeInfoList function is:
398 %
399 % const MimeInfo **GetMimeInfoList(const char *pattern,
400 % size_t *number_aliases,ExceptionInfo *exception)
401 %
402 % A description of each parameter follows:
403 %
404 % o pattern: Specifies a pointer to a text string containing a pattern.
405 %
406 % o number_aliases: This integer returns the number of magics in the
407 % list.
408 %
409 % o exception: return any errors or warnings in this structure.
410 %
411 */
412 
413 #if defined(__cplusplus) || defined(c_plusplus)
414 extern "C" {
415 #endif
416 
417 static int MimeInfoCompare(const void *x,const void *y)
418 {
419  const MimeInfo
420  **p,
421  **q;
422 
423  p=(const MimeInfo **) x,
424  q=(const MimeInfo **) y;
425  if (strcasecmp((*p)->path,(*q)->path) == 0)
426  return(strcasecmp((*p)->type,(*q)->type));
427  return(strcasecmp((*p)->path,(*q)->path));
428 }
429 
430 #if defined(__cplusplus) || defined(c_plusplus)
431 }
432 #endif
433 
434 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern,
435  size_t *number_aliases,ExceptionInfo *exception)
436 {
437  const MimeInfo
438  **aliases;
439 
440  register const MimeInfo
441  *p;
442 
443  register ssize_t
444  i;
445 
446  /*
447  Allocate mime list.
448  */
449  assert(pattern != (char *) NULL);
450  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
451  assert(number_aliases != (size_t *) NULL);
452  *number_aliases=0;
453  p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
454  if (p == (const MimeInfo *) NULL)
455  return((const MimeInfo **) NULL);
456  aliases=(const MimeInfo **) AcquireQuantumMemory((size_t)
457  GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
458  if (aliases == (const MimeInfo **) NULL)
459  return((const MimeInfo **) NULL);
460  /*
461  Generate mime list.
462  */
466  for (i=0; p != (const MimeInfo *) NULL; )
467  {
468  if ((p->stealth == MagickFalse) &&
469  (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
470  aliases[i++]=p;
472  }
474  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare);
475  aliases[i]=(MimeInfo *) NULL;
476  *number_aliases=(size_t) i;
477  return(aliases);
478 }
479 
480 /*
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % %
483 % %
484 % %
485 % G e t M i m e L i s t %
486 % %
487 % %
488 % %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %
491 % GetMimeList() returns any image format alias that matches the specified
492 % pattern.
493 %
494 % The format of the GetMimeList function is:
495 %
496 % char **GetMimeList(const char *pattern,size_t *number_aliases,
497 % ExceptionInfo *exception)
498 %
499 % A description of each parameter follows:
500 %
501 % o pattern: Specifies a pointer to a text string containing a pattern.
502 %
503 % o number_aliases: This integer returns the number of image format aliases
504 % in the list.
505 %
506 % o exception: return any errors or warnings in this structure.
507 %
508 */
509 
510 #if defined(__cplusplus) || defined(c_plusplus)
511 extern "C" {
512 #endif
513 
514 static int MimeCompare(const void *x,const void *y)
515 {
516  register char
517  *p,
518  *q;
519 
520  p=(char *) x;
521  q=(char *) y;
522  return(strcasecmp(p,q));
523 }
524 
525 #if defined(__cplusplus) || defined(c_plusplus)
526 }
527 #endif
528 
529 MagickExport char **GetMimeList(const char *pattern,
530  size_t *number_aliases,ExceptionInfo *exception)
531 {
532  char
533  **aliases;
534 
535  register const MimeInfo
536  *p;
537 
538  register ssize_t
539  i;
540 
541  /*
542  Allocate configure list.
543  */
544  assert(pattern != (char *) NULL);
545  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
546  assert(number_aliases != (size_t *) NULL);
547  *number_aliases=0;
548  p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
549  if (p == (const MimeInfo *) NULL)
550  return((char **) NULL);
551  aliases=(char **) AcquireQuantumMemory((size_t)
552  GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
553  if (aliases == (char **) NULL)
554  return((char **) NULL);
558  for (i=0; p != (const MimeInfo *) NULL; )
559  {
560  if ((p->stealth == MagickFalse) &&
561  (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
562  aliases[i++]=ConstantString(p->type);
564  }
566  qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare);
567  aliases[i]=(char *) NULL;
568  *number_aliases=(size_t) i;
569  return(aliases);
570 }
571 
572 /*
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 % %
575 % %
576 % %
577 % G e t M i m e D e s c r i p t i o n %
578 % %
579 % %
580 % %
581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 %
583 % GetMimeDescription() returns the mime type description.
584 %
585 % The format of the GetMimeDescription method is:
586 %
587 % const char *GetMimeDescription(const MimeInfo *mime_info)
588 %
589 % A description of each parameter follows:
590 %
591 % o mime_info: The magic info.
592 %
593 */
594 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info)
595 {
596  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
597  assert(mime_info != (MimeInfo *) NULL);
598  assert(mime_info->signature == MagickCoreSignature);
599  return(mime_info->description);
600 }
601 
602 /*
603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 % %
605 % %
606 % %
607 % G e t M i m e T y p e %
608 % %
609 % %
610 % %
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 %
613 % GetMimeType() returns the mime type.
614 %
615 % The format of the GetMimeType method is:
616 %
617 % const char *GetMimeType(const MimeInfo *mime_info)
618 %
619 % A description of each parameter follows:
620 %
621 % o mime_info: The magic info.
622 %
623 */
624 MagickExport const char *GetMimeType(const MimeInfo *mime_info)
625 {
626  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
627  assert(mime_info != (MimeInfo *) NULL);
628  assert(mime_info->signature == MagickCoreSignature);
629  return(mime_info->type);
630 }
631 
632 /*
633 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634 % %
635 % %
636 % %
637 + I s M i m e C a c h e I n s t a n t i a t e d %
638 % %
639 % %
640 % %
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642 %
643 % IsMimeCacheInstantiated() determines if the mime list is instantiated. If
644 % not, it instantiates the list and returns it.
645 %
646 % The format of the IsMimeInstantiated method is:
647 %
648 % MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
649 %
650 % A description of each parameter follows.
651 %
652 % o exception: return any errors or warnings in this structure.
653 %
654 */
656 {
657  if (mime_cache == (LinkedListInfo *) NULL)
658  {
659  if (mime_semaphore == (SemaphoreInfo *) NULL)
662  if (mime_cache == (LinkedListInfo *) NULL)
665  }
666  return(mime_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
667 }
668 
669 /*
670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671 % %
672 % %
673 % %
674 % L i s t M i m e I n f o %
675 % %
676 % %
677 % %
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 %
680 % ListMimeInfo() lists the magic info to a file.
681 %
682 % The format of the ListMimeInfo method is:
683 %
684 % MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
685 %
686 % A description of each parameter follows.
687 %
688 % o file: An pointer to a FILE.
689 %
690 % o exception: return any errors or warnings in this structure.
691 %
692 */
694 {
695  const char
696  *path;
697 
698  const MimeInfo
699  **mime_info;
700 
701  register ssize_t
702  i;
703 
704  size_t
705  number_aliases;
706 
707  ssize_t
708  j;
709 
710  if (file == (const FILE *) NULL)
711  file=stdout;
712  mime_info=GetMimeInfoList("*",&number_aliases,exception);
713  if (mime_info == (const MimeInfo **) NULL)
714  return(MagickFalse);
715  j=0;
716  path=(const char *) NULL;
717  for (i=0; i < (ssize_t) number_aliases; i++)
718  {
719  if (mime_info[i]->stealth != MagickFalse)
720  continue;
721  if ((path == (const char *) NULL) ||
722  (strcasecmp(path,mime_info[i]->path) != 0))
723  {
724  if (mime_info[i]->path != (char *) NULL)
725  (void) FormatLocaleFile(file,"\nPath: %s\n\n",mime_info[i]->path);
726  (void) FormatLocaleFile(file,"Type Description\n");
727  (void) FormatLocaleFile(file,
728  "-------------------------------------------------"
729  "------------------------------\n");
730  }
731  path=mime_info[i]->path;
732  (void) FormatLocaleFile(file,"%s",mime_info[i]->type);
733  if (strlen(mime_info[i]->type) <= 25)
734  {
735  for (j=(ssize_t) strlen(mime_info[i]->type); j <= 27; j++)
736  (void) FormatLocaleFile(file," ");
737  }
738  else
739  {
740  (void) FormatLocaleFile(file,"\n");
741  for (j=0; j <= 27; j++)
742  (void) FormatLocaleFile(file," ");
743  }
744  if (mime_info[i]->description != (char *) NULL)
745  (void) FormatLocaleFile(file,"%s",mime_info[i]->description);
746  (void) FormatLocaleFile(file,"\n");
747  }
748  (void) fflush(file);
749  mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info);
750  return(MagickTrue);
751 }
752 
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 
961 /*
962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 % %
964 % %
965 % %
966 + M a g i c k T o M i m e %
967 % %
968 % %
969 % %
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 %
972 % MagickToMime() returns the officially registered (or de facto) MIME
973 % media-type corresponding to a magick string. If there is no registered
974 % media-type, then the string "image/x-magick" (all lower case) is returned.
975 % The returned string must be deallocated by the user.
976 %
977 % The format of the MagickToMime method is:
978 %
979 % char *MagickToMime(const char *magick)
980 %
981 % A description of each parameter follows.
982 %
983 % o magick: ImageMagick format specification "magick" tag.
984 %
985 */
986 MagickExport char *MagickToMime(const char *magick)
987 {
988  char
989  filename[MagickPathExtent],
990  media[MagickPathExtent];
991 
992  const MimeInfo
993  *mime_info;
994 
996  *exception;
997 
998  (void) FormatLocaleString(filename,MagickPathExtent,"file.%s",magick);
999  LocaleLower(filename);
1000  exception=AcquireExceptionInfo();
1001  mime_info=GetMimeInfo(filename,(unsigned char *) " ",1,exception);
1002  exception=DestroyExceptionInfo(exception);
1003  if (mime_info != (const MimeInfo *) NULL)
1004  return(ConstantString(GetMimeType(mime_info)));
1005  (void) FormatLocaleString(media,MagickPathExtent,"image/x-%s",magick);
1006  LocaleLower(media+8);
1007  return(ConstantString(media));
1008 }
1009 
1010 /*
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 % %
1013 % %
1014 % %
1015 + M i m e C o m p o n e n t G e n e s i s %
1016 % %
1017 % %
1018 % %
1019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1020 %
1021 % MimeComponentGenesis() instantiates the mime component.
1022 %
1023 % The format of the MimeComponentGenesis method is:
1024 %
1025 % MagickBooleanType MimeComponentGenesis(void)
1026 %
1027 */
1029 {
1030  if (mime_semaphore == (SemaphoreInfo *) NULL)
1032  return(MagickTrue);
1033 }
1034 
1035 /*
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 % %
1038 % %
1039 % %
1040 + M i m e C o m p o n e n t T e r m i n u s %
1041 % %
1042 % %
1043 % %
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045 %
1046 % MimeComponentTerminus() destroys the mime component.
1047 %
1048 % The format of the MimeComponentTerminus method is:
1049 %
1050 % MimeComponentTerminus(void)
1051 %
1052 */
1053 
1054 static void *DestroyMimeElement(void *mime_info)
1055 {
1056  register MimeInfo
1057  *p;
1058 
1059  p=(MimeInfo *) mime_info;
1060  if (p->magic != (unsigned char *) NULL)
1061  p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1062  if (p->pattern != (char *) NULL)
1063  p->pattern=DestroyString(p->pattern);
1064  if (p->description != (char *) NULL)
1066  if (p->type != (char *) NULL)
1067  p->type=DestroyString(p->type);
1068  if (p->path != (char *) NULL)
1069  p->path=DestroyString(p->path);
1071  return((void *) NULL);
1072 }
1073 
1075 {
1076  if (mime_semaphore == (SemaphoreInfo *) NULL)
1079  if (mime_cache != (LinkedListInfo *) NULL)
1083 }
Definition: mime.c:69
MagickExport char * MagickToMime(const char *magick)
Definition: mime.c:986
MagickExport const char * GetMimeType(const MimeInfo *mime_info)
Definition: mime.c:624
#define MagickMaxRecursionDepth
Definition: studio.h:344
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:152
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:2972
MagickOffsetType offset
Definition: mime.c:81
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 size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:426
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:218
ssize_t mask
Definition: mime.c:90
size_t signature
Definition: mime.c:106
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
static void * AcquireCriticalMemory(const size_t size)
MagickExport void * RemoveElementByValueFromLinkedList(LinkedListInfo *list_info, const void *value)
Definition: linked-list.c:756
static MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *)
Definition: mime.c:655
size_t extent
Definition: mime.c:84
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:129
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:693
size_t length
Definition: mime.c:97
static int MimeCompare(const void *x, const void *y)
Definition: mime.c:514
#define MagickCoreSignature
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1215
MagickExport LinkedListInfo * GetConfigureOptions(const char *filename, ExceptionInfo *exception)
Definition: configure.c:639
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:404
MagickBooleanType
Definition: magick-type.h:158
#define DirectorySeparator
Definition: studio.h:259
unsigned int MagickStatusType
Definition: magick-type.h:121
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
MagickExport void LocaleLower(char *string)
Definition: locale.c:1490
static void * DestroyMimeElement(void *mime_info)
Definition: mime.c:1054
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:553
ssize_t value
Definition: mime.c:90
MagickExport MagickBooleanType GlobExpression(const char *expression, const char *pattern, const MagickBooleanType case_insensitive)
Definition: token.c:352
#define MagickPathExtent
MagickExport MagickBooleanType IsStringTrue(const char *value)
Definition: string.c:1425
static LinkedListInfo * mime_cache
Definition: mime.c:113
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:1413
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:2575
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:594
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
#define GetMagickModule()
Definition: log.h:28
MagickExport const char * GetStringInfoPath(const StringInfo *string_info)
Definition: string.c:1302
MagickExport const char * GetXMLTreeAttribute(XMLTreeInfo *xml_info, const char *tag)
Definition: xml-tree.c:779
unsigned char * magic
Definition: mime.c:100
MagickExport char * DestroyString(char *string)
Definition: string.c:823
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:529
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1084
static SemaphoreInfo * mime_semaphore
Definition: mime.c:116
MagickPrivate MagickBooleanType MimeComponentGenesis(void)
Definition: mime.c:1028
#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:417
char * pattern
Definition: mime.c:72
MagickPrivate void MimeComponentTerminus(void)
Definition: mime.c:1074
#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:311
MagickExport char * ConstantString(const char *source)
Definition: string.c:700
MagickExport XMLTreeInfo * NewXMLTree(const char *xml, ExceptionInfo *exception)
Definition: xml-tree.c:1956
EndianType endian
Definition: mime.c:94
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:434