42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/client.h"
45#include "magick/configure.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/hashmap.h"
49#include "magick/log.h"
50#include "magick/memory_.h"
51#include "magick/nt-base-private.h"
52#include "magick/semaphore.h"
53#include "magick/string_.h"
54#include "magick/token.h"
55#include "magick/utility.h"
56#include "magick/version.h"
57#include "magick/xml-tree.h"
58#include "magick/xml-tree-private.h"
63#define ConfigureFilename "configure.xml"
87static MagickBooleanType
90#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
91static MagickBooleanType
92 LoadConfigureCache(
LinkedListInfo *,
const char *,
const char *,
const size_t,
122static inline void AddConfigureKey(
LinkedListInfo *cache,
const char *path,
123 const char *name,
const char *value)
128 configure_info=(
ConfigureInfo *) AcquireMagickMemory(
sizeof(*configure_info));
131 (void) memset(configure_info,0,
sizeof(*configure_info));
132 configure_info->path=(
char *) path;
133 configure_info->name=(
char *) name;
134 configure_info->value=(
char *) value;
135 configure_info->exempt=MagickTrue;
136 configure_info->signature=MagickCoreSignature;
137 (void) AppendValueToLinkedList(cache,configure_info);
149 cache=NewLinkedList(0);
151 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
152#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
163 options=GetConfigureOptions(filename,exception);
164 option=(
const StringInfo *) GetNextValueInLinkedList(options);
167 status=LoadConfigureCache(cache,(
const char *)
168 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
169 if (status == MagickTrue)
171 option=(
const StringInfo *) GetNextValueInLinkedList(options);
173 options=DestroyConfigureOptions(options);
179 AddConfigureKey(cache,
"[built-in]",
"NAME",
"ImageMagick");
183 AddConfigureKey(cache,
"[built-in]",
"QuantumDepth",GetMagickQuantumDepth(
185 AddConfigureKey(cache,
"[built-in]",
"FEATURES",GetMagickFeatures());
186 AddConfigureKey(cache,
"[built-in]",
"DELEGATES",GetMagickDelegates());
208MagickExport MagickBooleanType ConfigureComponentGenesis(
void)
211 configure_semaphore=AllocateSemaphoreInfo();
234static void *DestroyConfigureElement(
void *configure_info)
240 if (p->exempt == MagickFalse)
242 if (p->value != (
char *) NULL)
243 p->value=DestroyString(p->value);
244 if (p->name != (
char *) NULL)
245 p->name=DestroyString(p->name);
246 if (p->path != (
char *) NULL)
247 p->path=DestroyString(p->path);
250 return((
void *) NULL);
253MagickExport
void ConfigureComponentTerminus(
void)
256 ActivateSemaphoreInfo(&configure_semaphore);
257 LockSemaphoreInfo(configure_semaphore);
259 configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
261 UnlockSemaphoreInfo(configure_semaphore);
262 DestroySemaphoreInfo(&configure_semaphore);
289static void *DestroyOptions(
void *option)
291 return(DestroyStringInfo((
StringInfo *) option));
297 return(DestroyLinkedList(options,DestroyOptions));
329MagickExport
const ConfigureInfo *GetConfigureInfo(
const char *name,
336 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
341 LockSemaphoreInfo(configure_semaphore);
342 ResetLinkedListIterator(configure_cache);
343 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
344 if ((name == (
const char *) NULL) || (LocaleCompare(name,
"*") == 0))
346 UnlockSemaphoreInfo(configure_semaphore);
351 if (LocaleCompare(name,p->name) == 0)
353 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
356 (void) InsertValueInLinkedList(configure_cache,0,
357 RemoveElementByValueFromLinkedList(configure_cache,p));
358 UnlockSemaphoreInfo(configure_semaphore);
392#if defined(__cplusplus) || defined(c_plusplus)
396static int ConfigureInfoCompare(
const void *x,
const void *y)
404 if (LocaleCompare((*p)->path,(*q)->path) == 0)
405 return(LocaleCompare((*p)->name,(*q)->name));
406 return(LocaleCompare((*p)->path,(*q)->path));
409#if defined(__cplusplus) || defined(c_plusplus)
413MagickExport
const ConfigureInfo **GetConfigureInfoList(
const char *pattern,
428 assert(pattern != (
char *) NULL);
429 assert(number_options != (
size_t *) NULL);
430 if (IsEventLogging() != MagickFalse)
431 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
433 p=GetConfigureInfo(
"*",exception);
436 options=(
const ConfigureInfo **) AcquireQuantumMemory((
size_t)
437 GetNumberOfElementsInLinkedList(configure_cache)+1UL,
sizeof(*options));
443 LockSemaphoreInfo(configure_semaphore);
444 ResetLinkedListIterator(configure_cache);
445 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
448 if ((p->stealth == MagickFalse) &&
449 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
451 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
453 UnlockSemaphoreInfo(configure_semaphore);
454 qsort((
void *) options,(
size_t) i,
sizeof(*options),ConfigureInfoCompare);
456 *number_options=(size_t) i;
489#if defined(__cplusplus) || defined(c_plusplus)
493static int ConfigureCompare(
const void *x,
const void *y)
501 return(LocaleCompare(*p,*q));
504#if defined(__cplusplus) || defined(c_plusplus)
508MagickExport
char **GetConfigureList(
const char *pattern,
523 assert(pattern != (
char *) NULL);
524 assert(number_options != (
size_t *) NULL);
525 if (IsEventLogging() != MagickFalse)
526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
528 p=GetConfigureInfo(
"*",exception);
530 return((
char **) NULL);
531 options=(
char **) AcquireQuantumMemory((
size_t)
532 GetNumberOfElementsInLinkedList(configure_cache)+1UL,
sizeof(*options));
533 if (options == (
char **) NULL)
534 return((
char **) NULL);
535 LockSemaphoreInfo(configure_semaphore);
536 ResetLinkedListIterator(configure_cache);
537 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
540 if ((p->stealth == MagickFalse) &&
541 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
542 options[i++]=ConstantString(p->name);
543 p=(
const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
545 UnlockSemaphoreInfo(configure_semaphore);
546 qsort((
void *) options,(
size_t) i,
sizeof(*options),ConfigureCompare);
547 options[i]=(
char *) NULL;
548 *number_options=(size_t) i;
574MagickExport
char *GetConfigureOption(
const char *option)
585 assert(option != (
const char *) NULL);
586 if (IsEventLogging() != MagickFalse)
587 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",option);
588 exception=AcquireExceptionInfo();
589 configure_info=GetConfigureInfo(option,exception);
590 exception=DestroyExceptionInfo(exception);
592 return((
char *) NULL);
593 value=GetConfigureValue(configure_info);
594 if ((value == (
const char *) NULL) || (*value ==
'\0'))
595 return((
char *) NULL);
596 return(ConstantString(value));
625MagickExport
LinkedListInfo *GetConfigureOptions(
const char *filename,
641 assert(filename != (
const char *) NULL);
643 if (IsEventLogging() != MagickFalse)
644 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",filename);
645 (void) CopyMagickString(path,filename,MaxTextExtent);
649 options=NewLinkedList(0);
650 paths=GetConfigurePaths(filename,exception);
653 ResetLinkedListIterator(paths);
654 element=(
const char *) GetNextValueInLinkedList(paths);
655 while (element != (
const char *) NULL)
657 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",element,filename);
658 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
659 "Searching for configure file: \"%s\"",path);
660 xml=ConfigureFileToStringInfo(path);
662 (void) AppendValueToLinkedList(options,xml);
663 element=(
const char *) GetNextValueInLinkedList(paths);
665 paths=DestroyLinkedList(paths,RelinquishMagickMemory);
667#if defined(MAGICKCORE_WINDOWS_SUPPORT)
668 if (GetNumberOfElementsInLinkedList(options) == 0)
673 blob=(
char *) NTResourceToBlob(filename);
674 if (blob != (
char *) NULL)
676 xml=AcquireStringInfo(0);
677 SetStringInfoLength(xml,strlen(blob)+1);
678 SetStringInfoDatum(xml,(
unsigned char *) blob);
679 SetStringInfoPath(xml,filename);
680 (void) AppendValueToLinkedList(options,xml);
684 if (GetNumberOfElementsInLinkedList(options) == 0)
685 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
686 "UnableToOpenConfigureFile",
"`%s'",filename);
687 ResetLinkedListIterator(options);
717MagickExport
LinkedListInfo *GetConfigurePaths(
const char *filename,
726 assert(filename != (
const char *) NULL);
728 if (IsEventLogging() != MagickFalse)
729 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",filename);
731 (void) CopyMagickString(path,filename,MaxTextExtent);
732 paths=NewLinkedList(0);
740 configure_path=GetEnvironmentValue(
"MAGICK_CONFIGURE_PATH");
741 if (configure_path != (
char *) NULL)
747 for (p=configure_path-1; p != (
char *) NULL; )
749 (void) CopyMagickString(path,p+1,MaxTextExtent);
750 q=strchr(path,DirectoryListSeparator);
751 if (q != (
char *) NULL)
753 q=path+strlen(path)-1;
754 if ((q >= path) && (*q != *DirectorySeparator))
755 (void) ConcatenateMagickString(path,DirectorySeparator,
757 (void) AppendValueToLinkedList(paths,ConstantString(path));
758 p=strchr(p+1,DirectoryListSeparator);
760 configure_path=DestroyString(configure_path);
763#if defined(MAGICKCORE_INSTALLED_SUPPORT)
764#if defined(MAGICKCORE_SHARE_PATH)
765 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
767#if defined(MAGICKCORE_SHAREARCH_PATH)
768 (void) AppendValueToLinkedList(paths,ConstantString(
769 MAGICKCORE_SHAREARCH_PATH));
771#if defined(MAGICKCORE_CONFIGURE_PATH)
772 (void) AppendValueToLinkedList(paths,ConstantString(
773 MAGICKCORE_CONFIGURE_PATH));
775#if defined(MAGICKCORE_DOCUMENTATION_PATH)
776 (void) AppendValueToLinkedList(paths,ConstantString(
777 MAGICKCORE_DOCUMENTATION_PATH));
779#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
787 key_value=NTRegistryKeyLookup(
"ConfigurePath");
788 if (key_value != (
unsigned char *) NULL)
790 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",(
char *) key_value,
792 (void) AppendValueToLinkedList(paths,ConstantString(path));
793 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
805 home=GetEnvironmentValue(
"MAGICK_HOME");
806 if (home != (
char *) NULL)
808#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
809 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",home,
811 (void) AppendValueToLinkedList(paths,ConstantString(path));
813 (void) FormatLocaleString(path,MaxTextExtent,
"%s/etc/%s/",home,
814 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
815 (void) AppendValueToLinkedList(paths,ConstantString(path));
816 (void) FormatLocaleString(path,MaxTextExtent,
"%s/share/%s/",home,
817 MAGICKCORE_SHARE_RELATIVE_PATH);
818 (void) AppendValueToLinkedList(paths,ConstantString(path));
819 (void) FormatLocaleString(path,MaxTextExtent,
"%s",
820 MAGICKCORE_SHAREARCH_PATH);
821 (void) AppendValueToLinkedList(paths,ConstantString(path));
823 home=DestroyString(home);
826 if (*GetClientPath() !=
'\0')
828#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
829 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",GetClientPath(),
831 (void) AppendValueToLinkedList(paths,ConstantString(path));
834 prefix[MaxTextExtent];
839 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
840 ChopPathComponents(prefix,1);
841 (void) FormatLocaleString(path,MaxTextExtent,
"%s/etc/%s/",prefix,
842 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
843 (void) AppendValueToLinkedList(paths,ConstantString(path));
844 (void) FormatLocaleString(path,MaxTextExtent,
"%s/share/%s/",prefix,
845 MAGICKCORE_SHARE_RELATIVE_PATH);
846 (void) AppendValueToLinkedList(paths,ConstantString(path));
847 (void) FormatLocaleString(path,MaxTextExtent,
"%s",
848 MAGICKCORE_SHAREARCH_PATH);
849 (void) AppendValueToLinkedList(paths,ConstantString(path));
855 (void) AppendValueToLinkedList(paths,ConstantString(
""));
861 home=GetEnvironmentValue(
"XDG_CONFIG_HOME");
862#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
863 if (home == (
char *) NULL)
864 home=GetEnvironmentValue(
"LOCALAPPDATA");
865 if (home == (
char *) NULL)
866 home=GetEnvironmentValue(
"APPDATA");
867 if (home == (
char *) NULL)
868 home=GetEnvironmentValue(
"USERPROFILE");
870 if (home != (
char *) NULL)
875 (void) FormatLocaleString(path,MaxTextExtent,
"%s%sImageMagick%s",
876 home,DirectorySeparator,DirectorySeparator);
877 (void) AppendValueToLinkedList(paths,ConstantString(path));
878 home=DestroyString(home);
880 home=GetEnvironmentValue(
"HOME");
881 if (home != (
char *) NULL)
886 (void) FormatLocaleString(path,MaxTextExtent,
887 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
888 DirectorySeparator,DirectorySeparator);
889 (void) AppendValueToLinkedList(paths,ConstantString(path));
893 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s.magick%s",home,
894 DirectorySeparator,DirectorySeparator);
895 (void) AppendValueToLinkedList(paths,ConstantString(path));
896 home=DestroyString(home);
899#if defined(MAGICKCORE_WINDOWS_SUPPORT)
902 module_path[MaxTextExtent];
904#if defined(_MAGICKDLL_)
905 if ((NTGetModulePath(
"CORE_RL_magick_.dll",module_path) != MagickFalse) ||
906 (NTGetModulePath(
"CORE_DB_magick_.dll",module_path) != MagickFalse))
914 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
916 key_value=NTRegistryKeyLookup(
"ConfigurePath");
917 if (key_value == (
unsigned char *) NULL)
918 (void) AppendValueToLinkedList(paths,ConstantString(path));
920 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
923 if (NTGetModulePath(
"Magick.dll",module_path) != MagickFalse)
928 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
930 (void) AppendValueToLinkedList(paths,ConstantString(path));
931 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
932 "\\inc\\lib\\auto\\Image\\Magick\\");
933 (void) AppendValueToLinkedList(paths,ConstantString(path));
937 if (GetNumberOfElementsInLinkedList(paths) == 0)
938 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
939 "no configuration paths found",
"`%s'",filename);
965MagickExport
const char *GetConfigureValue(
const ConfigureInfo *configure_info)
967 if (IsEventLogging() != MagickFalse)
968 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
970 assert(configure_info->signature == MagickCoreSignature);
971 return(configure_info->value);
997static MagickBooleanType IsConfigureCacheInstantiated(
ExceptionInfo *exception)
1002 ActivateSemaphoreInfo(&configure_semaphore);
1003 LockSemaphoreInfo(configure_semaphore);
1005 configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1006 UnlockSemaphoreInfo(configure_semaphore);
1008 return(configure_cache != (
LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1035MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1055 if (file == (
const FILE *) NULL)
1057 configure_info=GetConfigureInfoList(
"*",&number_options,exception);
1059 return(MagickFalse);
1060 path=(
const char *) NULL;
1061 for (i=0; i < (ssize_t) number_options; i++)
1063 if (configure_info[i]->stealth != MagickFalse)
1065 if ((path == (
const char *) NULL) ||
1066 (LocaleCompare(path,configure_info[i]->path) != 0))
1068 if (configure_info[i]->path != (
char *) NULL)
1069 (void) FormatLocaleFile(file,
"\nPath: %s\n\n",
1070 configure_info[i]->path);
1071 (void) FormatLocaleFile(file,
"Name Value\n");
1072 (void) FormatLocaleFile(file,
1073 "-------------------------------------------------"
1074 "------------------------------\n");
1076 path=configure_info[i]->path;
1078 if (configure_info[i]->name != (
char *) NULL)
1079 name=configure_info[i]->name;
1080 (void) FormatLocaleFile(file,
"%s",name);
1081 for (j=(ssize_t) strlen(name); j <= 13; j++)
1082 (
void) FormatLocaleFile(file,
" ");
1083 (void) FormatLocaleFile(file,
" ");
1085 if (configure_info[i]->value != (
char *) NULL)
1086 value=configure_info[i]->value;
1087 (void) FormatLocaleFile(file,
"%s",value);
1088 (void) FormatLocaleFile(file,
"\n");
1090 (void) fflush(file);
1091 configure_info=(
const ConfigureInfo **) RelinquishMagickMemory((
void *)
1096#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
1128static MagickBooleanType LoadConfigureCache(
LinkedListInfo *cache,
1129 const char *xml,
const char *filename,
const size_t depth,
1133 keyword[MaxTextExtent],
1151 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1152 "Loading configure file \"%s\" ...",filename);
1155 token=AcquireString(xml);
1156 extent=strlen(token)+MaxTextExtent;
1157 for (q=(
char *) xml; *q !=
'\0'; )
1162 (void) GetNextToken(q,&q,extent,token);
1165 (void) CopyMagickString(keyword,token,MaxTextExtent);
1166 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
1171 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
1172 (void) GetNextToken(q,&q,extent,token);
1175 if (LocaleNCompare(keyword,
"<!--",4) == 0)
1180 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
1181 (void) GetNextToken(q,&q,extent,token);
1184 if (LocaleCompare(keyword,
"<include") == 0)
1189 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
1191 (void) CopyMagickString(keyword,token,MaxTextExtent);
1192 (void) GetNextToken(q,&q,extent,token);
1195 (void) GetNextToken(q,&q,extent,token);
1196 if (LocaleCompare(keyword,
"file") == 0)
1198 if (depth > MagickMaxRecursionDepth)
1199 (void) ThrowMagickException(exception,GetMagickModule(),
1200 ConfigureError,
"IncludeElementNestedTooDeeply",
"`%s'",token);
1204 path[MaxTextExtent],
1207 GetPathComponent(filename,HeadPath,path);
1209 (void) ConcatenateMagickString(path,DirectorySeparator,
1211 if (*token == *DirectorySeparator)
1212 (void) CopyMagickString(path,token,MaxTextExtent);
1214 (
void) ConcatenateMagickString(path,token,MaxTextExtent);
1215 xml=FileToXML(path,~0UL);
1216 if (xml != (
char *) NULL)
1218 status&=LoadConfigureCache(cache,xml,path,
1220 xml=(
char *) RelinquishMagickMemory(xml);
1227 if (LocaleCompare(keyword,
"<configure") == 0)
1233 sizeof(*configure_info));
1235 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1236 (void) memset(configure_info,0,
sizeof(*configure_info));
1237 configure_info->path=ConstantString(filename);
1238 configure_info->exempt=MagickFalse;
1239 configure_info->signature=MagickCoreSignature;
1244 if ((LocaleCompare(keyword,
"/>") == 0) ||
1245 (LocaleCompare(keyword,
"</policy>") == 0))
1247 status=AppendValueToLinkedList(cache,configure_info);
1248 if (status == MagickFalse)
1249 (void) ThrowMagickException(exception,GetMagickModule(),
1250 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
1251 configure_info->name);
1258 (void) GetNextToken(q,(
const char **) NULL,extent,token);
1261 (void) GetNextToken(q,&q,extent,token);
1262 (void) GetNextToken(q,&q,extent,token);
1268 if (LocaleCompare((
char *) keyword,
"name") == 0)
1270 configure_info->name=ConstantString(token);
1278 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
1280 configure_info->stealth=IsMagickTrue(token);
1288 if (LocaleCompare((
char *) keyword,
"value") == 0)
1290 configure_info->value=ConstantString(token);
1299 token=(
char *) RelinquishMagickMemory(token);
1300 return(status != 0 ? MagickTrue : MagickFalse);