mime.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                        M   M  IIIII  M   M  EEEEE                           %
00006 %                        MM MM    I    MM MM  E                               %
00007 %                        M M M    I    M M M  EEE                             %
00008 %                        M   M    I    M   M  E                               %
00009 %                        M   M  IIIII  M   M  EEEEE                           %
00010 %                                                                             %
00011 %                                                                             %
00012 %                          MagickCore Mime Methods                            %
00013 %                                                                             %
00014 %                              Software Design                                %
00015 %                                 July 2000                                   %
00016 %                                                                             %
00017 %                                                                             %
00018 %  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
00019 %  dedicated to making software imaging solutions freely available.           %
00020 %                                                                             %
00021 %  You may not use this file except in compliance with the License.  You may  %
00022 %  obtain a copy of the License at                                            %
00023 %                                                                             %
00024 %    http://www.imagemagick.org/MagicksToolkit/script/license.php             %
00025 %                                                                             %
00026 %  Unless required by applicable law or agreed to in writing, software        %
00027 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00028 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00029 %  See the License for the specific language governing permissions and        %
00030 %  limitations under the License.                                             %
00031 %                                                                             %
00032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00033 %
00034 %
00035 */
00036 
00037 /*
00038   Include declarations.
00039 */
00040 #include "magick/studio.h"
00041 #include "magick/blob.h"
00042 #include "magick/client.h"
00043 #include "magick/configure.h"
00044 #include "magick/exception.h"
00045 #include "magick/exception-private.h"
00046 #include "magick/hashmap.h"
00047 #include "magick/memory_.h"
00048 #include "magick/mime.h"
00049 #include "magick/mime-private.h"
00050 #include "magick/option.h"
00051 #include "magick/semaphore.h"
00052 #include "magick/string_.h"
00053 #include "magick/token.h"
00054 #include "magick/utility.h"
00055 #include "magick/xml-tree.h"
00056 
00057 /*
00058   Define declarations.
00059 */
00060 #define MimeFilename  "mime.xml"
00061 
00062 /*
00063   Typedef declaration.
00064 */
00065 struct _MimeInfo
00066 {
00067   char
00068     *path,
00069     *type,
00070     *description,
00071     *pattern;
00072 
00073   long
00074     priority;
00075 
00076   MagickOffsetType
00077     offset;
00078 
00079   size_t
00080     extent;
00081 
00082   DataType
00083     data_type;
00084 
00085   long
00086     mask,
00087     value;
00088 
00089   EndianType
00090     endian;
00091 
00092   size_t
00093     length;
00094 
00095   unsigned char
00096     *magic;
00097 
00098   MagickBooleanType
00099     stealth;
00100 
00101   unsigned long
00102     signature;
00103 };
00104 
00105 /*
00106   Static declarations.
00107 */
00108 static const char
00109   *MimeMap = (char *)
00110     "<?xml version=\"1.0\"?>"
00111     "<mimemap>"
00112     "</mimemap>";
00113 
00114 static LinkedListInfo
00115   *mime_list = (LinkedListInfo *) NULL;
00116 
00117 static SemaphoreInfo
00118   *mime_semaphore = (SemaphoreInfo *) NULL;
00119 
00120 static volatile MagickBooleanType
00121   instantiate_mime = MagickFalse;
00122 
00123 /*
00124   Forward declarations.
00125 */
00126 static MagickBooleanType
00127   InitializeMimeList(ExceptionInfo *);
00128 
00129 /*
00130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00131 %                                                                             %
00132 %                                                                             %
00133 %                                                                             %
00134 +   D e s t r o y M i m e L i s t                                             %
00135 %                                                                             %
00136 %                                                                             %
00137 %                                                                             %
00138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00139 %
00140 %  DestroyMimeList() deallocates memory associated with the mime list.
00141 %
00142 %  The format of the DestroyMimeList method is:
00143 %
00144 %      DestroyMimeList(void)
00145 %
00146 */
00147 
00148 static void *DestroyMimeElement(void *mime_info)
00149 {
00150   register MimeInfo
00151     *p;
00152 
00153   p=(MimeInfo *) mime_info;
00154   if (p->magic != (unsigned char *) NULL)
00155     p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
00156   if (p->pattern != (char *) NULL)
00157     p->pattern=DestroyString(p->pattern);
00158   if (p->description != (char *) NULL)
00159     p->description=DestroyString(p->description);
00160   if (p->type != (char *) NULL)
00161     p->type=DestroyString(p->type);
00162   if (p->path != (char *) NULL)
00163     p->path=DestroyString(p->path);
00164   p=(MimeInfo *) RelinquishMagickMemory(p);
00165   return((void *) NULL);
00166 }
00167 
00168 MagickExport void DestroyMimeList(void)
00169 {
00170   AcquireSemaphoreInfo(&mime_semaphore);
00171   if (mime_list != (LinkedListInfo *) NULL)
00172     mime_list=DestroyLinkedList(mime_list,DestroyMimeElement);
00173   instantiate_mime=MagickFalse;
00174   RelinquishSemaphoreInfo(mime_semaphore);
00175   DestroySemaphoreInfo(&mime_semaphore);
00176 }
00177 
00178 /*
00179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00180 %                                                                             %
00181 %                                                                             %
00182 %                                                                             %
00183 +   G e t M i m e I n f o                                                     %
00184 %                                                                             %
00185 %                                                                             %
00186 %                                                                             %
00187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00188 %
00189 %  GetMimeInfo() attempts to classify the content to identify which mime type
00190 %  is associated with the content, if any.
00191 %
00192 %  The format of the GetMimeInfo method is:
00193 %
00194 %      const MimeInfo *GetMimeInfo(const char *filename,
00195 %        const unsigned char *magic,const size_t length,
00196 %        ExceptionInfo *exception)
00197 %
00198 %  A description of each parameter follows:
00199 %
00200 %    o filename:  If we cannot not classify the string, we attempt to classify
00201 %      based on the filename (e.g. *.pdf returns application/pdf).
00202 %
00203 %    o magic: A binary string generally representing the first few characters
00204 %      of the image file or blob.
00205 %
00206 %    o length: the length of the binary signature.
00207 %
00208 %    o exception: return any errors or warnings in this structure.
00209 %
00210 */
00211 MagickExport const MimeInfo *GetMimeInfo(const char *filename,
00212   const unsigned char *magic,const size_t length,ExceptionInfo *exception)
00213 {
00214   const MimeInfo
00215     *mime_info;
00216 
00217   EndianType
00218     endian;
00219 
00220   long
00221     value;
00222 
00223   register const MimeInfo
00224     *p;
00225 
00226   register const unsigned char
00227     *q;
00228 
00229   register long
00230     i;
00231 
00232   unsigned long
00233     lsb_first;
00234 
00235   assert(exception != (ExceptionInfo *) NULL);
00236   if ((mime_list == (LinkedListInfo *) NULL) ||
00237       (instantiate_mime == MagickFalse))
00238     if (InitializeMimeList(exception) == MagickFalse)
00239       return((const MimeInfo *) NULL);
00240   if ((mime_list == (LinkedListInfo *) NULL) ||
00241       (IsLinkedListEmpty(mime_list) != MagickFalse))
00242     return((const MimeInfo *) NULL);
00243   if ((magic == (const unsigned char *) NULL) || (length == 0))
00244     return((const MimeInfo *) GetValueFromLinkedList(mime_list,0));
00245   if (length == 0)
00246     return((const MimeInfo *) NULL);
00247   /*
00248     Search for mime tag.
00249   */
00250   mime_info=(const MimeInfo *) NULL;
00251   lsb_first=1;
00252   AcquireSemaphoreInfo(&mime_semaphore);
00253   ResetLinkedListIterator(mime_list);
00254   p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00255   while (p != (const MimeInfo *) NULL)
00256   {
00257     assert(p->offset >= 0);
00258     if (mime_info != (const MimeInfo *) NULL)
00259       if (p->priority > mime_info->priority)
00260         {
00261           p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00262           continue;
00263         }
00264     if ((p->pattern != (char *) NULL) && (filename != (char *) NULL))
00265       {
00266         if (GlobExpression(filename,p->pattern,MagickFalse) != MagickFalse)
00267           mime_info=p;
00268         p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00269         continue;
00270       }
00271     switch (p->data_type)
00272     {
00273       case ByteData:
00274       {
00275         if ((size_t) (p->offset+4) > length)
00276           break;
00277         q=magic+p->offset;
00278         value=(*q++);
00279         if (p->mask == 0)
00280           {
00281             if (p->value == value)
00282               mime_info=p;
00283           }
00284         else
00285           {
00286             if ((p->value & p->mask) == value)
00287               mime_info=p;
00288           }
00289         break;
00290       }
00291       case ShortData:
00292       {
00293         if ((size_t) (p->offset+4) > length)
00294           break;
00295         q=magic+p->offset;
00296         endian=p->endian;
00297         if (p->endian == UndefinedEndian)
00298           endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
00299         if (endian == LSBEndian)
00300           {
00301             value=(*q++);
00302             value|=(*q++) << 8;
00303           }
00304         else
00305           {
00306             value=(*q++) << 8;
00307             value|=(*q++);
00308           }
00309         if (p->mask == 0)
00310           {
00311             if (p->value == value)
00312               mime_info=p;
00313           }
00314         else
00315           {
00316             if ((p->value & p->mask) == value)
00317               mime_info=p;
00318           }
00319         break;
00320       }
00321       case LongData:
00322       {
00323         if ((size_t) (p->offset+4) > length)
00324           break;
00325         q=magic+p->offset;
00326         endian=p->endian;
00327         if (p->endian == UndefinedEndian)
00328           endian=(*(char *) &lsb_first) == 1 ? LSBEndian : MSBEndian;
00329         if (endian == LSBEndian)
00330           {
00331             value=(*q++);
00332             value|=(*q++) << 8;
00333             value|=(*q++) << 16;
00334             value|=(*q++) << 24;
00335           }
00336         else
00337           {
00338             value=(*q++) << 24;
00339             value|=(*q++) << 16;
00340             value|=(*q++) << 8;
00341             value|=(*q++);
00342           }
00343         if (p->mask == 0)
00344           {
00345             if (p->value == value)
00346               mime_info=p;
00347           }
00348         else
00349           {
00350             if ((p->value & p->mask) == value)
00351               mime_info=p;
00352           }
00353         break;
00354       }
00355       case StringData:
00356       default:
00357       {
00358         for (i=0; i <= (long) p->extent; i++)
00359         {
00360           if ((size_t) (p->offset+i+p->length) > length)
00361             break;
00362           if (memcmp(magic+p->offset+i,p->magic,p->length) == 0)
00363             {
00364               mime_info=p;
00365               break;
00366             }
00367         }
00368         break;
00369       }
00370     }
00371     p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00372   }
00373   if (p != (const MimeInfo *) NULL)
00374     (void) InsertValueInLinkedList(mime_list,0,
00375       RemoveElementByValueFromLinkedList(mime_list,p));
00376   RelinquishSemaphoreInfo(mime_semaphore);
00377   return(mime_info);
00378 }
00379 
00380 /*
00381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00382 %                                                                             %
00383 %                                                                             %
00384 %                                                                             %
00385 %   G e t M i m e I n f o L i s t                                             %
00386 %                                                                             %
00387 %                                                                             %
00388 %                                                                             %
00389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00390 %
00391 %  GetMimeInfoList() returns any image aliases that match the specified
00392 %  pattern.
00393 %
00394 %  The magic of the GetMimeInfoList function is:
00395 %
00396 %      const MimeInfo **GetMimeInfoList(const char *pattern,
00397 %        unsigned long *number_aliases,ExceptionInfo *exception)
00398 %
00399 %  A description of each parameter follows:
00400 %
00401 %    o pattern: Specifies a pointer to a text string containing a pattern.
00402 %
00403 %    o number_aliases:  This integer returns the number of magics in the
00404 %      list.
00405 %
00406 %    o exception: return any errors or warnings in this structure.
00407 %
00408 */
00409 
00410 #if defined(__cplusplus) || defined(c_plusplus)
00411 extern "C" {
00412 #endif
00413 
00414 static int MimeInfoCompare(const void *x,const void *y)
00415 {
00416   const MimeInfo
00417     **p,
00418     **q;
00419 
00420   p=(const MimeInfo **) x,
00421   q=(const MimeInfo **) y;
00422   if (strcasecmp((*p)->path,(*q)->path) == 0)
00423     return(strcasecmp((*p)->type,(*q)->type));
00424   return(strcasecmp((*p)->path,(*q)->path));
00425 }
00426 
00427 #if defined(__cplusplus) || defined(c_plusplus)
00428 }
00429 #endif
00430 
00431 MagickExport const MimeInfo **GetMimeInfoList(const char *pattern,
00432   unsigned long *number_aliases,ExceptionInfo *exception)
00433 {
00434   const MimeInfo
00435     **aliases;
00436 
00437   register const MimeInfo
00438     *p;
00439 
00440   register long
00441     i;
00442 
00443   /*
00444     Allocate mime list.
00445   */
00446   assert(pattern != (char *) NULL);
00447   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00448   assert(number_aliases != (unsigned long *) NULL);
00449   *number_aliases=0;
00450   p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
00451   if (p == (const MimeInfo *) NULL)
00452     return((const MimeInfo **) NULL);
00453   aliases=(const MimeInfo **) AcquireQuantumMemory((size_t)
00454     GetNumberOfElementsInLinkedList(mime_list)+1UL,sizeof(*aliases));
00455   if (aliases == (const MimeInfo **) NULL)
00456     return((const MimeInfo **) NULL);
00457   /*
00458     Generate mime list.
00459   */
00460   AcquireSemaphoreInfo(&mime_semaphore);
00461   ResetLinkedListIterator(mime_list);
00462   p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00463   for (i=0; p != (const MimeInfo *) NULL; )
00464   {
00465     if ((p->stealth == MagickFalse) &&
00466         (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
00467       aliases[i++]=p;
00468     p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00469   }
00470   RelinquishSemaphoreInfo(mime_semaphore);
00471   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeInfoCompare);
00472   aliases[i]=(MimeInfo *) NULL;
00473   *number_aliases=(unsigned long) i;
00474   return(aliases);
00475 }
00476 
00477 /*
00478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00479 %                                                                             %
00480 %                                                                             %
00481 %                                                                             %
00482 %   G e t M i m e L i s t                                                     %
00483 %                                                                             %
00484 %                                                                             %
00485 %                                                                             %
00486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00487 %
00488 %  GetMimeList() returns any image format aliases that match the specified
00489 %  pattern.
00490 %
00491 %  The format of the GetMimeList function is:
00492 %
00493 %      char **GetMimeList(const char *pattern,unsigned long *number_aliases,
00494 %        ExceptionInfo *exception)
00495 %
00496 %  A description of each parameter follows:
00497 %
00498 %    o pattern: Specifies a pointer to a text string containing a pattern.
00499 %
00500 %    o number_aliases:  This integer returns the number of image format aliases
00501 %      in the list.
00502 %
00503 %    o exception: return any errors or warnings in this structure.
00504 %
00505 */
00506 
00507 #if defined(__cplusplus) || defined(c_plusplus)
00508 extern "C" {
00509 #endif
00510 
00511 static int MimeCompare(const void *x,const void *y)
00512 {
00513   register char
00514     *p,
00515     *q;
00516 
00517   p=(char *) x;
00518   q=(char *) y;
00519   return(strcasecmp(p,q));
00520 }
00521 
00522 #if defined(__cplusplus) || defined(c_plusplus)
00523 }
00524 #endif
00525 
00526 MagickExport char **GetMimeList(const char *pattern,
00527   unsigned long *number_aliases,ExceptionInfo *exception)
00528 {
00529   char
00530     **aliases;
00531 
00532   register const MimeInfo
00533     *p;
00534 
00535   register long
00536     i;
00537 
00538   /*
00539     Allocate configure list.
00540   */
00541   assert(pattern != (char *) NULL);
00542   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00543   assert(number_aliases != (unsigned long *) NULL);
00544   *number_aliases=0;
00545   p=GetMimeInfo((char *) NULL,(unsigned char *) "*",0,exception);
00546   if (p == (const MimeInfo *) NULL)
00547     return((char **) NULL);
00548   aliases=(char **) AcquireQuantumMemory((size_t)
00549     GetNumberOfElementsInLinkedList(mime_list)+1UL,sizeof(*aliases));
00550   if (aliases == (char **) NULL)
00551     return((char **) NULL);
00552   AcquireSemaphoreInfo(&mime_semaphore);
00553   ResetLinkedListIterator(mime_list);
00554   p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00555   for (i=0; p != (const MimeInfo *) NULL; )
00556   {
00557     if ((p->stealth == MagickFalse) &&
00558         (GlobExpression(p->type,pattern,MagickFalse) != MagickFalse))
00559       aliases[i++]=ConstantString(p->type);
00560     p=(const MimeInfo *) GetNextValueInLinkedList(mime_list);
00561   }
00562   RelinquishSemaphoreInfo(mime_semaphore);
00563   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MimeCompare);
00564   aliases[i]=(char *) NULL;
00565   *number_aliases=(unsigned long) i;
00566   return(aliases);
00567 }
00568 
00569 /*
00570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00571 %                                                                             %
00572 %                                                                             %
00573 %                                                                             %
00574 %   G e t M i m e D e s c r i p t i o n                                       %
00575 %                                                                             %
00576 %                                                                             %
00577 %                                                                             %
00578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00579 %
00580 %  GetMimeDescription() returns the mime type description.
00581 %
00582 %  The format of the GetMimeDescription method is:
00583 %
00584 %      const char *GetMimeDescription(const MimeInfo *mime_info)
00585 %
00586 %  A description of each parameter follows:
00587 %
00588 %    o mime_info:  The magic info.
00589 %
00590 */
00591 MagickExport const char *GetMimeDescription(const MimeInfo *mime_info)
00592 {
00593   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00594   assert(mime_info != (MimeInfo *) NULL);
00595   assert(mime_info->signature == MagickSignature);
00596   return(mime_info->description);
00597 }
00598 
00599 /*
00600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00601 %                                                                             %
00602 %                                                                             %
00603 %                                                                             %
00604 %   G e t M i m e T y p e                                                     %
00605 %                                                                             %
00606 %                                                                             %
00607 %                                                                             %
00608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00609 %
00610 %  GetMimeType() returns the mime type.
00611 %
00612 %  The format of the GetMimeType method is:
00613 %
00614 %      const char *GetMimeType(const MimeInfo *mime_info)
00615 %
00616 %  A description of each parameter follows:
00617 %
00618 %    o mime_info:  The magic info.
00619 %
00620 */
00621 MagickExport const char *GetMimeType(const MimeInfo *mime_info)
00622 {
00623   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00624   assert(mime_info != (MimeInfo *) NULL);
00625   assert(mime_info->signature == MagickSignature);
00626   return(mime_info->type);
00627 }
00628 
00629 /*
00630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00631 %                                                                             %
00632 %                                                                             %
00633 %                                                                             %
00634 +   I n i t i a l i z e M i m e L i s t                                       %
00635 %                                                                             %
00636 %                                                                             %
00637 %                                                                             %
00638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00639 %
00640 %  InitializeMimeList() initializes the mime list.
00641 %
00642 %  The format of the InitializeMimeList method is:
00643 %
00644 %      MagickBooleanType InitializeMimeList(ExceptionInfo *exception)
00645 %
00646 %  A description of each parameter follows.
00647 %
00648 %    o exception: return any errors or warnings in this structure.
00649 %
00650 */
00651 static MagickBooleanType InitializeMimeList(ExceptionInfo *exception)
00652 {
00653   if ((mime_list == (LinkedListInfo *) NULL) &&
00654       (instantiate_mime == MagickFalse))
00655     {
00656       AcquireSemaphoreInfo(&mime_semaphore);
00657       if ((mime_list == (LinkedListInfo *) NULL) &&
00658           (instantiate_mime == MagickFalse))
00659         {
00660           (void) LoadMimeLists(MimeFilename,exception);
00661           instantiate_mime=MagickTrue;
00662         }
00663       RelinquishSemaphoreInfo(mime_semaphore);
00664     }
00665   return(mime_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
00666 }
00667 
00668 /*
00669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00670 %                                                                             %
00671 %                                                                             %
00672 %                                                                             %
00673 %  L i s t M i m e I n f o                                                    %
00674 %                                                                             %
00675 %                                                                             %
00676 %                                                                             %
00677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00678 %
00679 %  ListMimeInfo() lists the magic info to a file.
00680 %
00681 %  The format of the ListMimeInfo method is:
00682 %
00683 %      MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
00684 %
00685 %  A description of each parameter follows.
00686 %
00687 %    o file:  An pointer to a FILE.
00688 %
00689 %    o exception: return any errors or warnings in this structure.
00690 %
00691 */
00692 MagickExport MagickBooleanType ListMimeInfo(FILE *file,ExceptionInfo *exception)
00693 {
00694   const char
00695     *path;
00696 
00697   const MimeInfo
00698     **mime_info;
00699 
00700   long
00701     j;
00702 
00703   register long
00704     i;
00705 
00706   unsigned long
00707     number_aliases;
00708 
00709   if (file == (const FILE *) NULL)
00710     file=stdout;
00711   mime_info=GetMimeInfoList("*",&number_aliases,exception);
00712   if (mime_info == (const MimeInfo **) NULL)
00713     return(MagickFalse);
00714   j=0;
00715   path=(const char *) NULL;
00716   for (i=0; i < (long) number_aliases; i++)
00717   {
00718     if (mime_info[i]->stealth != MagickFalse)
00719       continue;
00720     if ((path == (const char *) NULL) ||
00721         (strcasecmp(path,mime_info[i]->path) != 0))
00722       {
00723         if (mime_info[i]->path != (char *) NULL)
00724           (void) fprintf(file,"\nPath: %s\n\n",mime_info[i]->path);
00725         (void) fprintf(file,"Type                   Description\n");
00726         (void) fprintf(file,"-------------------------------------------------"
00727           "------------------------------\n");
00728       }
00729     path=mime_info[i]->path;
00730     (void) fprintf(file,"%s",mime_info[i]->type);
00731     if (strlen(mime_info[i]->type) <= 25)
00732       {
00733         for (j=(long) strlen(mime_info[i]->type); j <= 27; j++)
00734           (void) fprintf(file," ");
00735       }
00736     else
00737       {
00738         (void) fprintf(file,"\n");
00739         for (j=0; j <= 27; j++)
00740           (void) fprintf(file," ");
00741       }
00742     if (mime_info[i]->description != (char *) NULL)
00743       (void) fprintf(file,"%s",mime_info[i]->description);
00744     (void) fprintf(file,"\n");
00745   }
00746   (void) fflush(file);
00747   mime_info=(const MimeInfo **) RelinquishMagickMemory((void *) mime_info);
00748   return(MagickTrue);
00749 }
00750 
00751 /*
00752 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00753 %                                                                             %
00754 %                                                                             %
00755 %                                                                             %
00756 +   L o a d M i m e L i s t                                                   %
00757 %                                                                             %
00758 %                                                                             %
00759 %                                                                             %
00760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00761 %
00762 %  LoadMimeList() loads the magic configuration file which provides a mapping
00763 %  between magic attributes and a magic name.
00764 %
00765 %  The format of the LoadMimeList method is:
00766 %
00767 %      MagickBooleanType LoadMimeList(const char *xml,const char *filename,
00768 %        const unsigned long depth,ExceptionInfo *exception)
00769 %
00770 %  A description of each parameter follows:
00771 %
00772 %    o xml:  The mime list in XML format.
00773 %
00774 %    o filename:  The mime list filename.
00775 %
00776 %    o depth: depth of <include /> statements.
00777 %
00778 %    o exception: return any errors or warnings in this structure.
00779 %
00780 */
00781 static MagickBooleanType LoadMimeList(const char *xml,const char *filename,
00782   const unsigned long depth,ExceptionInfo *exception)
00783 {
00784   const char
00785     *attribute;
00786 
00787   MimeInfo
00788     *mime_info = (MimeInfo *) NULL;
00789 
00790   MagickBooleanType
00791     status;
00792 
00793   XMLTreeInfo
00794     *mime,
00795     *mime_map,
00796     *include;
00797 
00798   /*
00799     Load the mime map file.
00800   */
00801   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00802     "Loading mime map \"%s\" ...",filename);
00803   if (xml == (const char *) NULL)
00804     return(MagickFalse);
00805   if (mime_list == (LinkedListInfo *) NULL)
00806     {
00807       mime_list=NewLinkedList(0);
00808       if (mime_list == (LinkedListInfo *) NULL)
00809         {
00810           ThrowFileException(exception,ResourceLimitError,
00811             "MemoryAllocationFailed",filename);
00812           return(MagickFalse);
00813         }
00814     }
00815   mime_map=NewXMLTree(xml,exception);
00816   if (mime_map == (XMLTreeInfo *) NULL)
00817     return(MagickFalse);
00818   status=MagickTrue;
00819   include=GetXMLTreeChild(mime_map,"include");
00820   while (include != (XMLTreeInfo *) NULL)
00821   {
00822     /*
00823       Process include element.
00824     */
00825     attribute=GetXMLTreeAttribute(include,"file");
00826     if (attribute != (const char *) NULL)
00827       {
00828         if (depth > 200)
00829           (void) ThrowMagickException(exception,GetMagickModule(),
00830             ConfigureError,"IncludeElementNestedTooDeeply","`%s'",filename);
00831         else
00832           {
00833             char
00834               path[MaxTextExtent],
00835               *xml;
00836 
00837             GetPathComponent(filename,HeadPath,path);
00838             if (*path != '\0')
00839               (void) ConcatenateMagickString(path,DirectorySeparator,
00840                 MaxTextExtent);
00841             (void) ConcatenateMagickString(path,attribute,MaxTextExtent);
00842             xml=FileToString(path,~0,exception);
00843             if (xml != (char *) NULL)
00844               {
00845                 status=LoadMimeList(xml,path,depth+1,exception);
00846                 xml=DestroyString(xml);
00847               }
00848           }
00849       }
00850     include=GetNextXMLTreeTag(include);
00851   }
00852   mime=GetXMLTreeChild(mime_map,"mime");
00853   while (mime != (XMLTreeInfo *) NULL)
00854   {
00855     const char
00856       *attribute;
00857 
00858     /*
00859       Process mime element.
00860     */
00861     mime_info=(MimeInfo *) AcquireMagickMemory(sizeof(*mime_info));
00862     if (mime_info == (MimeInfo *) NULL)
00863       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00864     (void) ResetMagickMemory(mime_info,0,sizeof(*mime_info));
00865     mime_info->path=ConstantString(filename);
00866     mime_info->signature=MagickSignature;
00867     attribute=GetXMLTreeAttribute(mime,"data-type");
00868     if (attribute != (const char *) NULL)
00869       mime_info->data_type=(DataType) ParseMagickOption(MagickDataTypeOptions,
00870         MagickTrue,attribute);
00871     attribute=GetXMLTreeAttribute(mime,"description");
00872     if (attribute != (const char *) NULL)
00873       mime_info->description=ConstantString(attribute);
00874     attribute=GetXMLTreeAttribute(mime,"endian");
00875     if (attribute != (const char *) NULL)
00876       mime_info->endian=(EndianType) ParseMagickOption(MagickEndianOptions,
00877         MagickTrue,attribute);
00878     attribute=GetXMLTreeAttribute(mime,"magic");
00879     if (attribute != (const char *) NULL)
00880       {
00881         char
00882           *token;
00883 
00884         const char
00885           *p;
00886 
00887         register unsigned char
00888           *q;
00889 
00890         token=AcquireString(attribute);
00891         (void) SubstituteString((char **) &token,"&lt;","<");
00892         (void) SubstituteString((char **) &token,"&amp;","&");
00893         (void) SubstituteString((char **) &token,"&quot;","\"");
00894         mime_info->magic=(unsigned char *) AcquireString(token);
00895         q=mime_info->magic;
00896         for (p=token; *p != '\0'; )
00897         {
00898           if (*p == '\\')
00899             {
00900               p++;
00901               if (isdigit((int) ((unsigned char) *p)) != 0)
00902                 {
00903                   char
00904                     *end;
00905 
00906                   *q++=(unsigned char) strtol(p,&end,8);
00907                   p+=(end-p);
00908                   mime_info->length++;
00909                   continue;
00910                 }
00911               switch (*p)
00912               {
00913                 case 'b': *q='\b'; break;
00914                 case 'f': *q='\f'; break;
00915                 case 'n': *q='\n'; break;
00916                 case 'r': *q='\r'; break;
00917                 case 't': *q='\t'; break;
00918                 case 'v': *q='\v'; break;
00919                 case 'a': *q='a'; break;
00920                 case '?': *q='\?'; break;
00921                 default: *q=(unsigned char) (*p); break;
00922               }
00923               p++;
00924               q++;
00925               mime_info->length++;
00926               continue;
00927             }
00928           *q++=(unsigned char) (*p++);
00929           mime_info->length++;
00930         }
00931         token=DestroyString(token);
00932         if (mime_info->data_type != StringData)
00933           mime_info->value=strtol((char *) mime_info->magic,(char **) NULL,0);
00934       }
00935     attribute=GetXMLTreeAttribute(mime,"mask");
00936     if (attribute != (const char *) NULL)
00937       mime_info->mask=strtol(attribute,(char **) NULL,0);
00938     attribute=GetXMLTreeAttribute(mime,"offset");
00939     if (attribute != (const char *) NULL)
00940       {
00941         char
00942           *c;
00943 
00944         mime_info->offset=(MagickOffsetType) strtol(attribute,&c,0);
00945         if (*c == ':')
00946           mime_info->extent=(size_t) strtol(c+1,(char **) NULL,0);
00947       }
00948     attribute=GetXMLTreeAttribute(mime,"pattern");
00949     if (attribute != (const char *) NULL)
00950       mime_info->pattern=ConstantString(attribute);
00951     attribute=GetXMLTreeAttribute(mime,"priority");
00952     if (attribute != (const char *) NULL)
00953       mime_info->priority=strtol(attribute,(char **) NULL,0);
00954     attribute=GetXMLTreeAttribute(mime,"stealth");
00955     if (attribute != (const char *) NULL)
00956       mime_info->stealth=IsMagickTrue(attribute);
00957     attribute=GetXMLTreeAttribute(mime,"type");
00958     if (attribute != (const char *) NULL)
00959       mime_info->type=ConstantString(attribute);
00960     status=AppendValueToLinkedList(mime_list,mime_info);
00961     if (status == MagickFalse)
00962       (void) ThrowMagickException(exception,GetMagickModule(),
00963         ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
00964     mime=GetNextXMLTreeTag(mime);
00965   }
00966   mime_map=DestroyXMLTree(mime_map);
00967   return(status);
00968 }
00969 
00970 /*
00971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00972 %                                                                             %
00973 %                                                                             %
00974 %                                                                             %
00975 %  L o a d M i m e L i s t s                                                  %
00976 %                                                                             %
00977 %                                                                             %
00978 %                                                                             %
00979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00980 %
00981 %  LoadMimeList() loads one or more magic configuration file which provides a
00982 %  mapping between magic attributes and a magic name.
00983 %
00984 %  The format of the LoadMimeLists method is:
00985 %
00986 %      MagickBooleanType LoadMimeLists(const char *filename,
00987 %        ExceptionInfo *exception)
00988 %
00989 %  A description of each parameter follows:
00990 %
00991 %    o filename: the font file name.
00992 %
00993 %    o exception: return any errors or warnings in this structure.
00994 %
00995 */
00996 MagickExport MagickBooleanType LoadMimeLists(const char *filename,
00997   ExceptionInfo *exception)
00998 {
00999 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
01000   return(LoadMimeList(MimeMap,"built-in",0,exception));
01001 #else
01002   const StringInfo
01003     *option;
01004 
01005   LinkedListInfo
01006     *options;
01007 
01008   MagickStatusType
01009     status;
01010 
01011   status=MagickFalse;
01012   options=GetConfigureOptions(filename,exception);
01013   option=(const StringInfo *) GetNextValueInLinkedList(options);
01014   while (option != (const StringInfo *) NULL)
01015   {
01016     status|=LoadMimeList((const char *) GetStringInfoDatum(option),
01017       GetStringInfoPath(option),0,exception);
01018     option=(const StringInfo *) GetNextValueInLinkedList(options);
01019   }
01020   options=DestroyConfigureOptions(options);
01021   if ((mime_list == (LinkedListInfo *) NULL) || 
01022       (IsLinkedListEmpty(mime_list) != MagickFalse))
01023     status|=LoadMimeList(MimeMap,"built-in",0,exception);
01024   else
01025     ClearMagickException(exception);
01026   return(status != 0 ? MagickTrue : MagickFalse);
01027 #endif
01028 }
01029 
01030 /*
01031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01032 %                                                                             %
01033 %                                                                             %
01034 %                                                                             %
01035 +  M a g i c k T o M i m e                                                    %
01036 %                                                                             %
01037 %                                                                             %
01038 %                                                                             %
01039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01040 %
01041 %  MagickToMime() returns the officially registered (or de facto) MIME
01042 %  media-type corresponding to a magick string.  If there is no registered
01043 %  media-type, then the string "image/x-magick" (all lower case) is returned.
01044 %  The returned string must be deallocated by the user.
01045 %
01046 %  The format of the MagickToMime method is:
01047 %
01048 %      char *MagickToMime(const char *magick)
01049 %
01050 %  A description of each parameter follows.
01051 %
01052 %   o  magick:  ImageMagick format specification "magick" tag.
01053 %
01054 */
01055 MagickExport char *MagickToMime(const char *magick)
01056 {
01057   char
01058     filename[MaxTextExtent],
01059     media[MaxTextExtent];
01060 
01061   const MimeInfo
01062     *mime_info;