Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                   CCCC   OOO   DDDD    EEEEE  RRRR                          %
      7 %                  C      O   O  D   D   E      R   R                         %
      8 %                  C      O   O  D   D   EEE    RRRR                          %
      9 %                  C      O   O  D   D   E      R R                           %
     10 %                   CCCC   OOO   DDDD    EEEEE  R  R                          %
     11 %                                                                             %
     12 %                                                                             %
     13 %                     MagickCore Image Coder Methods                          %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 May 2001                                    %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 */
     38 
     39 /*
     41   Include declarations.
     42 */
     43 #include "MagickCore/studio.h"
     44 #include "MagickCore/blob.h"
     45 #include "MagickCore/client.h"
     46 #include "MagickCore/coder.h"
     47 #include "MagickCore/coder-private.h"
     48 #include "MagickCore/configure.h"
     49 #include "MagickCore/draw.h"
     50 #include "MagickCore/exception.h"
     51 #include "MagickCore/exception-private.h"
     52 #include "MagickCore/linked-list.h"
     53 #include "MagickCore/log.h"
     54 #include "MagickCore/memory_.h"
     55 #include "MagickCore/option.h"
     56 #include "MagickCore/semaphore.h"
     57 #include "MagickCore/string_.h"
     58 #include "MagickCore/splay-tree.h"
     59 #include "MagickCore/token.h"
     60 #include "MagickCore/utility.h"
     61 #include "MagickCore/utility-private.h"
     62 #include "MagickCore/xml-tree.h"
     63 #include "MagickCore/xml-tree-private.h"
     64 
     65 /*
     67   Define declarations.
     68 */
     69 #define MagickCoderFilename  "coder.xml"
     70 
     71 /*
     73   Typedef declarations.
     74 */
     75 typedef struct _CoderMapInfo
     76 {
     77   const char
     78     *magick,
     79     *name;
     80 } CoderMapInfo;
     81 
     82 /*
     84   Static declarations.
     85 */
     86 static const CoderMapInfo
     87   CoderMap[] =
     88   {
     89     { "3FR", "DNG" },
     90     { "8BIM", "META" },
     91     { "8BIMTEXT", "META" },
     92     { "8BIMWTEXT", "META" },
     93     { "AFM", "TTF" },
     94     { "A", "RAW" },
     95     { "AI", "PDF" },
     96     { "APP1JPEG", "META" },
     97     { "APP1", "META" },
     98     { "ARW", "DNG" },
     99     { "AVI", "MPEG" },
    100     { "BIE", "JBIG" },
    101     { "BMP2", "BMP" },
    102     { "BMP3", "BMP" },
    103     { "B", "RAW" },
    104     { "BRF", "BRAILLE" },
    105     { "BGRA", "BGR" },
    106     { "BGRO", "BGR" },
    107     { "CMYKA", "CMYK" },
    108     { "C", "RAW" },
    109     { "CAL", "CALS" },
    110     { "CANVAS", "XC" },
    111     { "CMYKA", "CMYK" },
    112     { "CR2", "DNG" },
    113     { "CRW", "DNG" },
    114     { "CUR", "ICON" },
    115     { "DATA", "INLINE" },
    116     { "DCR", "DNG" },
    117     { "DCX", "PCX" },
    118     { "DFONT", "TTF" },
    119     { "DXT1", "DDS" },
    120     { "DXT5", "DDS" },
    121     { "EPDF", "PDF" },
    122     { "EPI", "PS" },
    123     { "EPS2", "PS2" },
    124     { "EPS3", "PS3" },
    125     { "EPSF", "PS" },
    126     { "EPSI", "PS" },
    127     { "EPS", "PS" },
    128     { "EPT2", "EPT" },
    129     { "EPT3", "EPT" },
    130     { "ERF", "DNG" },
    131     { "EXIF", "META" },
    132     { "FILE", "URL" },
    133     { "FRACTAL", "PLASMA" },
    134     { "FTP", "URL" },
    135     { "FTS", "FITS" },
    136     { "G3", "FAX" },
    137     { "G4", "FAX" },
    138     { "GIF87", "GIF" },
    139     { "G", "RAW" },
    140     { "GRANITE", "MAGICK" },
    141     { "GROUP4", "TIFF" },
    142     { "GV", "DOT" },
    143     { "HTM", "HTML" },
    144     { "ICB", "TGA" },
    145     { "ICO", "ICON" },
    146     { "IIQ", "DNG" },
    147     { "K25", "DNG" },
    148     { "KDC", "DNG" },
    149     { "H", "MAGICK" },
    150     { "HTM", "HTML" },
    151     { "HTTP", "URL" },
    152     { "HTTPS", "URL" },
    153     { "ICB", "TGA" },
    154     { "ICC", "META" },
    155     { "ICM", "META" },
    156     { "ICO", "ICON" },
    157     { "IMPLICIT", "***" },
    158     { "IPTC", "META" },
    159     { "IPTCTEXT", "META" },
    160     { "IPTCWTEXT", "META" },
    161     { "ISOBRL", "BRAILLE" },
    162     { "ISOBRL6", "BRAILLE" },
    163     { "JBG", "JBIG" },
    164     { "JNG", "PNG" },
    165     { "JPC", "JP2" },
    166     { "JPT", "JP2" },
    167     { "JPM", "JP2" },
    168     { "J2C", "JP2" },
    169     { "J2K", "JP2" },
    170     { "JNG", "PNG" },
    171     { "JPE", "JPEG" },
    172     { "JPG", "JPEG" },
    173     { "JPM", "JP2" },
    174     { "JPS", "JPEG" },
    175     { "JPT", "JP2" },
    176     { "JPX", "JP2" },
    177     { "K", "RAW" },
    178     { "K25", "DNG" },
    179     { "KDC", "DNG" },
    180     { "LOGO", "MAGICK" },
    181     { "M", "RAW" },
    182     { "M2V", "MPEG" },
    183     { "M4V", "MPEG" },
    184     { "MEF", "DNG" },
    185     { "MKV", "MPEG" },
    186     { "MNG", "PNG" },
    187     { "MOV", "MPEG" },
    188     { "MP4", "MPEG" },
    189     { "MPG", "MPEG" },
    190     { "MPRI", "MPR" },
    191     { "MEF", "DNG" },
    192     { "MRW", "DNG" },
    193     { "MSVG", "SVG" },
    194     { "NEF", "DNG" },
    195     { "NETSCAPE", "MAGICK" },
    196     { "NRW", "DNG" },
    197     { "O", "RAW" },
    198     { "ORF", "DNG" },
    199     { "OTF", "TTF" },
    200     { "P7", "PNM" },
    201     { "PAL", "UYVY" },
    202     { "PAM", "PNM" },
    203     { "PBM", "PNM" },
    204     { "PCDS", "PCD" },
    205     { "PCT", "PICT" },
    206     { "PDFA", "PDF" },
    207     { "PEF", "DNG" },
    208     { "PEF", "DNG" },
    209     { "PFA", "TTF" },
    210     { "PFB", "TTF" },
    211     { "PFM", "PNM" },
    212     { "PGM", "PNM" },
    213     { "PGX", "JP2" },
    214     { "PICON", "XPM" },
    215     { "PJPEG", "JPEG" },
    216     { "PM", "XPM" },
    217     { "PNG00", "PNG" },
    218     { "PNG24", "PNG" },
    219     { "PNG32", "PNG" },
    220     { "PNG48", "PNG" },
    221     { "PNG64", "PNG" },
    222     { "PNG8", "PNG" },
    223     { "PPM", "PNM" },
    224     { "PSB", "PSD" },
    225     { "PTIF", "TIFF" },
    226     { "R", "RAW" },
    227     { "RADIAL-GRADIENT", "GRADIENT" },
    228     { "RAF", "DNG" },
    229     { "RAS", "SUN" },
    230     { "RAW", "DNG" },
    231     { "RGBA", "RGB" },
    232     { "RGBO", "RGB" },
    233     { "RMF", "DNG" },
    234     { "ROSE", "MAGICK" },
    235     { "RW2", "DNG" },
    236     { "SHTML", "HTML" },
    237     { "SIX", "SIXEL" },
    238     { "SPARSE-COLOR", "TXT" },
    239     { "SR2", "DNG" },
    240     { "SRF", "DNG" },
    241     { "SVGZ", "SVG" },
    242     { "TEXT", "TXT" },
    243     { "TIFF64", "TIFF" },
    244     { "TIF", "TIFF" },
    245     { "TTC", "TTF" },
    246     { "UBRL", "BRAILLE" },
    247     { "UBRL6", "BRAILLE" },
    248     { "VDA", "TGA" },
    249     { "VST", "TGA" },
    250     { "WIZARD", "MAGICK" },
    251 #if defined(MAGICKCORE_WINGDI32_DELEGATE)
    252     { "WMF", "EMF" },
    253 #endif
    254     { "WMV", "MPEG" },
    255     { "WMZ", "WMF" },
    256     { "X3f", "DNG" },
    257     { "XMP", "META" },
    258     { "XTRNARRAY", "XTRN" },
    259     { "XTRNBLOB", "XTRN" },
    260     { "XTRNFILE", "XTRN" },
    261     { "XTRNIMAGE", "XTRN" },
    262     { "XV", "VIFF" },
    263     { "Y", "RAW" },
    264     { "YCbCrA", "YCbCr" }
    265  };
    266 
    267 static SemaphoreInfo
    268   *coder_semaphore = (SemaphoreInfo *) NULL;
    269 
    270 static SplayTreeInfo
    271   *coder_cache = (SplayTreeInfo *) NULL;
    272 
    273 /*
    275   Forward declarations.
    276 */
    277 static MagickBooleanType
    278   IsCoderTreeInstantiated(ExceptionInfo *),
    279   LoadCoderCache(SplayTreeInfo *,const char *,const char *,const size_t,
    280     ExceptionInfo *);
    281 
    282 /*
    284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    285 %                                                                             %
    286 %                                                                             %
    287 %                                                                             %
    288 +  A c q u i r e C o d e r C a c h e                                          %
    289 %                                                                             %
    290 %                                                                             %
    291 %                                                                             %
    292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    293 %
    294 %  AcquireCoderCache() caches one or more coder configurations which provides a
    295 %  mapping between coder attributes and a coder name.
    296 %
    297 %  The format of the AcquireCoderCache coder is:
    298 %
    299 %      SplayTreeInfo *AcquireCoderCache(const char *filename,
    300 %        ExceptionInfo *exception)
    301 %
    302 %  A description of each parameter follows:
    303 %
    304 %    o filename: the font file name.
    305 %
    306 %    o exception: return any errors or warnings in this structure.
    307 %
    308 */
    309 
    310 static void *DestroyCoderNode(void *coder_info)
    311 {
    312   register CoderInfo
    313     *p;
    314 
    315   p=(CoderInfo *) coder_info;
    316   if (p->exempt == MagickFalse)
    317     {
    318       if (p->path != (char *) NULL)
    319         p->path=DestroyString(p->path);
    320       if (p->name != (char *) NULL)
    321         p->name=DestroyString(p->name);
    322       if (p->magick != (char *) NULL)
    323         p->magick=DestroyString(p->magick);
    324     }
    325   return(RelinquishMagickMemory(p));
    326 }
    327 
    328 static SplayTreeInfo *AcquireCoderCache(const char *filename,
    329   ExceptionInfo *exception)
    330 {
    331   MagickStatusType
    332     status;
    333 
    334   register ssize_t
    335     i;
    336 
    337   SplayTreeInfo
    338     *cache;
    339 
    340   /*
    341     Load external coder map.
    342   */
    343   cache=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
    344     DestroyCoderNode);
    345   if (cache == (SplayTreeInfo *) NULL)
    346     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    347   status=MagickTrue;
    348 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
    349   {
    350     const StringInfo
    351       *option;
    352 
    353     LinkedListInfo
    354       *options;
    355 
    356     options=GetConfigureOptions(filename,exception);
    357     option=(const StringInfo *) GetNextValueInLinkedList(options);
    358     while (option != (const StringInfo *) NULL)
    359     {
    360       status&=LoadCoderCache(cache,(const char *) GetStringInfoDatum(option),
    361         GetStringInfoPath(option),0,exception);
    362       option=(const StringInfo *) GetNextValueInLinkedList(options);
    363     }
    364     options=DestroyConfigureOptions(options);
    365   }
    366 #endif
    367   /*
    368     Load built-in coder map.
    369   */
    370   for (i=0; i < (ssize_t) (sizeof(CoderMap)/sizeof(*CoderMap)); i++)
    371   {
    372     CoderInfo
    373       *coder_info;
    374 
    375     register const CoderMapInfo
    376       *p;
    377 
    378     p=CoderMap+i;
    379     coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
    380     if (coder_info == (CoderInfo *) NULL)
    381       {
    382         (void) ThrowMagickException(exception,GetMagickModule(),
    383           ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
    384         continue;
    385       }
    386     (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
    387     coder_info->path=(char *) "[built-in]";
    388     coder_info->magick=(char *) p->magick;
    389     coder_info->name=(char *) p->name;
    390     coder_info->exempt=MagickTrue;
    391     coder_info->signature=MagickCoreSignature;
    392     status&=AddValueToSplayTree(cache,ConstantString(coder_info->magick),
    393       coder_info);
    394     if (status == MagickFalse)
    395       (void) ThrowMagickException(exception,GetMagickModule(),
    396         ResourceLimitError,"MemoryAllocationFailed","`%s'",coder_info->name);
    397   }
    398   return(cache);
    399 }
    400 
    401 /*
    403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    404 %                                                                             %
    405 %                                                                             %
    406 %                                                                             %
    407 +   C o d e r C o m p o n e n t G e n e s i s                                 %
    408 %                                                                             %
    409 %                                                                             %
    410 %                                                                             %
    411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    412 %
    413 %  CoderComponentGenesis() instantiates the coder component.
    414 %
    415 %  The format of the CoderComponentGenesis method is:
    416 %
    417 %      MagickBooleanType CoderComponentGenesis(void)
    418 %
    419 */
    420 MagickPrivate MagickBooleanType CoderComponentGenesis(void)
    421 {
    422   if (coder_semaphore == (SemaphoreInfo *) NULL)
    423     coder_semaphore=AcquireSemaphoreInfo();
    424   return(MagickTrue);
    425 }
    426 
    427 /*
    429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    430 %                                                                             %
    431 %                                                                             %
    432 %                                                                             %
    433 +   C o d e r C o m p o n e n t T e r m i n u s                               %
    434 %                                                                             %
    435 %                                                                             %
    436 %                                                                             %
    437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    438 %
    439 %  CoderComponentTerminus() destroys the coder component.
    440 %
    441 %  The format of the CoderComponentTerminus method is:
    442 %
    443 %      CoderComponentTerminus(void)
    444 %
    445 */
    446 MagickPrivate void CoderComponentTerminus(void)
    447 {
    448   if (coder_semaphore == (SemaphoreInfo *) NULL)
    449     ActivateSemaphoreInfo(&coder_semaphore);
    450   LockSemaphoreInfo(coder_semaphore);
    451   if (coder_cache != (SplayTreeInfo *) NULL)
    452     coder_cache=DestroySplayTree(coder_cache);
    453   UnlockSemaphoreInfo(coder_semaphore);
    454   RelinquishSemaphoreInfo(&coder_semaphore);
    455 }
    456 
    457 /*
    459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    460 %                                                                             %
    461 %                                                                             %
    462 %                                                                             %
    463 +   G e t C o d e r I n f o                                                   %
    464 %                                                                             %
    465 %                                                                             %
    466 %                                                                             %
    467 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    468 %
    469 %  GetCoderInfo searches the coder list for the specified name and if found
    470 %  returns attributes for that coder.
    471 %
    472 %  The format of the GetCoderInfo method is:
    473 %
    474 %      const CoderInfo *GetCoderInfo(const char *name,ExceptionInfo *exception)
    475 %
    476 %  A description of each parameter follows:
    477 %
    478 %    o name: the coder name.
    479 %
    480 %    o exception: return any errors or warnings in this structure.
    481 %
    482 */
    483 MagickExport const CoderInfo *GetCoderInfo(const char *name,
    484   ExceptionInfo *exception)
    485 {
    486   const CoderInfo
    487     *coder_info;
    488 
    489   assert(exception != (ExceptionInfo *) NULL);
    490   if (IsCoderTreeInstantiated(exception) == MagickFalse)
    491     return((const CoderInfo *) NULL);
    492   LockSemaphoreInfo(coder_semaphore);
    493   if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
    494     {
    495       ResetSplayTreeIterator(coder_cache);
    496       coder_info=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
    497       UnlockSemaphoreInfo(coder_semaphore);
    498       return(coder_info);
    499     }
    500   coder_info=(const CoderInfo *) GetValueFromSplayTree(coder_cache,name);
    501   UnlockSemaphoreInfo(coder_semaphore);
    502   return(coder_info);
    503 }
    504 
    505 /*
    507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    508 %                                                                             %
    509 %                                                                             %
    510 %                                                                             %
    511 %   G e t C o d e r I n f o L i s t                                           %
    512 %                                                                             %
    513 %                                                                             %
    514 %                                                                             %
    515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    516 %
    517 %  GetCoderInfoList() returns any coder_map that match the specified pattern.
    518 %  The format of the GetCoderInfoList function is:
    519 %
    520 %      const CoderInfo **GetCoderInfoList(const char *pattern,
    521 %        size_t *number_coders,ExceptionInfo *exception)
    522 %
    523 %  A description of each parameter follows:
    524 %
    525 %    o pattern: Specifies a pointer to a text string containing a pattern.
    526 %
    527 %    o number_coders:  This integer returns the number of coders in the list.
    528 %
    529 %    o exception: return any errors or warnings in this structure.
    530 %
    531 */
    532 
    533 static int CoderInfoCompare(const void *x,const void *y)
    534 {
    535   const CoderInfo
    536     **p,
    537     **q;
    538 
    539   p=(const CoderInfo **) x,
    540   q=(const CoderInfo **) y;
    541   if (LocaleCompare((*p)->path,(*q)->path) == 0)
    542     return(LocaleCompare((*p)->name,(*q)->name));
    543   return(LocaleCompare((*p)->path,(*q)->path));
    544 }
    545 
    546 MagickExport const CoderInfo **GetCoderInfoList(const char *pattern,
    547   size_t *number_coders,ExceptionInfo *exception)
    548 {
    549   const CoderInfo
    550     **coder_map;
    551 
    552   register const CoderInfo
    553     *p;
    554 
    555   register ssize_t
    556     i;
    557 
    558   /*
    559     Allocate coder list.
    560   */
    561   assert(pattern != (char *) NULL);
    562   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
    563   assert(number_coders != (size_t *) NULL);
    564   *number_coders=0;
    565   p=GetCoderInfo("*",exception);
    566   if (p == (const CoderInfo *) NULL)
    567     return((const CoderInfo **) NULL);
    568   coder_map=(const CoderInfo **) AcquireQuantumMemory((size_t)
    569     GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
    570   if (coder_map == (const CoderInfo **) NULL)
    571     return((const CoderInfo **) NULL);
    572   /*
    573     Generate coder list.
    574   */
    575   LockSemaphoreInfo(coder_semaphore);
    576   ResetSplayTreeIterator(coder_cache);
    577   p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
    578   for (i=0; p != (const CoderInfo *) NULL; )
    579   {
    580     if ((p->stealth == MagickFalse) &&
    581         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
    582       coder_map[i++]=p;
    583     p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
    584   }
    585   UnlockSemaphoreInfo(coder_semaphore);
    586   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderInfoCompare);
    587   coder_map[i]=(CoderInfo *) NULL;
    588   *number_coders=(size_t) i;
    589   return(coder_map);
    590 }
    591 
    592 /*
    594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    595 %                                                                             %
    596 %                                                                             %
    597 %                                                                             %
    598 %   G e t C o d e r L i s t                                                   %
    599 %                                                                             %
    600 %                                                                             %
    601 %                                                                             %
    602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    603 %
    604 %  GetCoderList() returns any coder_map that match the specified pattern.
    605 %
    606 %  The format of the GetCoderList function is:
    607 %
    608 %      char **GetCoderList(const char *pattern,size_t *number_coders,
    609 %        ExceptionInfo *exception)
    610 %
    611 %  A description of each parameter follows:
    612 %
    613 %    o pattern: Specifies a pointer to a text string containing a pattern.
    614 %
    615 %    o number_coders:  This integer returns the number of coders in the list.
    616 %
    617 %    o exception: return any errors or warnings in this structure.
    618 %
    619 */
    620 
    621 static int CoderCompare(const void *x,const void *y)
    622 {
    623   register const char
    624     **p,
    625     **q;
    626 
    627   p=(const char **) x;
    628   q=(const char **) y;
    629   return(LocaleCompare(*p,*q));
    630 }
    631 
    632 MagickExport char **GetCoderList(const char *pattern,
    633   size_t *number_coders,ExceptionInfo *exception)
    634 {
    635   char
    636     **coder_map;
    637 
    638   register const CoderInfo
    639     *p;
    640 
    641   register ssize_t
    642     i;
    643 
    644   /*
    645     Allocate coder list.
    646   */
    647   assert(pattern != (char *) NULL);
    648   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
    649   assert(number_coders != (size_t *) NULL);
    650   *number_coders=0;
    651   p=GetCoderInfo("*",exception);
    652   if (p == (const CoderInfo *) NULL)
    653     return((char **) NULL);
    654   coder_map=(char **) AcquireQuantumMemory((size_t)
    655     GetNumberOfNodesInSplayTree(coder_cache)+1UL,sizeof(*coder_map));
    656   if (coder_map == (char **) NULL)
    657     return((char **) NULL);
    658   /*
    659     Generate coder list.
    660   */
    661   LockSemaphoreInfo(coder_semaphore);
    662   ResetSplayTreeIterator(coder_cache);
    663   p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
    664   for (i=0; p != (const CoderInfo *) NULL; )
    665   {
    666     if ((p->stealth == MagickFalse) &&
    667         (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
    668       coder_map[i++]=ConstantString(p->name);
    669     p=(const CoderInfo *) GetNextValueInSplayTree(coder_cache);
    670   }
    671   UnlockSemaphoreInfo(coder_semaphore);
    672   qsort((void *) coder_map,(size_t) i,sizeof(*coder_map),CoderCompare);
    673   coder_map[i]=(char *) NULL;
    674   *number_coders=(size_t) i;
    675   return(coder_map);
    676 }
    677 
    678 /*
    680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    681 %                                                                             %
    682 %                                                                             %
    683 %                                                                             %
    684 +   I s C o d e r T r e e I n s t a n t i a t e d                             %
    685 %                                                                             %
    686 %                                                                             %
    687 %                                                                             %
    688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    689 %
    690 %  IsCoderTreeInstantiated() determines if the coder tree is instantiated.  If
    691 %  not, it instantiates the tree and returns it.
    692 %
    693 %  The format of the IsCoderInstantiated method is:
    694 %
    695 %      MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
    696 %
    697 %  A description of each parameter follows.
    698 %
    699 %    o exception: return any errors or warnings in this structure.
    700 %
    701 */
    702 static MagickBooleanType IsCoderTreeInstantiated(ExceptionInfo *exception)
    703 {
    704   if (coder_cache == (SplayTreeInfo *) NULL)
    705     {
    706       if (coder_semaphore == (SemaphoreInfo *) NULL)
    707         ActivateSemaphoreInfo(&coder_semaphore);
    708       LockSemaphoreInfo(coder_semaphore);
    709       if (coder_cache == (SplayTreeInfo *) NULL)
    710         coder_cache=AcquireCoderCache(MagickCoderFilename,exception);
    711       UnlockSemaphoreInfo(coder_semaphore);
    712     }
    713   return(coder_cache != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
    714 }
    715 
    716 /*
    718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    719 %                                                                             %
    720 %                                                                             %
    721 %                                                                             %
    722 %  L i s t C o d e r I n f o                                                  %
    723 %                                                                             %
    724 %                                                                             %
    725 %                                                                             %
    726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    727 %
    728 %  ListCoderInfo() lists the coder info to a file.
    729 %
    730 %  The format of the ListCoderInfo coder is:
    731 %
    732 %      MagickBooleanType ListCoderInfo(FILE *file,ExceptionInfo *exception)
    733 %
    734 %  A description of each parameter follows.
    735 %
    736 %    o file:  An pointer to a FILE.
    737 %
    738 %    o exception: return any errors or warnings in this structure.
    739 %
    740 */
    741 MagickExport MagickBooleanType ListCoderInfo(FILE *file,
    742   ExceptionInfo *exception)
    743 {
    744   const char
    745     *path;
    746 
    747   const CoderInfo
    748     **coder_info;
    749 
    750   register ssize_t
    751     i;
    752 
    753   size_t
    754     number_coders;
    755 
    756   ssize_t
    757     j;
    758 
    759   if (file == (const FILE *) NULL)
    760     file=stdout;
    761   coder_info=GetCoderInfoList("*",&number_coders,exception);
    762   if (coder_info == (const CoderInfo **) NULL)
    763     return(MagickFalse);
    764   path=(const char *) NULL;
    765   for (i=0; i < (ssize_t) number_coders; i++)
    766   {
    767     if (coder_info[i]->stealth != MagickFalse)
    768       continue;
    769     if ((path == (const char *) NULL) ||
    770         (LocaleCompare(path,coder_info[i]->path) != 0))
    771       {
    772         if (coder_info[i]->path != (char *) NULL)
    773           (void) FormatLocaleFile(file,"\nPath: %s\n\n",coder_info[i]->path);
    774         (void) FormatLocaleFile(file,"Magick      Coder\n");
    775         (void) FormatLocaleFile(file,
    776           "-------------------------------------------------"
    777           "------------------------------\n");
    778       }
    779     path=coder_info[i]->path;
    780     (void) FormatLocaleFile(file,"%s",coder_info[i]->magick);
    781     for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 11; j++)
    782       (void) FormatLocaleFile(file," ");
    783     if (coder_info[i]->name != (char *) NULL)
    784       (void) FormatLocaleFile(file,"%s",coder_info[i]->name);
    785     (void) FormatLocaleFile(file,"\n");
    786   }
    787   coder_info=(const CoderInfo **) RelinquishMagickMemory((void *) coder_info);
    788   (void) fflush(file);
    789   return(MagickTrue);
    790 }
    791 
    792 /*
    794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    795 %                                                                             %
    796 %                                                                             %
    797 %                                                                             %
    798 +   L o a d C o d e r C a c h e                                               %
    799 %                                                                             %
    800 %                                                                             %
    801 %                                                                             %
    802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    803 %
    804 %  LoadCoderCache() loads the coder configurations which provides a
    805 %  mapping between coder attributes and a coder name.
    806 %
    807 %  The format of the LoadCoderCache coder is:
    808 %
    809 %      MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml,
    810 %        const char *filename,const size_t depth,ExceptionInfo *exception)
    811 %
    812 %  A description of each parameter follows:
    813 %
    814 %    o xml:  The coder list in XML format.
    815 %
    816 %    o filename:  The coder list filename.
    817 %
    818 %    o depth: depth of <include /> statements.
    819 %
    820 %    o exception: return any errors or warnings in this structure.
    821 %
    822 */
    823 static MagickBooleanType LoadCoderCache(SplayTreeInfo *cache,const char *xml,
    824   const char *filename,const size_t depth,ExceptionInfo *exception)
    825 {
    826   char
    827     keyword[MagickPathExtent],
    828     *token;
    829 
    830   const char
    831     *q;
    832 
    833   CoderInfo
    834     *coder_info;
    835 
    836   MagickStatusType
    837     status;
    838 
    839   size_t
    840     extent;
    841 
    842   /*
    843     Load the coder map file.
    844   */
    845   (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
    846     "Loading coder configuration file \"%s\" ...",filename);
    847   if (xml == (const char *) NULL)
    848     return(MagickFalse);
    849   status=MagickTrue;
    850   coder_info=(CoderInfo *) NULL;
    851   token=AcquireString(xml);
    852   extent=strlen(token)+MagickPathExtent;
    853   for (q=(char *) xml; *q != '\0'; )
    854   {
    855     /*
    856       Interpret XML.
    857     */
    858     GetNextToken(q,&q,extent,token);
    859     if (*token == '\0')
    860       break;
    861     (void) CopyMagickString(keyword,token,MagickPathExtent);
    862     if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
    863       {
    864         /*
    865           Doctype element.
    866         */
    867         while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
    868           GetNextToken(q,&q,extent,token);
    869         continue;
    870       }
    871     if (LocaleNCompare(keyword,"<!--",4) == 0)
    872       {
    873         /*
    874           Comment element.
    875         */
    876         while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
    877           GetNextToken(q,&q,extent,token);
    878         continue;
    879       }
    880     if (LocaleCompare(keyword,"<include") == 0)
    881       {
    882         /*
    883           Include element.
    884         */
    885         while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
    886         {
    887           (void) CopyMagickString(keyword,token,MagickPathExtent);
    888           GetNextToken(q,&q,extent,token);
    889           if (*token != '=')
    890             continue;
    891           GetNextToken(q,&q,extent,token);
    892           if (LocaleCompare(keyword,"file") == 0)
    893             {
    894               if (depth > 200)
    895                 (void) ThrowMagickException(exception,GetMagickModule(),
    896                   ConfigureError,"IncludeNodeNestedTooDeeply","`%s'",token);
    897               else
    898                 {
    899                   char
    900                     path[MagickPathExtent],
    901                     *file_xml;
    902 
    903                   GetPathComponent(filename,HeadPath,path);
    904                   if (*path != '\0')
    905                     (void) ConcatenateMagickString(path,DirectorySeparator,
    906                       MagickPathExtent);
    907                   if (*token == *DirectorySeparator)
    908                     (void) CopyMagickString(path,token,MagickPathExtent);
    909                   else
    910                     (void) ConcatenateMagickString(path,token,MagickPathExtent);
    911                   file_xml=FileToXML(path,~0UL);
    912                   if (file_xml != (char *) NULL)
    913                     {
    914                       status&=LoadCoderCache(cache,file_xml,path,depth+1,
    915                         exception);
    916                       file_xml=DestroyString(file_xml);
    917                     }
    918                 }
    919             }
    920         }
    921         continue;
    922       }
    923     if (LocaleCompare(keyword,"<coder") == 0)
    924       {
    925         /*
    926           Coder element.
    927         */
    928         coder_info=(CoderInfo *) AcquireMagickMemory(sizeof(*coder_info));
    929         if (coder_info == (CoderInfo *) NULL)
    930           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    931         (void) ResetMagickMemory(coder_info,0,sizeof(*coder_info));
    932         coder_info->path=ConstantString(filename);
    933         coder_info->exempt=MagickFalse;
    934         coder_info->signature=MagickCoreSignature;
    935         continue;
    936       }
    937     if (coder_info == (CoderInfo *) NULL)
    938       continue;
    939     if (LocaleCompare(keyword,"/>") == 0)
    940       {
    941         status=AddValueToSplayTree(cache,ConstantString(coder_info->magick),
    942           coder_info);
    943         if (status == MagickFalse)
    944           (void) ThrowMagickException(exception,GetMagickModule(),
    945             ResourceLimitError,"MemoryAllocationFailed","`%s'",
    946             coder_info->magick);
    947         coder_info=(CoderInfo *) NULL;
    948         continue;
    949       }
    950     GetNextToken(q,(const char **) NULL,extent,token);
    951     if (*token != '=')
    952       continue;
    953     GetNextToken(q,&q,extent,token);
    954     GetNextToken(q,&q,extent,token);
    955     switch (*keyword)
    956     {
    957       case 'M':
    958       case 'm':
    959       {
    960         if (LocaleCompare((char *) keyword,"magick") == 0)
    961           {
    962             coder_info->magick=ConstantString(token);
    963             break;
    964           }
    965         break;
    966       }
    967       case 'N':
    968       case 'n':
    969       {
    970         if (LocaleCompare((char *) keyword,"name") == 0)
    971           {
    972             coder_info->name=ConstantString(token);
    973             break;
    974           }
    975         break;
    976       }
    977       case 'S':
    978       case 's':
    979       {
    980         if (LocaleCompare((char *) keyword,"stealth") == 0)
    981           {
    982             coder_info->stealth=IsStringTrue(token);
    983             break;
    984           }
    985         break;
    986       }
    987       default:
    988         break;
    989     }
    990   }
    991   token=(char *) RelinquishMagickMemory(token);
    992   return(status != 0 ? MagickTrue : MagickFalse);
    993 }
    994