MagickCore  6.7.5
magic.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                    M   M   AAA    GGGG  IIIII   CCCC                        %
00007 %                    MM MM  A   A  G        I    C                            %
00008 %                    M M M  AAAAA  G GGG    I    C                            %
00009 %                    M   M  A   A  G   G    I    C                            %
00010 %                    M   M  A   A   GGGG  IIIII   CCCC                        %
00011 %                                                                             %
00012 %                                                                             %
00013 %                      MagickCore Image Magic Methods                         %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                              Bob Friesenhahn                                %
00017 %                                 July 2000                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "MagickCore/studio.h"
00043 #include "MagickCore/blob.h"
00044 #include "MagickCore/client.h"
00045 #include "MagickCore/configure.h"
00046 #include "MagickCore/configure-private.h"
00047 #include "MagickCore/exception.h"
00048 #include "MagickCore/exception-private.h"
00049 #include "MagickCore/hashmap.h"
00050 #include "MagickCore/magic.h"
00051 #include "MagickCore/magic-private.h"
00052 #include "MagickCore/memory_.h"
00053 #include "MagickCore/semaphore.h"
00054 #include "MagickCore/string_.h"
00055 #include "MagickCore/string-private.h"
00056 #include "MagickCore/token.h"
00057 #include "MagickCore/utility.h"
00058 #include "MagickCore/utility-private.h"
00059 #include "MagickCore/xml-tree.h"
00060 
00061 /*
00062   Define declarations.
00063 */
00064 #define MagicFilename  "magic.xml"
00065 #define MagickString(magic)  (const unsigned char *) (magic), sizeof(magic)-1
00066 
00067 /*
00068   Typedef declarations.
00069 */
00070 typedef struct _MagicMapInfo
00071 {
00072   const char
00073     *name;
00074 
00075   const MagickOffsetType
00076     offset;
00077 
00078   const unsigned char
00079     *magic;
00080 
00081   const size_t
00082     length;
00083 } MagicMapInfo;
00084 
00085 /*
00086   Static declarations.
00087 */
00088 static const MagicMapInfo
00089   MagicMap[] =
00090   {
00091     { "8BIMWTEXT", 0, MagickString("8\000B\000I\000M\000#") },
00092     { "8BIMTEXT", 0, MagickString("8BIM#") },
00093     { "8BIM", 0, MagickString("8BIM") },
00094     { "BMP", 0, MagickString("BA") },
00095     { "BMP", 0, MagickString("BM") },
00096     { "BMP", 0, MagickString("CI") },
00097     { "BMP", 0, MagickString("CP") },
00098     { "BMP", 0, MagickString("IC") },
00099     { "BMP", 0, MagickString("PI") },
00100     { "CALS", 21, MagickString("version: MIL-STD-1840") },
00101     { "CALS", 0, MagickString("srcdocid:") },
00102     { "CALS", 9, MagickString("srcdocid:") },
00103     { "CALS", 8, MagickString("rorient:") },
00104     { "CGM", 0, MagickString("BEGMF") },
00105     { "CIN", 0, MagickString("\200\052\137\327") },
00106     { "CRW", 0, MagickString("II\x1a\x00\x00\x00HEAPCCDR") },
00107     { "DCM", 128, MagickString("DICM") },
00108     { "DCX", 0, MagickString("\261\150\336\72") },
00109     { "DIB", 0, MagickString("\050\000") },
00110     { "DDS", 0, MagickString("DDS ") },
00111     { "DJVU", 0, MagickString("AT&TFORM") },
00112     { "DOT", 0, MagickString("digraph") },
00113     { "DPX", 0, MagickString("SDPX") },
00114     { "DPX", 0, MagickString("XPDS") },
00115     { "EMF", 40, MagickString("\040\105\115\106\000\000\001\000") },
00116     { "EPT", 0, MagickString("\305\320\323\306") },
00117     { "EXR", 0, MagickString("\166\057\061\001") },
00118     { "FAX", 0, MagickString("DFAX") },
00119     { "FIG", 0, MagickString("#FIG") },
00120     { "FITS", 0, MagickString("IT0") },
00121     { "FITS", 0, MagickString("SIMPLE") },
00122     { "FPX", 0, MagickString("\320\317\021\340") },
00123     { "GIF", 0, MagickString("GIF8") },
00124     { "GPLT", 0, MagickString("#!/usr/local/bin/gnuplot") },
00125     { "HDF", 1, MagickString("HDF") },
00126     { "HDR", 0, MagickString("#?RADIANCE") },
00127     { "HDR", 0, MagickString("#?RGBE") },
00128     { "HPGL", 0, MagickString("IN;") },
00129     { "HTML", 1, MagickString("HTML") },
00130     { "HTML", 1, MagickString("html") },
00131     { "ILBM", 8, MagickString("ILBM") },
00132     { "IPTCWTEXT", 0, MagickString("\062\000#\000\060\000=\000\042\000&\000#\000\060\000;\000&\000#\000\062\000;\000\042\000") },
00133     { "IPTCTEXT", 0, MagickString("2#0=\042�\042") },
00134     { "IPTC", 0, MagickString("\034\002") },
00135     { "JNG", 0, MagickString("\213JNG\r\n\032\n") },
00136     { "JPEG", 0, MagickString("\377\330\377") },
00137     { "JPC", 0, MagickString("\377\117") },
00138     { "JP2", 4, MagickString("\152\120\040\040\015") },
00139     { "MAT", 0, MagickString("MATLAB 5.0 MAT-file,") },
00140     { "MIFF", 0, MagickString("Id=ImageMagick") },
00141     { "MIFF", 0, MagickString("id=ImageMagick") },
00142     { "MNG", 0, MagickString("\212MNG\r\n\032\n") },
00143     { "MPC", 0, MagickString("id=MagickCache") },
00144     { "MPEG", 0, MagickString("\000\000\001\263") },
00145     { "MRW", 0, MagickString("\x00MRM") },
00146     { "MVG", 0, MagickString("push graphic-context") },
00147     { "ORF", 0, MagickString("IIRO\x08\x00\x00\x00") },
00148     { "PCD", 2048, MagickString("PCD_") },
00149     { "PCL", 0, MagickString("\033E\033") },
00150     { "PCX", 0, MagickString("\012\002") },
00151     { "PCX", 0, MagickString("\012\005") },
00152     { "PDB", 60, MagickString("vIMGView") },
00153     { "PDF", 0, MagickString("%PDF-") },
00154     { "PES", 0, MagickString("#PES") },
00155     { "PFA", 0, MagickString("%!PS-AdobeFont-1.0") },
00156     { "PFB", 6, MagickString("%!PS-AdobeFont-1.0") },
00157     { "PGX", 0, MagickString("\050\107\020\115\046") },
00158     { "PICT", 522, MagickString("\000\021\002\377\014\000") },
00159     { "PNG", 0, MagickString("\211PNG\r\n\032\n") },
00160     { "PBM", 0, MagickString("P1") },
00161     { "PGM", 0, MagickString("P2") },
00162     { "PPM", 0, MagickString("P3") },
00163     { "PBM", 0, MagickString("P4") },
00164     { "PGM", 0, MagickString("P5") },
00165     { "PPM", 0, MagickString("P6") },
00166     { "PAM", 0, MagickString("P7") },
00167     { "PFM", 0, MagickString("PF") },
00168     { "PFM", 0, MagickString("Pf") },
00169     { "PS", 0, MagickString("%!") },
00170     { "PS", 0, MagickString("\004%!") },
00171     { "PS", 0, MagickString("\305\320\323\306") },
00172     { "PSB", 0, MagickString("8BPB") },
00173     { "PSD", 0, MagickString("8BPS") },
00174     { "PWP", 0, MagickString("SFW95") },
00175     { "RAF", 0, MagickString("FUJIFILMCCD-RAW ") },
00176     { "RLE", 0, MagickString("\122\314") },
00177     { "SCT", 0, MagickString("CT") },
00178     { "SFW", 0, MagickString("SFW94") },
00179     { "SGI", 0, MagickString("\001\332") },
00180     { "SUN", 0, MagickString("\131\246\152\225") },
00181     { "SVG", 1, MagickString("?XML") },
00182     { "SVG", 1, MagickString("?xml") },
00183     { "TIFF", 0, MagickString("\115\115\000\052") },
00184     { "TIFF", 0, MagickString("\111\111\052\000") },
00185     { "TIFF64", 0, MagickString("\115\115\000\053\000\010\000\000") },
00186     { "TIFF64", 0, MagickString("\111\111\053\000\010\000\000\000") },
00187     { "TXT", 0, MagickString("# ImageMagick pixel enumeration:") },
00188     { "VICAR", 0, MagickString("LBLSIZE") },
00189     { "VICAR", 0, MagickString("NJPL1I") },
00190     { "VIFF", 0, MagickString("\253\001") },
00191     { "WEBP", 8, MagickString("WEBP") },
00192     { "WMF", 0, MagickString("\327\315\306\232") },
00193     { "WMF", 0, MagickString("\001\000\011\000") },
00194     { "WPG", 0, MagickString("\377WPC") },
00195     { "XBM", 0, MagickString("#define") },
00196     { "XCF", 0, MagickString("gimp xcf") },
00197     { "XEF", 0, MagickString("FOVb") },
00198     { "XPM", 1, MagickString("* XPM *") },
00199     { "XWD", 4, MagickString("\007\000\000") },
00200     { "XWD", 5, MagickString("\000\000\007") }
00201  };
00202 
00203 static LinkedListInfo
00204   *magic_list = (LinkedListInfo *) NULL;
00205 
00206 static SemaphoreInfo
00207   *magic_semaphore = (SemaphoreInfo *) NULL;
00208 
00209 static volatile MagickBooleanType
00210   instantiate_magic = MagickFalse;
00211 
00212 /*
00213   Forward declarations.
00214 */
00215 static MagickBooleanType
00216   InitializeMagicList(ExceptionInfo *),
00217   LoadMagicLists(const char *,ExceptionInfo *);
00218 
00219 /*
00220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00221 %                                                                             %
00222 %                                                                             %
00223 %                                                                             %
00224 +   G e t M a g i c I n f o                                                   %
00225 %                                                                             %
00226 %                                                                             %
00227 %                                                                             %
00228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00229 %
00230 %  GetMagicInfo() searches the magic list for the specified name and if found
00231 %  returns attributes for that magic.
00232 %
00233 %  The format of the GetMagicInfo method is:
00234 %
00235 %      const MagicInfo *GetMagicInfo(const unsigned char *magic,
00236 %        const size_t length,ExceptionInfo *exception)
00237 %
00238 %  A description of each parameter follows:
00239 %
00240 %    o magic: A binary string generally representing the first few characters
00241 %      of the image file or blob.
00242 %
00243 %    o length: the length of the binary signature.
00244 %
00245 %    o exception: return any errors or warnings in this structure.
00246 %
00247 */
00248 MagickExport const MagicInfo *GetMagicInfo(const unsigned char *magic,
00249   const size_t length,ExceptionInfo *exception)
00250 {
00251   register const MagicInfo
00252     *p;
00253 
00254   assert(exception != (ExceptionInfo *) NULL);
00255   if ((magic_list == (LinkedListInfo *) NULL) ||
00256       (instantiate_magic == MagickFalse))
00257     if (InitializeMagicList(exception) == MagickFalse)
00258       return((const MagicInfo *) NULL);
00259   if ((magic_list == (LinkedListInfo *) NULL) ||
00260       (IsLinkedListEmpty(magic_list) != MagickFalse))
00261     return((const MagicInfo *) NULL);
00262   if (magic == (const unsigned char *) NULL)
00263     return((const MagicInfo *) GetValueFromLinkedList(magic_list,0));
00264   if (length == 0)
00265     return((const MagicInfo *) NULL);
00266   /*
00267     Search for magic tag.
00268   */
00269   LockSemaphoreInfo(magic_semaphore);
00270   ResetLinkedListIterator(magic_list);
00271   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00272   while (p != (const MagicInfo *) NULL)
00273   {
00274     assert(p->offset >= 0);
00275     if (((size_t) (p->offset+p->length) <= length) &&
00276         (memcmp(magic+p->offset,p->magic,p->length) == 0))
00277       break;
00278     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00279   }
00280   if (p != (const MagicInfo *) NULL)
00281     (void) InsertValueInLinkedList(magic_list,0,
00282       RemoveElementByValueFromLinkedList(magic_list,p));
00283   UnlockSemaphoreInfo(magic_semaphore);
00284   return(p);
00285 }
00286 
00287 /*
00288 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00289 %                                                                             %
00290 %                                                                             %
00291 %                                                                             %
00292 %   G e t M a g i c I n f o L i s t                                           %
00293 %                                                                             %
00294 %                                                                             %
00295 %                                                                             %
00296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00297 %
00298 %  GetMagicInfoList() returns any image aliases that match the specified
00299 %  pattern.
00300 %
00301 %  The magic of the GetMagicInfoList function is:
00302 %
00303 %      const MagicInfo **GetMagicInfoList(const char *pattern,
00304 %        size_t *number_aliases,ExceptionInfo *exception)
00305 %
00306 %  A description of each parameter follows:
00307 %
00308 %    o pattern: Specifies a pointer to a text string containing a pattern.
00309 %
00310 %    o number_aliases:  This integer returns the number of aliases in the list.
00311 %
00312 %    o exception: return any errors or warnings in this structure.
00313 %
00314 */
00315 
00316 #if defined(__cplusplus) || defined(c_plusplus)
00317 extern "C" {
00318 #endif
00319 
00320 static int MagicInfoCompare(const void *x,const void *y)
00321 {
00322   const MagicInfo
00323     **p,
00324     **q;
00325 
00326   p=(const MagicInfo **) x,
00327   q=(const MagicInfo **) y;
00328   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00329     return(LocaleCompare((*p)->name,(*q)->name));
00330   return(LocaleCompare((*p)->path,(*q)->path));
00331 }
00332 
00333 #if defined(__cplusplus) || defined(c_plusplus)
00334 }
00335 #endif
00336 
00337 MagickExport const MagicInfo **GetMagicInfoList(const char *pattern,
00338   size_t *number_aliases,ExceptionInfo *exception)
00339 {
00340   const MagicInfo
00341     **aliases;
00342 
00343   register const MagicInfo
00344     *p;
00345 
00346   register ssize_t
00347     i;
00348 
00349   /*
00350     Allocate magic list.
00351   */
00352   assert(pattern != (char *) NULL);
00353   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00354   assert(number_aliases != (size_t *) NULL);
00355   *number_aliases=0;
00356   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
00357   if (p == (const MagicInfo *) NULL)
00358     return((const MagicInfo **) NULL);
00359   aliases=(const MagicInfo **) AcquireQuantumMemory((size_t)
00360     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
00361   if (aliases == (const MagicInfo **) NULL)
00362     return((const MagicInfo **) NULL);
00363   /*
00364     Generate magic list.
00365   */
00366   LockSemaphoreInfo(magic_semaphore);
00367   ResetLinkedListIterator(magic_list);
00368   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00369   for (i=0; p != (const MagicInfo *) NULL; )
00370   {
00371     if ((p->stealth == MagickFalse) &&
00372         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00373       aliases[i++]=p;
00374     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00375   }
00376   UnlockSemaphoreInfo(magic_semaphore);
00377   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicInfoCompare);
00378   aliases[i]=(MagicInfo *) NULL;
00379   *number_aliases=(size_t) i;
00380   return(aliases);
00381 }
00382 
00383 /*
00384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00385 %                                                                             %
00386 %                                                                             %
00387 %                                                                             %
00388 %   G e t M a g i c L i s t                                                   %
00389 %                                                                             %
00390 %                                                                             %
00391 %                                                                             %
00392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00393 %
00394 %  GetMagicList() returns any image format aliases that match the specified
00395 %  pattern.
00396 %
00397 %  The format of the GetMagicList function is:
00398 %
00399 %      char **GetMagicList(const char *pattern,size_t *number_aliases,
00400 %        ExceptionInfo *exception)
00401 %
00402 %  A description of each parameter follows:
00403 %
00404 %    o pattern: Specifies a pointer to a text string containing a pattern.
00405 %
00406 %    o number_aliases:  This integer returns the number of image format aliases
00407 %      in the list.
00408 %
00409 %    o exception: return any errors or warnings in this structure.
00410 %
00411 */
00412 
00413 #if defined(__cplusplus) || defined(c_plusplus)
00414 extern "C" {
00415 #endif
00416 
00417 static int MagicCompare(const void *x,const void *y)
00418 {
00419   register const char
00420     *p,
00421     *q;
00422 
00423   p=(const char *) x;
00424   q=(const char *) y;
00425   return(LocaleCompare(p,q));
00426 }
00427 
00428 #if defined(__cplusplus) || defined(c_plusplus)
00429 }
00430 #endif
00431 
00432 MagickExport char **GetMagicList(const char *pattern,
00433   size_t *number_aliases,ExceptionInfo *exception)
00434 {
00435   char
00436     **aliases;
00437 
00438   register const MagicInfo
00439     *p;
00440 
00441   register ssize_t
00442     i;
00443 
00444   /*
00445     Allocate configure list.
00446   */
00447   assert(pattern != (char *) NULL);
00448   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00449   assert(number_aliases != (size_t *) NULL);
00450   *number_aliases=0;
00451   p=GetMagicInfo((const unsigned char *) NULL,0,exception);
00452   if (p == (const MagicInfo *) NULL)
00453     return((char **) NULL);
00454   aliases=(char **) AcquireQuantumMemory((size_t)
00455     GetNumberOfElementsInLinkedList(magic_list)+1UL,sizeof(*aliases));
00456   if (aliases == (char **) NULL)
00457     return((char **) NULL);
00458   LockSemaphoreInfo(magic_semaphore);
00459   ResetLinkedListIterator(magic_list);
00460   p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00461   for (i=0; p != (const MagicInfo *) NULL; )
00462   {
00463     if ((p->stealth == MagickFalse) &&
00464         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
00465       aliases[i++]=ConstantString(p->name);
00466     p=(const MagicInfo *) GetNextValueInLinkedList(magic_list);
00467   }
00468   UnlockSemaphoreInfo(magic_semaphore);
00469   qsort((void *) aliases,(size_t) i,sizeof(*aliases),MagicCompare);
00470   aliases[i]=(char *) NULL;
00471   *number_aliases=(size_t) i;
00472   return(aliases);
00473 }
00474 
00475 /*
00476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00477 %                                                                             %
00478 %                                                                             %
00479 %                                                                             %
00480 %   G e t M a g i c N a m e                                                   %
00481 %                                                                             %
00482 %                                                                             %
00483 %                                                                             %
00484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00485 %
00486 %  GetMagicName() returns the name associated with the magic.
00487 %
00488 %  The format of the GetMagicName method is:
00489 %
00490 %      const char *GetMagicName(const MagicInfo *magic_info)
00491 %
00492 %  A description of each parameter follows:
00493 %
00494 %    o magic_info:  The magic info.
00495 %
00496 */
00497 MagickExport const char *GetMagicName(const MagicInfo *magic_info)
00498 {
00499   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00500   assert(magic_info != (MagicInfo *) NULL);
00501   assert(magic_info->signature == MagickSignature);
00502   return(magic_info->name);
00503 }
00504 
00505 /*
00506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00507 %                                                                             %
00508 %                                                                             %
00509 %                                                                             %
00510 +   I n i t i a l i z e M a g i c L i s t                                     %
00511 %                                                                             %
00512 %                                                                             %
00513 %                                                                             %
00514 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00515 %
00516 %  InitializeMagicList() initializes the magic list.
00517 %
00518 %  The format of the InitializeMagicList method is:
00519 %
00520 %      MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
00521 %
00522 %  A description of each parameter follows.
00523 %
00524 %    o exception: return any errors or warnings in this structure.
00525 %
00526 */
00527 static MagickBooleanType InitializeMagicList(ExceptionInfo *exception)
00528 {
00529   if ((magic_list == (LinkedListInfo *) NULL) &&
00530       (instantiate_magic == MagickFalse))
00531     {
00532       if (magic_semaphore == (SemaphoreInfo *) NULL)
00533         AcquireSemaphoreInfo(&magic_semaphore);
00534       LockSemaphoreInfo(magic_semaphore);
00535       if ((magic_list == (LinkedListInfo *) NULL) &&
00536           (instantiate_magic == MagickFalse))
00537         {
00538           (void) LoadMagicLists(MagicFilename,exception);
00539           instantiate_magic=MagickTrue;
00540         }
00541       UnlockSemaphoreInfo(magic_semaphore);
00542     }
00543   return(magic_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
00544 }
00545 
00546 /*
00547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00548 %                                                                             %
00549 %                                                                             %
00550 %                                                                             %
00551 %  L i s t M a g i c I n f o                                                  %
00552 %                                                                             %
00553 %                                                                             %
00554 %                                                                             %
00555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00556 %
00557 %  ListMagicInfo() lists the magic info to a file.
00558 %
00559 %  The format of the ListMagicInfo method is:
00560 %
00561 %      MagickBooleanType ListMagicInfo(FILE *file,ExceptionInfo *exception)
00562 %
00563 %  A description of each parameter follows.
00564 %
00565 %    o file:  An pointer to a FILE.
00566 %
00567 %    o exception: return any errors or warnings in this structure.
00568 %
00569 */
00570 MagickExport MagickBooleanType ListMagicInfo(FILE *file,
00571   ExceptionInfo *exception)
00572 {
00573   const char
00574     *path;
00575 
00576   const MagicInfo
00577     **magic_info;
00578 
00579   register ssize_t
00580     i;
00581 
00582   size_t
00583     number_aliases;
00584 
00585   ssize_t
00586     j;
00587 
00588   if (file == (const FILE *) NULL)
00589     file=stdout;
00590   magic_info=GetMagicInfoList("*",&number_aliases,exception);
00591   if (magic_info == (const MagicInfo **) NULL)
00592     return(MagickFalse);
00593   j=0;
00594   path=(const char *) NULL;
00595   for (i=0; i < (ssize_t) number_aliases; i++)
00596   {
00597     if (magic_info[i]->stealth != MagickFalse)
00598       continue;
00599     if ((path == (const char *) NULL) ||
00600         (LocaleCompare(path,magic_info[i]->path) != 0))
00601       {
00602         if (magic_info[i]->path != (char *) NULL)
00603           (void) FormatLocaleFile(file,"\nPath: %s\n\n",magic_info[i]->path);
00604         (void) FormatLocaleFile(file,"Name      Offset Target\n");
00605         (void) FormatLocaleFile(file,
00606           "-------------------------------------------------"
00607           "------------------------------\n");
00608       }
00609     path=magic_info[i]->path;
00610     (void) FormatLocaleFile(file,"%s",magic_info[i]->name);
00611     for (j=(ssize_t) strlen(magic_info[i]->name); j <= 9; j++)
00612       (void) FormatLocaleFile(file," ");
00613     (void) FormatLocaleFile(file,"%6ld ",(long) magic_info[i]->offset);
00614     if (magic_info[i]->target != (char *) NULL)
00615       {
00616         register ssize_t
00617           j;
00618 
00619         for (j=0; magic_info[i]->target[j] != '\0'; j++)
00620           if (isprint((int) ((unsigned char) magic_info[i]->target[j])) != 0)
00621             (void) FormatLocaleFile(file,"%c",magic_info[i]->target[j]);
00622           else
00623             (void) FormatLocaleFile(file,"\\%03o",(unsigned int)
00624               ((unsigned char) magic_info[i]->target[j]));
00625       }
00626     (void) FormatLocaleFile(file,"\n");
00627   }
00628   (void) fflush(file);
00629   magic_info=(const MagicInfo **) RelinquishMagickMemory((void *) magic_info);
00630   return(MagickTrue);
00631 }
00632 
00633 /*
00634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00635 %                                                                             %
00636 %                                                                             %
00637 %                                                                             %
00638 +   L o a d M a g i c L i s t                                                 %
00639 %                                                                             %
00640 %                                                                             %
00641 %                                                                             %
00642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00643 %
00644 %  LoadMagicList() loads the magic configuration file which provides a mapping
00645 %  between magic attributes and a magic name.
00646 %
00647 %  The format of the LoadMagicList method is:
00648 %
00649 %      MagickBooleanType LoadMagicList(const char *xml,const char *filename,
00650 %        const size_t depth,ExceptionInfo *exception)
00651 %
00652 %  A description of each parameter follows:
00653 %
00654 %    o xml: The magic list in XML format.
00655 %
00656 %    o filename: The magic list filename.
00657 %
00658 %    o depth: depth of <include /> statements.
00659 %
00660 %    o exception: return any errors or warnings in this structure.
00661 %
00662 */
00663 static MagickBooleanType LoadMagicList(const char *xml,const char *filename,
00664   const size_t depth,ExceptionInfo *exception)
00665 {
00666   char
00667     keyword[MaxTextExtent],
00668     *token;
00669 
00670   const char
00671     *q;
00672 
00673   MagickBooleanType
00674     status;
00675 
00676   MagicInfo
00677     *magic_info;
00678 
00679   /*
00680     Load the magic map file.
00681   */
00682   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00683     "Loading magic configure file \"%s\" ...",filename);
00684   if (xml == (char *) NULL)
00685     return(MagickFalse);
00686   if (magic_list == (LinkedListInfo *) NULL)
00687     {
00688       magic_list=NewLinkedList(0);
00689       if (magic_list == (LinkedListInfo *) NULL)
00690         {
00691           ThrowFileException(exception,ResourceLimitError,
00692             "MemoryAllocationFailed",filename);
00693           return(MagickFalse);
00694         }
00695     }
00696   status=MagickTrue;
00697   magic_info=(MagicInfo *) NULL;
00698   token=AcquireString(xml);
00699   for (q=(char *) xml; *q != '\0'; )
00700   {
00701     /*
00702       Interpret XML.
00703     */
00704     GetMagickToken(q,&q,token);
00705     if (*token == '\0')
00706       break;
00707     (void) CopyMagickString(keyword,token,MaxTextExtent);
00708     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
00709       {
00710         /*
00711           Doctype element.
00712         */
00713         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
00714           GetMagickToken(q,&q,token);
00715         continue;
00716       }
00717     if (LocaleNCompare(keyword,"<!--",4) == 0)
00718       {
00719         /*
00720           Comment element.
00721         */
00722         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
00723           GetMagickToken(q,&q,token);
00724         continue;
00725       }
00726     if (LocaleCompare(keyword,"<include") == 0)
00727       {
00728         /*
00729           Include element.
00730         */
00731         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
00732         {
00733           (void) CopyMagickString(keyword,token,MaxTextExtent);
00734           GetMagickToken(q,&q,token);
00735           if (*token != '=')
00736             continue;
00737           GetMagickToken(q,&q,token);
00738           if (LocaleCompare(keyword,"file") == 0)
00739             {
00740               if (depth > 200)
00741                 (void) ThrowMagickException(exception,GetMagickModule(),
00742                   ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
00743               else
00744                 {
00745                   char
00746                     path[MaxTextExtent],
00747                     *xml;
00748 
00749                   GetPathComponent(filename,HeadPath,path);
00750                   if (*path != '\0')
00751                     (void) ConcatenateMagickString(path,DirectorySeparator,
00752                       MaxTextExtent);
00753                   if (*token == *DirectorySeparator)
00754                     (void) CopyMagickString(path,token,MaxTextExtent);
00755                   else
00756                     (void) ConcatenateMagickString(path,token,MaxTextExtent);
00757                   xml=FileToString(path,~0,exception);
00758                   if (xml != (char *) NULL)
00759                     {
00760                       status=LoadMagicList(xml,path,depth+1,exception);
00761                       xml=(char *) RelinquishMagickMemory(xml);
00762                     }
00763                 }
00764             }
00765         }
00766         continue;
00767       }
00768     if (LocaleCompare(keyword,"<magic") == 0)
00769       {
00770         /*
00771           Magic element.
00772         */
00773         magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
00774         if (magic_info == (MagicInfo *) NULL)
00775           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00776         (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
00777         magic_info->path=ConstantString(filename);
00778         magic_info->exempt=MagickFalse;
00779         magic_info->signature=MagickSignature;
00780         continue;
00781       }
00782     if (magic_info == (MagicInfo *) NULL)
00783       continue;
00784     if (LocaleCompare(keyword,"/>") == 0)
00785       {
00786         status=AppendValueToLinkedList(magic_list,magic_info);
00787         if (status == MagickFalse)
00788           (void) ThrowMagickException(exception,GetMagickModule(),
00789             ResourceLimitError,"MemoryAllocationFailed","`%s'",
00790             magic_info->name);
00791         magic_info=(MagicInfo *) NULL;
00792       }
00793     GetMagickToken(q,(const char **) NULL,token);
00794     if (*token != '=')
00795       continue;
00796     GetMagickToken(q,&q,token);
00797     GetMagickToken(q,&q,token);
00798     switch (*keyword)
00799     {
00800       case 'N':
00801       case 'n':
00802       {
00803         if (LocaleCompare((char *) keyword,"name") == 0)
00804           {
00805             magic_info->name=ConstantString(token);
00806             break;
00807           }
00808         break;
00809       }
00810       case 'O':
00811       case 'o':
00812       {
00813         if (LocaleCompare((char *) keyword,"offset") == 0)
00814           {
00815             magic_info->offset=(MagickOffsetType) StringToLong(token);
00816             break;
00817           }
00818         break;
00819       }
00820       case 'S':
00821       case 's':
00822       {
00823         if (LocaleCompare((char *) keyword,"stealth") == 0)
00824           {
00825             magic_info->stealth=IsMagickTrue(token);
00826             break;
00827           }
00828         break;
00829       }
00830       case 'T':
00831       case 't':
00832       {
00833         if (LocaleCompare((char *) keyword,"target") == 0)
00834           {
00835             char
00836               *p;
00837 
00838             register unsigned char
00839               *q;
00840 
00841             size_t
00842               length;
00843 
00844             length=strlen(token);
00845             magic_info->target=ConstantString(token);
00846             magic_info->magic=(unsigned char *) ConstantString(token);
00847             q=magic_info->magic;
00848             for (p=magic_info->target; *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                       magic_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                   magic_info->length++;
00878                   continue;
00879                 }
00880               else
00881                 if (LocaleNCompare(p,"&amp;",5) == 0)
00882                   (void) CopyMagickString(p+1,p+5,length-magic_info->length);
00883               *q++=(unsigned char) (*p++);
00884               magic_info->length++;
00885             }
00886             break;
00887           }
00888         break;
00889       }
00890       default:
00891         break;
00892     }
00893   }
00894   token=(char *) RelinquishMagickMemory(token);
00895   return(status);
00896 }
00897 
00898 /*
00899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00900 %                                                                             %
00901 %                                                                             %
00902 %                                                                             %
00903 %  L o a d M a g i c L i s t s                                                %
00904 %                                                                             %
00905 %                                                                             %
00906 %                                                                             %
00907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00908 %
00909 %  LoadMagicLists() loads one or more magic configuration file which provides a
00910 %  mapping between magic attributes and a magic name.
00911 %
00912 %  The format of the LoadMagicLists method is:
00913 %
00914 %      MagickBooleanType LoadMagicLists(const char *filename,
00915 %        ExceptionInfo *exception)
00916 %
00917 %  A description of each parameter follows:
00918 %
00919 %    o filename: the font file name.
00920 %
00921 %    o exception: return any errors or warnings in this structure.
00922 %
00923 */
00924 static MagickBooleanType LoadMagicLists(const char *filename,
00925   ExceptionInfo *exception)
00926 {
00927   char
00928     path[MaxTextExtent];
00929 
00930   const StringInfo
00931     *option;
00932 
00933   LinkedListInfo
00934     *options;
00935 
00936   MagickStatusType
00937     status;
00938 
00939   register ssize_t
00940     i;
00941 
00942   /*
00943     Load built-in magic map.
00944   */
00945   status=MagickFalse;
00946   if (magic_list == (LinkedListInfo *) NULL)
00947     {
00948       magic_list=NewLinkedList(0);
00949       if (magic_list == (LinkedListInfo *) NULL)
00950         {
00951           ThrowFileException(exception,ResourceLimitError,
00952             "MemoryAllocationFailed",filename);
00953           return(MagickFalse);
00954         }
00955     }
00956   for (i=0; i < (ssize_t) (sizeof(MagicMap)/sizeof(*MagicMap)); i++)
00957   {
00958     MagicInfo
00959       *magic_info;
00960 
00961     register const MagicMapInfo
00962       *p;
00963 
00964     p=MagicMap+i;
00965     magic_info=(MagicInfo *) AcquireMagickMemory(sizeof(*magic_info));
00966     if (magic_info == (MagicInfo *) NULL)
00967       {
00968         (void) ThrowMagickException(exception,GetMagickModule(),
00969           ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
00970         continue;
00971       }
00972     (void) ResetMagickMemory(magic_info,0,sizeof(*magic_info));
00973     magic_info->path=(char *) "[built-in]";
00974     magic_info->name=(char *) p->name;
00975     magic_info->offset=p->offset;
00976     magic_info->target=(char *) p->magic;
00977     magic_info->magic=(unsigned char *) p->magic;
00978     magic_info->length=p->length;
00979     magic_info->exempt=MagickTrue;
00980     magic_info->signature=MagickSignature;
00981     status=AppendValueToLinkedList(magic_list,magic_info);
00982     if (status == MagickFalse)
00983       (void) ThrowMagickException(exception,GetMagickModule(),
00984         ResourceLimitError,"MemoryAllocationFailed","`%s'",magic_info->name);
00985   }
00986   /*
00987     Load external magic map.
00988   */
00989   *path='\0';
00990   options=GetConfigureOptions(filename,exception);
00991   option=(const StringInfo *) GetNextValueInLinkedList(options);
00992   while (option != (const StringInfo *) NULL)
00993   {
00994     (void) CopyMagickString(path,GetStringInfoPath(option),MaxTextExtent);
00995     status|=LoadMagicList((const char *) GetStringInfoDatum(option),
00996       GetStringInfoPath(option),0,exception);
00997     option=(const StringInfo *) GetNextValueInLinkedList(options);
00998   }
00999   options=DestroyConfigureOptions(options);
01000   return(status != 0 ? MagickTrue : MagickFalse);
01001 }
01002 
01003 /*
01004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01005 %                                                                             %
01006 %                                                                             %
01007 %                                                                             %
01008 +   M a g i c C o m p o n e n t G e n e s i s                                 %
01009 %                                                                             %
01010 %                                                                             %
01011 %                                                                             %
01012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01013 %
01014 %  MagicComponentGenesis() instantiates the magic component.
01015 %
01016 %  The format of the MagicComponentGenesis method is:
01017 %
01018 %      MagickBooleanType MagicComponentGenesis(void)
01019 %
01020 */
01021 MagickPrivate MagickBooleanType MagicComponentGenesis(void)
01022 {
01023   AcquireSemaphoreInfo(&magic_semaphore);
01024   return(MagickTrue);
01025 }
01026 
01027 /*
01028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01029 %                                                                             %
01030 %                                                                             %
01031 %                                                                             %
01032 +   M a g i c C o m p o n e n t T e r m i n u s                               %
01033 %                                                                             %
01034 %                                                                             %
01035 %                                                                             %
01036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01037 %
01038 %  MagicComponentTerminus() destroys the magic component.
01039 %
01040 %  The format of the MagicComponentTerminus method is:
01041 %
01042 %      MagicComponentTerminus(void)
01043 %
01044 */
01045 
01046 static void *DestroyMagicElement(void *magic_info)
01047 {
01048   register MagicInfo
01049     *p;
01050 
01051   p=(MagicInfo *) magic_info;
01052   if (p->exempt == MagickFalse)
01053     {
01054       if (p->path != (char *) NULL)
01055         p->path=DestroyString(p->path);
01056       if (p->name != (char *) NULL)
01057         p->name=DestroyString(p->name);
01058       if (p->target != (char *) NULL)
01059         p->target=DestroyString(p->target);
01060       if (p->magic != (unsigned char *) NULL)
01061         p->magic=(unsigned char *) RelinquishMagickMemory(p->magic);
01062     }
01063   p=(MagicInfo *) RelinquishMagickMemory(p);
01064   return((void *) NULL);
01065 }
01066 
01067 MagickPrivate void MagicComponentTerminus(void)
01068 {
01069   if (magic_semaphore == (SemaphoreInfo *) NULL)
01070     AcquireSemaphoreInfo(&magic_semaphore);
01071   LockSemaphoreInfo(magic_semaphore);
01072   if (magic_list != (LinkedListInfo *) NULL)
01073     magic_list=DestroyLinkedList(magic_list,DestroyMagicElement);
01074   instantiate_magic=MagickFalse;
01075   UnlockSemaphoreInfo(magic_semaphore);
01076   DestroySemaphoreInfo(&magic_semaphore);
01077 }