2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % M M IIIII M M EEEEE %
9 % M M IIIII M M EEEEE %
12 % MagickCore Mime Methods %
18 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
19 % dedicated to making software imaging solutions freely available. %
21 % You may not use this file except in compliance with the License. You may %
22 % obtain a copy of the License at %
24 % http://www.imagemagick.org/MagicksToolkit/script/license.php %
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. %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40 #include "MagickCore/studio.h"
41 #include "MagickCore/blob.h"
42 #include "MagickCore/client.h"
43 #include "MagickCore/configure.h"
44 #include "MagickCore/configure-private.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/linked-list.h"
48 #include "MagickCore/memory_.h"
49 #include "MagickCore/memory-private.h"
50 #include "MagickCore/mime.h"
51 #include "MagickCore/mime-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/semaphore.h"
54 #include "MagickCore/string_.h"
55 #include "MagickCore/token.h"
56 #include "MagickCore/utility.h"
57 #include "MagickCore/utility-private.h"
58 #include "MagickCore/xml-tree.h"
59 #include "MagickCore/xml-tree-private.h"
64 #define MimeFilename "mime.xml"
114 "<?xml version=\"1.0\"?>"
118 static LinkedListInfo
119 *mime_cache = (LinkedListInfo *) NULL;
122 *mime_semaphore = (SemaphoreInfo *) NULL;
125 Forward declarations.
127 static MagickBooleanType
128 IsMimeCacheInstantiated(ExceptionInfo *),
129 LoadMimeCache(LinkedListInfo *,const char *,const char *,const size_t,
133 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 % A c q u i r e M i m e C a c h e %
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
143 % AcquireMimeCache() caches one or more magic configurations which provides
144 % a mapping between magic attributes and a magic name.
146 % The format of the AcquireMimeCache method is:
148 % LinkedListInfo *AcquireMimeCache(const char *filename,
149 % ExceptionInfo *exception)
151 % A description of each parameter follows:
153 % o filename: the font file name.
155 % o exception: return any errors or warnings in this structure.
158 MagickExport LinkedListInfo *AcquireMimeCache(const char *filename,
159 ExceptionInfo *exception)
167 cache=NewLinkedList(0);
169 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
177 options=GetConfigureOptions(filename,exception);
178 option=(const StringInfo *) GetNextValueInLinkedList(options);
179 while (option != (const StringInfo *) NULL)
181 status&=LoadMimeCache(cache,(const char *)
182 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
183 option=(const StringInfo *) GetNextValueInLinkedList(options);
185 options=DestroyConfigureOptions(options);
188 if (IsLinkedListEmpty(cache) != MagickFalse)
189 status&=LoadMimeCache(cache,MimeMap,"built-in",0,exception);
194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 + G e t M i m e I n f o %
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 % GetMimeInfo() attempts to classify the content to identify which mime type
205 % is associated with the content, if any.
207 % The format of the GetMimeInfo method is:
209 % const MimeInfo *GetMimeInfo(const char *filename,
210 % const unsigned char *magic,const size_t length,
211 % ExceptionInfo *exception)
213 % A description of each parameter follows:
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).
218 % o magic: A binary string generally representing the first few characters
219 % of the image file or blob.
221 % o length: the length of the binary signature.
223 % o exception: return any errors or warnings in this structure.
226 MagickExport const MimeInfo *GetMimeInfo(const char *filename,
227 const unsigned char *magic,const size_t length,ExceptionInfo *exception)
235 register const MimeInfo
238 register const unsigned char
250 assert(exception != (ExceptionInfo *) NULL);
251 if (IsMimeCacheInstantiated(exception) == MagickFalse)
252 return((const MimeInfo *) NULL);
256 mime_info=(const MimeInfo *) NULL;
258 LockSemaphoreInfo(mime_semaphore);
259 ResetLinkedListIterator(mime_cache);
260 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
261 if ((magic == (const unsigned char *) NULL) || (length == 0))
263 UnlockSemaphoreInfo(mime_semaphore);
266 while (p != (const MimeInfo *) NULL)
268 assert(p->offset >= 0);
269 if (mime_info != (const MimeInfo *) NULL)
270 if (p->priority > mime_info->priority)
272 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
275 if ((p->pattern != (char *) NULL) && (filename != (char *) NULL))
277 if (GlobExpression(filename,p->pattern,MagickFalse) != MagickFalse)
279 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
282 switch (p->data_type)
286 if ((size_t) (p->offset+4) > length)
289 value=(ssize_t) (*q++);
292 if (p->value == value)
297 if ((p->value & p->mask) == value)
304 if ((size_t) (p->offset+4) > length)
308 if (p->endian == UndefinedEndian)
309 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
310 if (endian == LSBEndian)
312 value=(ssize_t) (*q++);
317 value=(ssize_t) (*q++) << 8;
322 if (p->value == value)
327 if ((p->value & p->mask) == value)
334 if ((size_t) (p->offset+4) > length)
338 if (p->endian == UndefinedEndian)
339 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
340 if (endian == LSBEndian)
342 value=(ssize_t) (*q++);
343 value|=((ssize_t) *q++) << 8;
344 value|=((ssize_t) *q++) << 16;
345 value|=((ssize_t) *q++) << 24;
349 value=(ssize_t) (*q++) << 24;
350 value|=((ssize_t) *q++) << 16;
351 value|=((ssize_t) *q++) << 8;
352 value|=((ssize_t) *q++);
356 if (p->value == value)
361 if ((p->value & p->mask) == value)
369 for (i=0; i <= (ssize_t) p->extent; i++)
371 if ((size_t) (p->offset+i+p->length) > length)
373 if (memcmp(magic+p->offset+i,p->magic,p->length) == 0)
382 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
384 if (mime_info != (const MimeInfo *) NULL)
385 (void) InsertValueInLinkedList(mime_cache,0,
386 RemoveElementByValueFromLinkedList(mime_cache,p));
387 UnlockSemaphoreInfo(mime_semaphore);
392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
396 % G e t M i m e I n f o L i s t %
400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
402 % GetMimeInfoList() returns any image aliases that match the specified
405 % The magic of the GetMimeInfoList function is:
407 % const MimeInfo **GetMimeInfoList(const char *pattern,
408 % size_t *number_aliases,ExceptionInfo *exception)
410 % A description of each parameter follows:
412 % o pattern: Specifies a pointer to a text string containing a pattern.
414 % o number_aliases: This integer returns the number of magics in the
417 % o exception: return any errors or warnings in this structure.
421 #if defined(__cplusplus) || defined(c_plusplus)
425 static int MimeInfoCompare(const void *x,const void *y)
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));
438 #if defined(__cplusplus) || defined(c_plusplus)
442 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern,
443 size_t *number_aliases,ExceptionInfo *exception)
448 register const MimeInfo
457 assert(pattern != (char *) NULL);
458 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
459 assert(number_aliases != (size_t *) NULL);
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);
471 LockSemaphoreInfo(mime_semaphore);
472 ResetLinkedListIterator(mime_cache);
473 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
474 for (i=0; p != (const MimeInfo *) NULL; )
476 if ((p->stealth == MagickFalse) &&
477 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
479 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
481 UnlockSemaphoreInfo(mime_semaphore);
482 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare);
483 aliases[i]=(MimeInfo *) NULL;
484 *number_aliases=(size_t) i;
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
493 % G e t M i m e L i s t %
497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
499 % GetMimeList() returns any image format alias that matches the specified
502 % The format of the GetMimeList function is:
504 % char **GetMimeList(const char *pattern,size_t *number_aliases,
505 % ExceptionInfo *exception)
507 % A description of each parameter follows:
509 % o pattern: Specifies a pointer to a text string containing a pattern.
511 % o number_aliases: This integer returns the number of image format aliases
514 % o exception: return any errors or warnings in this structure.
518 #if defined(__cplusplus) || defined(c_plusplus)
522 static int MimeCompare(const void *x,const void *y)
530 return(strcasecmp(p,q));
533 #if defined(__cplusplus) || defined(c_plusplus)
537 MagickExport char **GetMimeList(const char *pattern,
538 size_t *number_aliases,ExceptionInfo *exception)
543 register const MimeInfo
550 Allocate configure list.
552 assert(pattern != (char *) NULL);
553 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
554 assert(number_aliases != (size_t *) NULL);
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);
563 LockSemaphoreInfo(mime_semaphore);
564 ResetLinkedListIterator(mime_cache);
565 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
566 for (i=0; p != (const MimeInfo *) NULL; )
568 if ((p->stealth == MagickFalse) &&
569 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
570 aliases[i++]=ConstantString(p->type);
571 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
573 UnlockSemaphoreInfo(mime_semaphore);
574 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare);
575 aliases[i]=(char *) NULL;
576 *number_aliases=(size_t) i;
581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585 % G e t M i m e D e s c r i p t i o n %
589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 % GetMimeDescription() returns the mime type description.
593 % The format of the GetMimeDescription method is:
595 % const char *GetMimeDescription(const MimeInfo *mime_info)
597 % A description of each parameter follows:
599 % o mime_info: The magic info.
602 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info)
604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
605 assert(mime_info != (MimeInfo *) NULL);
606 assert(mime_info->signature == MagickCoreSignature);
607 return(mime_info->description);
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615 % G e t M i m e T y p e %
619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
621 % GetMimeType() returns the mime type.
623 % The format of the GetMimeType method is:
625 % const char *GetMimeType(const MimeInfo *mime_info)
627 % A description of each parameter follows:
629 % o mime_info: The magic info.
632 MagickExport const char *GetMimeType(const MimeInfo *mime_info)
634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
635 assert(mime_info != (MimeInfo *) NULL);
636 assert(mime_info->signature == MagickCoreSignature);
637 return(mime_info->type);
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 + I s M i m e C a c h e I n s t a n t i a t e d %
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
651 % IsMimeCacheInstantiated() determines if the mime list is instantiated. If
652 % not, it instantiates the list and returns it.
654 % The format of the IsMimeInstantiated method is:
656 % MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
658 % A description of each parameter follows.
660 % o exception: return any errors or warnings in this structure.
663 static MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
665 if (mime_cache == (LinkedListInfo *) NULL)
667 if (mime_semaphore == (SemaphoreInfo *) NULL)
668 ActivateSemaphoreInfo(&mime_semaphore);
669 LockSemaphoreInfo(mime_semaphore);
670 if (mime_cache == (LinkedListInfo *) NULL)
671 mime_cache=AcquireMimeCache(MimeFilename,exception);
672 UnlockSemaphoreInfo(mime_semaphore);
674 return(mime_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 % L i s t M i m e I n f o %
686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688 % ListMimeInfo() lists the magic info to a file.
690 % The format of the ListMimeInfo method is:
692 % MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
694 % A description of each parameter follows.
696 % o file: An pointer to a FILE.
698 % o exception: return any errors or warnings in this structure.
701 MagickExport MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
718 if (file == (const FILE *) NULL)
720 mime_info=GetMimeInfoList("*",&number_aliases,exception);
721 if (mime_info == (const MimeInfo **) NULL)
724 path=(const char *) NULL;
725 for (i=0; i < (ssize_t) number_aliases; i++)
727 if (mime_info[i]->stealth != MagickFalse)
729 if ((path == (const char *) NULL) ||
730 (strcasecmp(path,mime_info[i]->path) != 0))
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");
739 path=mime_info[i]->path;
740 (void) FormatLocaleFile(file,"%s",mime_info[i]->type);
741 if (strlen(mime_info[i]->type) <= 25)
743 for (j=(ssize_t) strlen(mime_info[i]->type); j <= 27; j++)
744 (void) FormatLocaleFile(file," ");
748 (void) FormatLocaleFile(file,"\n");
749 for (j=0; j <= 27; j++)
750 (void) FormatLocaleFile(file," ");
752 if (mime_info[i]->description != (char *) NULL)
753 (void) FormatLocaleFile(file,"%s",mime_info[i]->description);
754 (void) FormatLocaleFile(file,"\n");
757 mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info);
762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766 + L o a d M i m e C a c h e %
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772 % LoadMimeCache() loads the mime configurations which provides a mapping
773 % between mime attributes and a mime name.
775 % The format of the LoadMimeCache method is:
777 % MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
778 % const char *filename,const size_t depth,ExceptionInfo *exception)
780 % A description of each parameter follows:
782 % o xml: The mime list in XML format.
784 % o filename: The mime list filename.
786 % o depth: depth of <include /> statements.
788 % o exception: return any errors or warnings in this structure.
791 static MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
792 const char *filename,const size_t depth,ExceptionInfo *exception)
798 *mime_info = (MimeInfo *) NULL;
809 Load the mime map file.
811 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
812 "Loading mime map \"%s\" ...",filename);
813 if (xml == (const char *) NULL)
815 mime_map=NewXMLTree(xml,exception);
816 if (mime_map == (XMLTreeInfo *) NULL)
819 include=GetXMLTreeChild(mime_map,"include");
820 while (include != (XMLTreeInfo *) NULL)
823 Process include element.
825 attribute=GetXMLTreeAttribute(include,"file");
826 if (attribute != (const char *) NULL)
828 if (depth > MagickMaxRecursionDepth)
829 (void) ThrowMagickException(exception,GetMagickModule(),
830 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",filename);
834 path[MagickPathExtent],
837 GetPathComponent(filename,HeadPath,path);
839 (void) ConcatenateMagickString(path,DirectorySeparator,
841 if (*attribute == *DirectorySeparator)
842 (void) CopyMagickString(path,attribute,MagickPathExtent);
844 (void) ConcatenateMagickString(path,attribute,MagickPathExtent);
845 file_xml=FileToXML(path,~0UL);
846 if (file_xml != (char *) NULL)
848 status&=LoadMimeCache(cache,file_xml,path,depth+1,exception);
849 file_xml=DestroyString(file_xml);
853 include=GetNextXMLTreeTag(include);
855 mime=GetXMLTreeChild(mime_map,"mime");
856 while (mime != (XMLTreeInfo *) NULL)
859 Process mime element.
861 mime_info=(MimeInfo *) AcquireCriticalMemory(sizeof(*mime_info));
862 (void) memset(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)
867 mime_info->data_type=(DataType) ParseCommandOption(MagickDataTypeOptions,
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)
874 mime_info->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
875 MagickTrue,attribute);
876 attribute=GetXMLTreeAttribute(mime,"magic");
877 if (attribute != (const char *) NULL)
885 register unsigned char
888 token=AcquireString(attribute);
889 (void) SubstituteString((char **) &token,"<","<");
890 (void) SubstituteString((char **) &token,"&","&");
891 (void) SubstituteString((char **) &token,""","\"");
892 mime_info->magic=(unsigned char *) AcquireString(token);
894 for (p=token; *p != '\0'; )
899 if (isdigit((int) ((unsigned char) *p)) != 0)
904 *q++=(unsigned char) strtol(p,&end,8);
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;
926 *q++=(unsigned char) (*p++);
929 token=DestroyString(token);
930 if (mime_info->data_type != StringData)
931 mime_info->value=(ssize_t) strtoul((char *) mime_info->magic,
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)
943 mime_info->offset=(MagickOffsetType) strtol(attribute,&c,0);
945 mime_info->extent=(size_t) strtol(c+1,(char **) NULL,0);
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);
965 mime_map=DestroyXMLTree(mime_map);
966 return(status != 0 ? MagickTrue : MagickFalse);
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974 + M a g i c k T o M i m e %
978 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
985 % The format of the MagickToMime method is:
987 % char *MagickToMime(const char *magick)
989 % A description of each parameter follows.
991 % o magick: ImageMagick format specification "magick" tag.
994 MagickExport char *MagickToMime(const char *magick)
997 filename[MagickPathExtent],
998 media[MagickPathExtent];
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));
1019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1023 + M i m e C o m p o n e n t G e n e s i s %
1027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 % MimeComponentGenesis() instantiates the mime component.
1031 % The format of the MimeComponentGenesis method is:
1033 % MagickBooleanType MimeComponentGenesis(void)
1036 MagickPrivate MagickBooleanType MimeComponentGenesis(void)
1038 if (mime_semaphore == (SemaphoreInfo *) NULL)
1039 mime_semaphore=AcquireSemaphoreInfo();
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 + M i m e C o m p o n e n t T e r m i n u s %
1052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 % MimeComponentTerminus() destroys the mime component.
1056 % The format of the MimeComponentTerminus method is:
1058 % MimeComponentTerminus(void)
1062 static void *DestroyMimeElement(void *mime_info)
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)
1073 p->description=DestroyString(p->description);
1074 if (p->type != (char *) NULL)
1075 p->type=DestroyString(p->type);
1076 if (p->path != (char *) NULL)
1077 p->path=DestroyString(p->path);
1078 p=(MimeInfo *) RelinquishMagickMemory(p);
1079 return((void *) NULL);
1082 MagickPrivate void MimeComponentTerminus(void)
1084 if (mime_semaphore == (SemaphoreInfo *) NULL)
1085 ActivateSemaphoreInfo(&mime_semaphore);
1086 LockSemaphoreInfo(mime_semaphore);
1087 if (mime_cache != (LinkedListInfo *) NULL)
1088 mime_cache=DestroyLinkedList(mime_cache,DestroyMimeElement);
1089 UnlockSemaphoreInfo(mime_semaphore);
1090 RelinquishSemaphoreInfo(&mime_semaphore);