2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % M M IIIII M M EEEEE %
9 % M M IIIII M M EEEEE %
12 % MagickCore Mime Methods %
18 % Copyright 1999-2017 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/mime.h"
50 #include "MagickCore/mime-private.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"
56 #include "MagickCore/utility-private.h"
57 #include "MagickCore/xml-tree.h"
58 #include "MagickCore/xml-tree-private.h"
63 #define MimeFilename "mime.xml"
113 "<?xml version=\"1.0\"?>"
117 static LinkedListInfo
118 *mime_cache = (LinkedListInfo *) NULL;
121 *mime_semaphore = (SemaphoreInfo *) NULL;
124 Forward declarations.
126 static MagickBooleanType
127 IsMimeCacheInstantiated(ExceptionInfo *),
128 LoadMimeCache(LinkedListInfo *,const char *,const char *,const size_t,
132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136 % A c q u i r e M i m e C a c h e %
140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 % AcquireMimeCache() caches one or more magic configurations which provides
143 % a mapping between magic attributes and a magic name.
145 % The format of the AcquireMimeCache method is:
147 % LinkedListInfo *AcquireMimeCache(const char *filename,
148 % ExceptionInfo *exception)
150 % A description of each parameter follows:
152 % o filename: the font file name.
154 % o exception: return any errors or warnings in this structure.
157 MagickExport LinkedListInfo *AcquireMimeCache(const char *filename,
158 ExceptionInfo *exception)
166 cache=NewLinkedList(0);
167 if (cache == (LinkedListInfo *) NULL)
168 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
170 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
178 options=GetConfigureOptions(filename,exception);
179 option=(const StringInfo *) GetNextValueInLinkedList(options);
180 while (option != (const StringInfo *) NULL)
182 status&=LoadMimeCache(cache,(const char *)
183 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
184 option=(const StringInfo *) GetNextValueInLinkedList(options);
186 options=DestroyConfigureOptions(options);
189 if (IsLinkedListEmpty(cache) != MagickFalse)
190 status&=LoadMimeCache(cache,MimeMap,"built-in",0,exception);
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199 + G e t M i m e I n f o %
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 % GetMimeInfo() attempts to classify the content to identify which mime type
206 % is associated with the content, if any.
208 % The format of the GetMimeInfo method is:
210 % const MimeInfo *GetMimeInfo(const char *filename,
211 % const unsigned char *magic,const size_t length,
212 % ExceptionInfo *exception)
214 % A description of each parameter follows:
216 % o filename: If we cannot not classify the string, we attempt to classify
217 % based on the filename (e.g. *.pdf returns application/pdf).
219 % o magic: A binary string generally representing the first few characters
220 % of the image file or blob.
222 % o length: the length of the binary signature.
224 % o exception: return any errors or warnings in this structure.
227 MagickExport const MimeInfo *GetMimeInfo(const char *filename,
228 const unsigned char *magic,const size_t length,ExceptionInfo *exception)
236 register const MimeInfo
239 register const unsigned char
251 assert(exception != (ExceptionInfo *) NULL);
252 if (IsMimeCacheInstantiated(exception) == MagickFalse)
253 return((const MimeInfo *) NULL);
257 mime_info=(const MimeInfo *) NULL;
259 LockSemaphoreInfo(mime_semaphore);
260 ResetLinkedListIterator(mime_cache);
261 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
262 if ((magic == (const unsigned char *) NULL) || (length == 0))
264 UnlockSemaphoreInfo(mime_semaphore);
267 while (p != (const MimeInfo *) NULL)
269 assert(p->offset >= 0);
270 if (mime_info != (const MimeInfo *) NULL)
271 if (p->priority > mime_info->priority)
273 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
276 if ((p->pattern != (char *) NULL) && (filename != (char *) NULL))
278 if (GlobExpression(filename,p->pattern,MagickFalse) != MagickFalse)
280 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
283 switch (p->data_type)
287 if ((size_t) (p->offset+4) > length)
290 value=(ssize_t) (*q++);
293 if (p->value == value)
298 if ((p->value & p->mask) == value)
305 if ((size_t) (p->offset+4) > length)
309 if (p->endian == UndefinedEndian)
310 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
311 if (endian == LSBEndian)
313 value=(ssize_t) (*q++);
318 value=(ssize_t) (*q++) << 8;
323 if (p->value == value)
328 if ((p->value & p->mask) == value)
335 if ((size_t) (p->offset+4) > length)
339 if (p->endian == UndefinedEndian)
340 endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
341 if (endian == LSBEndian)
343 value=(ssize_t) (*q++);
344 value|=((ssize_t) *q++) << 8;
345 value|=((ssize_t) *q++) << 16;
346 value|=((ssize_t) *q++) << 24;
350 value=(ssize_t) (*q++) << 24;
351 value|=((ssize_t) *q++) << 16;
352 value|=((ssize_t) *q++) << 8;
353 value|=((ssize_t) *q++);
357 if (p->value == value)
362 if ((p->value & p->mask) == value)
370 for (i=0; i <= (ssize_t) p->extent; i++)
372 if ((size_t) (p->offset+i+p->length) > length)
374 if (memcmp(magic+p->offset+i,p->magic,p->length) == 0)
383 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
385 if (mime_info != (const MimeInfo *) NULL)
386 (void) InsertValueInLinkedList(mime_cache,0,
387 RemoveElementByValueFromLinkedList(mime_cache,p));
388 UnlockSemaphoreInfo(mime_semaphore);
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397 % G e t M i m e I n f o L i s t %
401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 % GetMimeInfoList() returns any image aliases that match the specified
406 % The magic of the GetMimeInfoList function is:
408 % const MimeInfo **GetMimeInfoList(const char *pattern,
409 % size_t *number_aliases,ExceptionInfo *exception)
411 % A description of each parameter follows:
413 % o pattern: Specifies a pointer to a text string containing a pattern.
415 % o number_aliases: This integer returns the number of magics in the
418 % o exception: return any errors or warnings in this structure.
422 #if defined(__cplusplus) || defined(c_plusplus)
426 static int MimeInfoCompare(const void *x,const void *y)
432 p=(const MimeInfo **) x,
433 q=(const MimeInfo **) y;
434 if (strcasecmp((*p)->path,(*q)->path) == 0)
435 return(strcasecmp((*p)->type,(*q)->type));
436 return(strcasecmp((*p)->path,(*q)->path));
439 #if defined(__cplusplus) || defined(c_plusplus)
443 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern,
444 size_t *number_aliases,ExceptionInfo *exception)
449 register const MimeInfo
458 assert(pattern != (char *) NULL);
459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
460 assert(number_aliases != (size_t *) NULL);
462 p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
463 if (p == (const MimeInfo *) NULL)
464 return((const MimeInfo **) NULL);
465 aliases=(const MimeInfo **) AcquireQuantumMemory((size_t)
466 GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
467 if (aliases == (const MimeInfo **) NULL)
468 return((const MimeInfo **) NULL);
472 LockSemaphoreInfo(mime_semaphore);
473 ResetLinkedListIterator(mime_cache);
474 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
475 for (i=0; p != (const MimeInfo *) NULL; )
477 if ((p->stealth == MagickFalse) &&
478 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
480 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
482 UnlockSemaphoreInfo(mime_semaphore);
483 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare);
484 aliases[i]=(MimeInfo *) NULL;
485 *number_aliases=(size_t) i;
490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 % G e t M i m e L i s t %
498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500 % GetMimeList() returns any image format alias that matches the specified
503 % The format of the GetMimeList function is:
505 % char **GetMimeList(const char *pattern,size_t *number_aliases,
506 % ExceptionInfo *exception)
508 % A description of each parameter follows:
510 % o pattern: Specifies a pointer to a text string containing a pattern.
512 % o number_aliases: This integer returns the number of image format aliases
515 % o exception: return any errors or warnings in this structure.
519 #if defined(__cplusplus) || defined(c_plusplus)
523 static int MimeCompare(const void *x,const void *y)
531 return(strcasecmp(p,q));
534 #if defined(__cplusplus) || defined(c_plusplus)
538 MagickExport char **GetMimeList(const char *pattern,
539 size_t *number_aliases,ExceptionInfo *exception)
544 register const MimeInfo
551 Allocate configure list.
553 assert(pattern != (char *) NULL);
554 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
555 assert(number_aliases != (size_t *) NULL);
557 p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
558 if (p == (const MimeInfo *) NULL)
559 return((char **) NULL);
560 aliases=(char **) AcquireQuantumMemory((size_t)
561 GetNumberOfElementsInLinkedList(mime_cache)+1UL,sizeof(*aliases));
562 if (aliases == (char **) NULL)
563 return((char **) NULL);
564 LockSemaphoreInfo(mime_semaphore);
565 ResetLinkedListIterator(mime_cache);
566 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
567 for (i=0; p != (const MimeInfo *) NULL; )
569 if ((p->stealth == MagickFalse) &&
570 (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
571 aliases[i++]=ConstantString(p->type);
572 p=(const MimeInfo *) GetNextValueInLinkedList(mime_cache);
574 UnlockSemaphoreInfo(mime_semaphore);
575 qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare);
576 aliases[i]=(char *) NULL;
577 *number_aliases=(size_t) i;
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 % G e t M i m e D e s c r i p t i o n %
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
592 % GetMimeDescription() returns the mime type description.
594 % The format of the GetMimeDescription method is:
596 % const char *GetMimeDescription(const MimeInfo *mime_info)
598 % A description of each parameter follows:
600 % o mime_info: The magic info.
603 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info)
605 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
606 assert(mime_info != (MimeInfo *) NULL);
607 assert(mime_info->signature == MagickCoreSignature);
608 return(mime_info->description);
612 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616 % G e t M i m e T y p e %
620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
622 % GetMimeType() returns the mime type.
624 % The format of the GetMimeType method is:
626 % const char *GetMimeType(const MimeInfo *mime_info)
628 % A description of each parameter follows:
630 % o mime_info: The magic info.
633 MagickExport const char *GetMimeType(const MimeInfo *mime_info)
635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
636 assert(mime_info != (MimeInfo *) NULL);
637 assert(mime_info->signature == MagickCoreSignature);
638 return(mime_info->type);
642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 + I s M i m e C a c h e I n s t a n t i a t e d %
650 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % IsMimeCacheInstantiated() determines if the mime list is instantiated. If
653 % not, it instantiates the list and returns it.
655 % The format of the IsMimeInstantiated method is:
657 % MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
659 % A description of each parameter follows.
661 % o exception: return any errors or warnings in this structure.
664 static MagickBooleanType IsMimeCacheInstantiated(ExceptionInfo *exception)
666 if (mime_cache == (LinkedListInfo *) NULL)
668 if (mime_semaphore == (SemaphoreInfo *) NULL)
669 ActivateSemaphoreInfo(&mime_semaphore);
670 LockSemaphoreInfo(mime_semaphore);
671 if (mime_cache == (LinkedListInfo *) NULL)
672 mime_cache=AcquireMimeCache(MimeFilename,exception);
673 UnlockSemaphoreInfo(mime_semaphore);
675 return(mime_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 % L i s t M i m e I n f o %
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 % ListMimeInfo() lists the magic info to a file.
691 % The format of the ListMimeInfo method is:
693 % MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
695 % A description of each parameter follows.
697 % o file: An pointer to a FILE.
699 % o exception: return any errors or warnings in this structure.
702 MagickExport MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
719 if (file == (const FILE *) NULL)
721 mime_info=GetMimeInfoList("*",&number_aliases,exception);
722 if (mime_info == (const MimeInfo **) NULL)
725 path=(const char *) NULL;
726 for (i=0; i < (ssize_t) number_aliases; i++)
728 if (mime_info[i]->stealth != MagickFalse)
730 if ((path == (const char *) NULL) ||
731 (strcasecmp(path,mime_info[i]->path) != 0))
733 if (mime_info[i]->path != (char *) NULL)
734 (void) FormatLocaleFile(file,"\nPath: %s\n\n",mime_info[i]->path);
735 (void) FormatLocaleFile(file,"Type Description\n");
736 (void) FormatLocaleFile(file,
737 "-------------------------------------------------"
738 "------------------------------\n");
740 path=mime_info[i]->path;
741 (void) FormatLocaleFile(file,"%s",mime_info[i]->type);
742 if (strlen(mime_info[i]->type) <= 25)
744 for (j=(ssize_t) strlen(mime_info[i]->type); j <= 27; j++)
745 (void) FormatLocaleFile(file," ");
749 (void) FormatLocaleFile(file,"\n");
750 for (j=0; j <= 27; j++)
751 (void) FormatLocaleFile(file," ");
753 if (mime_info[i]->description != (char *) NULL)
754 (void) FormatLocaleFile(file,"%s",mime_info[i]->description);
755 (void) FormatLocaleFile(file,"\n");
758 mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info);
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 + L o a d M i m e C a c h e %
771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
773 % LoadMimeCache() loads the mime configurations which provides a mapping
774 % between mime attributes and a mime name.
776 % The format of the LoadMimeCache method is:
778 % MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
779 % const char *filename,const size_t depth,ExceptionInfo *exception)
781 % A description of each parameter follows:
783 % o xml: The mime list in XML format.
785 % o filename: The mime list filename.
787 % o depth: depth of <include /> statements.
789 % o exception: return any errors or warnings in this structure.
792 static MagickBooleanType LoadMimeCache(LinkedListInfo *cache,const char *xml,
793 const char *filename,const size_t depth,ExceptionInfo *exception)
799 *mime_info = (MimeInfo *) NULL;
810 Load the mime map file.
812 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
813 "Loading mime map \"%s\" ...",filename);
814 if (xml == (const char *) NULL)
816 mime_map=NewXMLTree(xml,exception);
817 if (mime_map == (XMLTreeInfo *) NULL)
820 include=GetXMLTreeChild(mime_map,"include");
821 while (include != (XMLTreeInfo *) NULL)
824 Process include element.
826 attribute=GetXMLTreeAttribute(include,"file");
827 if (attribute != (const char *) NULL)
830 (void) ThrowMagickException(exception,GetMagickModule(),
831 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",filename);
835 path[MagickPathExtent],
838 GetPathComponent(filename,HeadPath,path);
840 (void) ConcatenateMagickString(path,DirectorySeparator,
842 if (*attribute == *DirectorySeparator)
843 (void) CopyMagickString(path,attribute,MagickPathExtent);
845 (void) ConcatenateMagickString(path,attribute,MagickPathExtent);
846 file_xml=FileToXML(path,~0UL);
847 if (file_xml != (char *) NULL)
849 status&=LoadMimeCache(cache,file_xml,path,depth+1,exception);
850 file_xml=DestroyString(file_xml);
854 include=GetNextXMLTreeTag(include);
856 mime=GetXMLTreeChild(mime_map,"mime");
857 while (mime != (XMLTreeInfo *) NULL)
860 Process mime element.
862 mime_info=(MimeInfo *) AcquireMagickMemory(sizeof(*mime_info));
863 if (mime_info == (MimeInfo *) NULL)
864 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
865 (void) ResetMagickMemory(mime_info,0,sizeof(*mime_info));
866 mime_info->path=ConstantString(filename);
867 mime_info->signature=MagickCoreSignature;
868 attribute=GetXMLTreeAttribute(mime,"data-type");
869 if (attribute != (const char *) NULL)
870 mime_info->data_type=(DataType) ParseCommandOption(MagickDataTypeOptions,
871 MagickTrue,attribute);
872 attribute=GetXMLTreeAttribute(mime,"description");
873 if (attribute != (const char *) NULL)
874 mime_info->description=ConstantString(attribute);
875 attribute=GetXMLTreeAttribute(mime,"endian");
876 if (attribute != (const char *) NULL)
877 mime_info->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
878 MagickTrue,attribute);
879 attribute=GetXMLTreeAttribute(mime,"magic");
880 if (attribute != (const char *) NULL)
888 register unsigned char
891 token=AcquireString(attribute);
892 (void) SubstituteString((char **) &token,"<","<");
893 (void) SubstituteString((char **) &token,"&","&");
894 (void) SubstituteString((char **) &token,""","\"");
895 mime_info->magic=(unsigned char *) AcquireString(token);
897 for (p=token; *p != '\0'; )
902 if (isdigit((int) ((unsigned char) *p)) != 0)
907 *q++=(unsigned char) strtol(p,&end,8);
914 case 'b': *q='\b'; break;
915 case 'f': *q='\f'; break;
916 case 'n': *q='\n'; break;
917 case 'r': *q='\r'; break;
918 case 't': *q='\t'; break;
919 case 'v': *q='\v'; break;
920 case 'a': *q='a'; break;
921 case '?': *q='\?'; break;
922 default: *q=(unsigned char) (*p); break;
929 *q++=(unsigned char) (*p++);
932 token=DestroyString(token);
933 if (mime_info->data_type != StringData)
934 mime_info->value=(ssize_t) strtoul((char *) mime_info->magic,
937 attribute=GetXMLTreeAttribute(mime,"mask");
938 if (attribute != (const char *) NULL)
939 mime_info->mask=(ssize_t) strtoul(attribute,(char **) NULL,0);
940 attribute=GetXMLTreeAttribute(mime,"offset");
941 if (attribute != (const char *) NULL)
946 mime_info->offset=(MagickOffsetType) strtol(attribute,&c,0);
948 mime_info->extent=(size_t) strtol(c+1,(char **) NULL,0);
950 attribute=GetXMLTreeAttribute(mime,"pattern");
951 if (attribute != (const char *) NULL)
952 mime_info->pattern=ConstantString(attribute);
953 attribute=GetXMLTreeAttribute(mime,"priority");
954 if (attribute != (const char *) NULL)
955 mime_info->priority=(ssize_t) strtol(attribute,(char **) NULL,0);
956 attribute=GetXMLTreeAttribute(mime,"stealth");
957 if (attribute != (const char *) NULL)
958 mime_info->stealth=IsStringTrue(attribute);
959 attribute=GetXMLTreeAttribute(mime,"type");
960 if (attribute != (const char *) NULL)
961 mime_info->type=ConstantString(attribute);
962 status=AppendValueToLinkedList(cache,mime_info);
963 if (status == MagickFalse)
964 (void) ThrowMagickException(exception,GetMagickModule(),
965 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
966 mime=GetNextXMLTreeTag(mime);
968 mime_map=DestroyXMLTree(mime_map);
969 return(status != 0 ? MagickTrue : MagickFalse);
973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 + M a g i c k T o M i m e %
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 % MagickToMime() returns the officially registered (or de facto) MIME
984 % media-type corresponding to a magick string. If there is no registered
985 % media-type, then the string "image/x-magick" (all lower case) is returned.
986 % The returned string must be deallocated by the user.
988 % The format of the MagickToMime method is:
990 % char *MagickToMime(const char *magick)
992 % A description of each parameter follows.
994 % o magick: ImageMagick format specification "magick" tag.
997 MagickExport char *MagickToMime(const char *magick)
1000 filename[MagickPathExtent],
1001 media[MagickPathExtent];
1009 (void) FormatLocaleString(filename,MagickPathExtent,"file.%s",magick);
1010 LocaleLower(filename);
1011 exception=AcquireExceptionInfo();
1012 mime_info=GetMimeInfo(filename,(unsigned char *) " ",1,exception);
1013 exception=DestroyExceptionInfo(exception);
1014 if (mime_info != (const MimeInfo *) NULL)
1015 return(ConstantString(GetMimeType(mime_info)));
1016 (void) FormatLocaleString(media,MagickPathExtent,"image/x-%s",magick);
1017 LocaleLower(media+8);
1018 return(ConstantString(media));
1022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1026 + M i m e C o m p o n e n t G e n e s i s %
1030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 % MimeComponentGenesis() instantiates the mime component.
1034 % The format of the MimeComponentGenesis method is:
1036 % MagickBooleanType MimeComponentGenesis(void)
1039 MagickPrivate MagickBooleanType MimeComponentGenesis(void)
1041 if (mime_semaphore == (SemaphoreInfo *) NULL)
1042 mime_semaphore=AcquireSemaphoreInfo();
1047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1051 + M i m e C o m p o n e n t T e r m i n u s %
1055 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1057 % MimeComponentTerminus() destroys the mime component.
1059 % The format of the MimeComponentTerminus method is:
1061 % MimeComponentTerminus(void)
1065 static void *DestroyMimeElement(void *mime_info)
1070 p=(MimeInfo *) mime_info;
1071 if (p->magic != (unsigned char *) NULL)
1072 p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
1073 if (p->pattern != (char *) NULL)
1074 p->pattern=DestroyString(p->pattern);
1075 if (p->description != (char *) NULL)
1076 p->description=DestroyString(p->description);
1077 if (p->type != (char *) NULL)
1078 p->type=DestroyString(p->type);
1079 if (p->path != (char *) NULL)
1080 p->path=DestroyString(p->path);
1081 p=(MimeInfo *) RelinquishMagickMemory(p);
1082 return((void *) NULL);
1085 MagickPrivate void MimeComponentTerminus(void)
1087 if (mime_semaphore == (SemaphoreInfo *) NULL)
1088 ActivateSemaphoreInfo(&mime_semaphore);
1089 LockSemaphoreInfo(mime_semaphore);
1090 if (mime_cache != (LinkedListInfo *) NULL)
1091 mime_cache=DestroyLinkedList(mime_cache,DestroyMimeElement);
1092 UnlockSemaphoreInfo(mime_semaphore);
1093 RelinquishSemaphoreInfo(&mime_semaphore);