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