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