42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/client.h"
45#include "magick/coder.h"
46#include "magick/configure.h"
47#include "magick/draw.h"
48#include "magick/exception.h"
49#include "magick/exception-private.h"
50#include "magick/hashmap.h"
51#include "magick/log.h"
52#include "magick/memory_.h"
53#include "magick/option.h"
54#include "magick/semaphore.h"
55#include "magick/string_.h"
56#include "magick/splay-tree.h"
57#include "magick/token.h"
58#include "magick/utility.h"
59#include "magick/xml-tree.h"
60#include "magick/xml-tree-private.h"
65#define MagickCoderFilename "coder.xml"
87 {
"8BIMTEXT",
"META" },
88 {
"8BIMWTEXT",
"META" },
93 {
"APP1JPEG",
"META" },
102 {
"BRF",
"BRAILLE" },
114 {
"DATA",
"INLINE" },
132 {
"FRACTAL",
"PLASMA" },
139 {
"GRANITE",
"MAGICK" },
141 {
"GROUP4",
"TIFF" },
158 {
"IMPLICIT",
"***" },
160 {
"IPTCTEXT",
"META" },
161 {
"IPTCWTEXT",
"META" },
162 {
"ISOBRL",
"BRAILLE" },
163 {
"ISOBRL6",
"BRAILLE" },
181 {
"LOGO",
"MAGICK" },
197 {
"NETSCAPE",
"MAGICK" },
228 {
"RADIAL-GRADIENT",
"GRADIENT" },
235 {
"ROSE",
"MAGICK" },
239 {
"SPARSE-COLOR",
"TXT" },
244 {
"TIFF64",
"TIFF" },
247 {
"UBRL",
"BRAILLE" },
248 {
"UBRL6",
"BRAILLE" },
252 {
"WIZARD",
"MAGICK" },
253#if defined(MAGICKCORE_WINGDI32_DELEGATE)
262 {
"YCbCrA",
"YCbCr" }
274static MagickBooleanType
277#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
278static MagickBooleanType
279 LoadCoderCache(
SplayTreeInfo *,
const char *,
const char *,
const size_t,
310static void *DestroyCoderNode(
void *coder_info)
316 if (p->exempt == MagickFalse)
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);
325 return(RelinquishMagickMemory(p));
343 cache=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
346 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
348#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
356 options=GetConfigureOptions(filename,exception);
357 option=(
const StringInfo *) GetNextValueInLinkedList(options);
360 status&=LoadCoderCache(cache,(
const char *)
361 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
362 option=(
const StringInfo *) GetNextValueInLinkedList(options);
364 options=DestroyConfigureOptions(options);
370 for (i=0; i < (ssize_t) (
sizeof(CoderMap)/
sizeof(*CoderMap)); i++)
379 coder_info=(
CoderInfo *) AcquireMagickMemory(
sizeof(*coder_info));
382 (void) ThrowMagickException(exception,GetMagickModule(),
383 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",p->name);
386 (void) memset(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),
394 if (status == MagickFalse)
395 (void) ThrowMagickException(exception,GetMagickModule(),
396 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",coder_info->name);
419MagickExport MagickBooleanType CoderComponentGenesis(
void)
422 coder_semaphore=AllocateSemaphoreInfo();
444MagickExport
void CoderComponentTerminus(
void)
447 ActivateSemaphoreInfo(&coder_semaphore);
448 LockSemaphoreInfo(coder_semaphore);
450 coder_cache=DestroySplayTree(coder_cache);
451 UnlockSemaphoreInfo(coder_semaphore);
452 DestroySemaphoreInfo(&coder_semaphore);
480MagickExport
const CoderInfo *GetCoderInfo(
const char *name,
484 if (IsCoderTreeInstantiated(exception) == MagickFalse)
486 if ((name == (
const char *) NULL) || (LocaleCompare(name,
"*") == 0))
487 return((
const CoderInfo *) GetRootValueFromSplayTree(coder_cache));
488 return((
const CoderInfo *) GetValueFromSplayTree(coder_cache,name));
518static int CoderInfoCompare(
const void *x,
const void *y)
526 if (LocaleCompare((*p)->path,(*q)->path) == 0)
527 return(LocaleCompare((*p)->name,(*q)->name));
528 return(LocaleCompare((*p)->path,(*q)->path));
531MagickExport
const CoderInfo **GetCoderInfoList(
const char *pattern,
546 assert(pattern != (
char *) NULL);
547 assert(number_coders != (
size_t *) NULL);
548 if (IsEventLogging() != MagickFalse)
549 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
551 p=GetCoderInfo(
"*",exception);
554 coder_map=(
const CoderInfo **) AcquireQuantumMemory((
size_t)
555 GetNumberOfNodesInSplayTree(coder_cache)+1UL,
sizeof(*coder_map));
556 if (coder_map == (
const CoderInfo **) NULL)
561 LockSemaphoreInfo(coder_semaphore);
562 ResetSplayTreeIterator(coder_cache);
563 p=(
const CoderInfo *) GetNextValueInSplayTree(coder_cache);
564 for (i=0; p != (
const CoderInfo *) NULL; )
566 if ((p->stealth == MagickFalse) &&
567 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
569 p=(
const CoderInfo *) GetNextValueInSplayTree(coder_cache);
571 UnlockSemaphoreInfo(coder_semaphore);
572 qsort((
void *) coder_map,(
size_t) i,
sizeof(*coder_map),CoderInfoCompare);
574 *number_coders=(size_t) i;
606static int CoderCompare(
const void *x,
const void *y)
614 return(LocaleCompare(*p,*q));
617MagickExport
char **GetCoderList(
const char *pattern,
632 assert(pattern != (
char *) NULL);
633 assert(number_coders != (
size_t *) NULL);
634 if (IsEventLogging() != MagickFalse)
635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
637 p=GetCoderInfo(
"*",exception);
639 return((
char **) NULL);
640 coder_map=(
char **) AcquireQuantumMemory((
size_t)
641 GetNumberOfNodesInSplayTree(coder_cache)+1UL,
sizeof(*coder_map));
642 if (coder_map == (
char **) NULL)
643 return((
char **) NULL);
647 LockSemaphoreInfo(coder_semaphore);
648 ResetSplayTreeIterator(coder_cache);
649 p=(
const CoderInfo *) GetNextValueInSplayTree(coder_cache);
650 for (i=0; p != (
const CoderInfo *) NULL; )
652 if ((p->stealth == MagickFalse) &&
653 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
654 coder_map[i++]=ConstantString(p->name);
655 p=(
const CoderInfo *) GetNextValueInSplayTree(coder_cache);
657 UnlockSemaphoreInfo(coder_semaphore);
658 qsort((
void *) coder_map,(
size_t) i,
sizeof(*coder_map),CoderCompare);
659 coder_map[i]=(
char *) NULL;
660 *number_coders=(size_t) i;
687static MagickBooleanType IsCoderTreeInstantiated(
ExceptionInfo *exception)
692 ActivateSemaphoreInfo(&coder_semaphore);
693 LockSemaphoreInfo(coder_semaphore);
695 coder_cache=AcquireCoderCache(MagickCoderFilename,exception);
696 UnlockSemaphoreInfo(coder_semaphore);
698 return(coder_cache != (
SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
725MagickExport MagickBooleanType ListCoderInfo(FILE *file,
743 if (file == (
const FILE *) NULL)
745 coder_info=GetCoderInfoList(
"*",&number_coders,exception);
746 if (coder_info == (
const CoderInfo **) NULL)
748 path=(
const char *) NULL;
749 for (i=0; i < (ssize_t) number_coders; i++)
751 if (coder_info[i]->stealth != MagickFalse)
753 if ((path == (
const char *) NULL) ||
754 (LocaleCompare(path,coder_info[i]->path) != 0))
756 if (coder_info[i]->path != (
char *) NULL)
757 (void) FormatLocaleFile(file,
"\nPath: %s\n\n",coder_info[i]->path);
758 (void) FormatLocaleFile(file,
"Magick Coder\n");
759 (void) FormatLocaleFile(file,
760 "-------------------------------------------------"
761 "------------------------------\n");
763 path=coder_info[i]->path;
764 (void) FormatLocaleFile(file,
"%s",coder_info[i]->magick);
765 for (j=(ssize_t) strlen(coder_info[i]->magick); j <= 11; j++)
766 (
void) FormatLocaleFile(file,
" ");
767 if (coder_info[i]->name != (
char *) NULL)
768 (void) FormatLocaleFile(file,
"%s",coder_info[i]->name);
769 (void) FormatLocaleFile(file,
"\n");
771 coder_info=(
const CoderInfo **) RelinquishMagickMemory((
void *) coder_info);
776#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
807static MagickBooleanType LoadCoderCache(
SplayTreeInfo *cache,
const char *xml,
808 const char *filename,
const size_t depth,
ExceptionInfo *exception)
811 keyword[MaxTextExtent],
829 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
830 "Loading coder configuration file \"%s\" ...",filename);
831 if (xml == (
const char *) NULL)
835 token=AcquireString(xml);
836 extent=strlen(token)+MaxTextExtent;
837 for (q=(
char *) xml; *q !=
'\0'; )
842 (void) GetNextToken(q,&q,extent,token);
845 (void) CopyMagickString(keyword,token,MaxTextExtent);
846 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
851 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
852 (void) GetNextToken(q,&q,extent,token);
855 if (LocaleNCompare(keyword,
"<!--",4) == 0)
860 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
861 (void) GetNextToken(q,&q,extent,token);
864 if (LocaleCompare(keyword,
"<include") == 0)
869 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
871 (void) CopyMagickString(keyword,token,MaxTextExtent);
872 (void) GetNextToken(q,&q,extent,token);
875 (void) GetNextToken(q,&q,extent,token);
876 if (LocaleCompare(keyword,
"file") == 0)
878 if (depth > MagickMaxRecursionDepth)
879 (void) ThrowMagickException(exception,GetMagickModule(),
880 ConfigureError,
"IncludeNodeNestedTooDeeply",
"`%s'",token);
887 GetPathComponent(filename,HeadPath,path);
889 (void) ConcatenateMagickString(path,DirectorySeparator,
891 if (*token == *DirectorySeparator)
892 (void) CopyMagickString(path,token,MaxTextExtent);
894 (
void) ConcatenateMagickString(path,token,MaxTextExtent);
895 xml=FileToXML(path,~0UL);
896 if (xml != (
char *) NULL)
898 status&=LoadCoderCache(cache,xml,path,depth+1,
900 xml=(
char *) RelinquishMagickMemory(xml);
907 if (LocaleCompare(keyword,
"<coder") == 0)
912 coder_info=(
CoderInfo *) AcquireMagickMemory(
sizeof(*coder_info));
914 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
915 (void) memset(coder_info,0,
sizeof(*coder_info));
916 coder_info->path=ConstantString(filename);
917 coder_info->exempt=MagickFalse;
918 coder_info->signature=MagickCoreSignature;
923 if ((LocaleCompare(keyword,
"/>") == 0) ||
924 (LocaleCompare(keyword,
"</policy>") == 0))
926 status=AddValueToSplayTree(cache,ConstantString(
927 coder_info->magick),coder_info);
928 if (status == MagickFalse)
929 (void) ThrowMagickException(exception,GetMagickModule(),
930 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
935 (void) GetNextToken(q,(
const char **) NULL,extent,token);
938 (void) GetNextToken(q,&q,extent,token);
939 (void) GetNextToken(q,&q,extent,token);
945 if (LocaleCompare((
char *) keyword,
"magick") == 0)
947 coder_info->magick=ConstantString(token);
955 if (LocaleCompare((
char *) keyword,
"name") == 0)
957 coder_info->name=ConstantString(token);
965 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
967 coder_info->stealth=IsMagickTrue(token);
976 token=(
char *) RelinquishMagickMemory(token);
977 return(status != 0 ? MagickTrue : MagickFalse);