42#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
46#include "MagickCore/configure-private.h"
47#include "MagickCore/exception.h"
48#include "MagickCore/exception-private.h"
49#include "MagickCore/linked-list.h"
50#include "MagickCore/linked-list-private.h"
51#include "MagickCore/log.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/semaphore.h"
54#include "MagickCore/string_.h"
55#include "MagickCore/string-private.h"
56#include "MagickCore/token.h"
57#include "MagickCore/utility.h"
58#include "MagickCore/utility-private.h"
59#include "MagickCore/version.h"
60#include "MagickCore/xml-tree.h"
61#include "MagickCore/xml-tree-private.h"
66#define ConfigureFilename "configure.xml"
91static MagickBooleanType
94#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
95static MagickBooleanType
96 LoadConfigureCache(
LinkedListInfo *,
const char *,
const char *,
const size_t,
126static inline void AddConfigureKey(
LinkedListInfo *cache,
const char *path,
127 const char *name,
const char *value,MagickBooleanType exempt)
132 configure_info=(
ConfigureInfo *) AcquireMagickMemory(
sizeof(*configure_info));
135 (void) memset(configure_info,0,
sizeof(*configure_info));
136 if (exempt == MagickTrue)
138 configure_info->path=(
char *) path;
139 configure_info->name=(
char *) name;
140 configure_info->value=(
char *) value;
144 configure_info->path=ConstantString(path);
145 configure_info->name=ConstantString(name);
146 configure_info->value=ConstantString(value);
148 configure_info->exempt=exempt;
149 configure_info->signature=MagickCoreSignature;
150 (void) AppendValueToLinkedList(cache,configure_info);
157 head_path[MagickPathExtent],
158 path[MagickPathExtent];
166 cache=NewLinkedList(0);
167#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
178 options=GetConfigureOptions(filename,exception);
179 option=(
const StringInfo *) GetNextValueInLinkedList(options);
182 status=LoadConfigureCache(cache,(
const char *)
183 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
184 if (status == MagickTrue)
186 option=(
const StringInfo *) GetNextValueInLinkedList(options);
188 options=DestroyConfigureOptions(options);
191 magick_unreferenced(filename);
192 magick_unreferenced(exception);
197 AddConfigureKey(cache,
"[built-in]",
"NAME",
"ImageMagick",MagickTrue);
201 AddConfigureKey(cache,
"[built-in]",
"QuantumDepth",GetMagickQuantumDepth(
202 (
size_t *)NULL),MagickTrue);
203 AddConfigureKey(cache,
"[built-in]",
"FEATURES",GetMagickFeatures(),
205 AddConfigureKey(cache,
"[built-in]",
"DELEGATES",GetMagickDelegates(),
207 (void) AcquireUniqueFilename(path);
208 GetPathComponent(path,HeadPath,head_path);
209 AddConfigureKey(cache,
"[built-in]",
"MAGICK_TEMPORARY_PATH",head_path,
232MagickPrivate MagickBooleanType ConfigureComponentGenesis(
void)
235 configure_semaphore=AcquireSemaphoreInfo();
258static void *DestroyConfigureElement(
void *configure_info)
264 if (p->exempt == MagickFalse)
266 if (p->value != (
char *) NULL)
267 p->value=DestroyString(p->value);
268 if (p->name != (
char *) NULL)
269 p->name=DestroyString(p->name);
270 if (p->path != (
char *) NULL)
271 p->path=DestroyString(p->path);
274 return((
void *) NULL);
277MagickPrivate
void ConfigureComponentTerminus(
void)
280 ActivateSemaphoreInfo(&configure_semaphore);
281 LockSemaphoreInfo(configure_semaphore);
283 configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
285 UnlockSemaphoreInfo(configure_semaphore);
286 RelinquishSemaphoreInfo(&configure_semaphore);
313static void *DestroyOptions(
void *option)
315 return(DestroyStringInfo((
StringInfo *) option));
321 return(DestroyLinkedList(options,DestroyOptions));
353MagickExport
const ConfigureInfo *GetConfigureInfo(
const char *name,
363 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
369 LockSemaphoreInfo(configure_semaphore);
370 p=GetHeadElementInLinkedList(configure_cache);
371 if ((name == (
const char *) NULL) || (LocaleCompare(name,
"*") == 0))
373 UnlockSemaphoreInfo(configure_semaphore);
381 if (LocaleCompare(name,option->name) == 0)
388 SetHeadElementInLinkedList(configure_cache,p);
389 UnlockSemaphoreInfo(configure_semaphore);
423#if defined(__cplusplus) || defined(c_plusplus)
427static int ConfigureInfoCompare(
const void *x,
const void *y)
435 if (LocaleCompare((*p)->path,(*q)->path) == 0)
436 return(LocaleCompare((*p)->name,(*q)->name));
437 return(LocaleCompare((*p)->path,(*q)->path));
440#if defined(__cplusplus) || defined(c_plusplus)
444MagickExport
const ConfigureInfo **GetConfigureInfoList(
const char *pattern,
456 assert(pattern != (
char *) NULL);
457 assert(number_options != (
size_t *) NULL);
458 if (IsEventLogging() != MagickFalse)
459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
461 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
463 options=(
const ConfigureInfo **) AcquireQuantumMemory((
size_t)
464 GetNumberOfElementsInLinkedList(configure_cache)+1UL,
sizeof(*options));
467 LockSemaphoreInfo(configure_semaphore);
468 p=GetHeadElementInLinkedList(configure_cache);
475 if ((option->stealth == MagickFalse) &&
476 (GlobExpression(option->name,pattern,MagickFalse) != MagickFalse))
480 UnlockSemaphoreInfo(configure_semaphore);
482 options=(
const ConfigureInfo **) RelinquishMagickMemory((
void*) options);
485 qsort((
void *) options,(
size_t) i,
sizeof(*options),ConfigureInfoCompare);
488 *number_options=(size_t) i;
521#if defined(__cplusplus) || defined(c_plusplus)
525static int ConfigureCompare(
const void *x,
const void *y)
533 return(LocaleCompare(*p,*q));
536#if defined(__cplusplus) || defined(c_plusplus)
540MagickExport
char **GetConfigureList(
const char *pattern,
552 assert(pattern != (
char *) NULL);
553 assert(number_options != (
size_t *) NULL);
554 if (IsEventLogging() != MagickFalse)
555 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",pattern);
557 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
558 return((
char **) NULL);
559 options=(
char **) AcquireQuantumMemory((
size_t)
560 GetNumberOfElementsInLinkedList(configure_cache)+1UL,
sizeof(*options));
561 if (options == (
char **) NULL)
562 return((
char **) NULL);
563 LockSemaphoreInfo(configure_semaphore);
564 p=GetHeadElementInLinkedList(configure_cache);
571 if ((option->stealth == MagickFalse) &&
572 (GlobExpression(option->name,pattern,MagickFalse) != MagickFalse))
573 options[i++]=ConstantString(option->name);
576 UnlockSemaphoreInfo(configure_semaphore);
578 options=(
char **) RelinquishMagickMemory(options);
581 qsort((
void *) options,(
size_t) i,
sizeof(*options),ConfigureCompare);
582 options[i]=(
char *) NULL;
584 *number_options=(size_t) i;
610MagickExport
char *GetConfigureOption(
const char *option)
621 assert(option != (
const char *) NULL);
622 if (IsEventLogging() != MagickFalse)
623 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",option);
624 exception=AcquireExceptionInfo();
625 configure_info=GetConfigureInfo(option,exception);
626 exception=DestroyExceptionInfo(exception);
628 return((
char *) NULL);
629 value=GetConfigureValue(configure_info);
630 if ((value == (
const char *) NULL) || (*value ==
'\0'))
631 return((
char *) NULL);
632 return(ConstantString(value));
661MagickExport
LinkedListInfo *GetConfigureOptions(
const char *filename,
665 path[MagickPathExtent];
677 assert(filename != (
const char *) NULL);
679 if (IsEventLogging() != MagickFalse)
680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",filename);
681 (void) CopyMagickString(path,filename,MagickPathExtent);
685 options=NewLinkedList(0);
686 paths=GetConfigurePaths(filename,exception);
689 ResetLinkedListIterator(paths);
690 element=(
const char *) GetNextValueInLinkedList(paths);
691 while (element != (
const char *) NULL)
693 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",element,
695 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
696 "Searching for configure file: \"%s\"",path);
697 xml=ConfigureFileToStringInfo(path);
699 (void) AppendValueToLinkedList(options,xml);
700 element=(
const char *) GetNextValueInLinkedList(paths);
702 paths=DestroyLinkedList(paths,RelinquishMagickMemory);
704#if defined(MAGICKCORE_WINDOWS_SUPPORT)
705 if (GetNumberOfElementsInLinkedList(options) == 0)
710 blob=(
char *) NTResourceToBlob(filename);
711 if (blob != (
char *) NULL)
713 xml=AcquireStringInfo(0);
714 SetStringInfoLength(xml,strlen(blob)+1);
715 SetStringInfoDatum(xml,(
unsigned char *) blob);
716 SetStringInfoPath(xml,filename);
717 (void) AppendValueToLinkedList(options,xml);
721 if (GetNumberOfElementsInLinkedList(options) == 0)
722 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
723 "UnableToOpenConfigureFile",
"`%s'",filename);
724 ResetLinkedListIterator(options);
754MagickExport
LinkedListInfo *GetConfigurePaths(
const char *filename,
758 path[MagickPathExtent];
763 assert(filename != (
const char *) NULL);
765 if (IsEventLogging() != MagickFalse)
766 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",filename);
767 (void) CopyMagickString(path,filename,MagickPathExtent);
768 paths=NewLinkedList(0);
776 configure_path=GetEnvironmentValue(
"MAGICK_CONFIGURE_PATH");
777 if (configure_path != (
char *) NULL)
783 for (p=configure_path-1; p != (
char *) NULL; )
785 (void) CopyMagickString(path,p+1,MagickPathExtent);
786 q=strchr(path,DirectoryListSeparator);
787 if (q != (
char *) NULL)
789 q=path+strlen(path)-1;
790 if ((q >= path) && (*q != *DirectorySeparator))
791 (void) ConcatenateMagickString(path,DirectorySeparator,
793 (void) AppendValueToLinkedList(paths,ConstantString(path));
794 p=strchr(p+1,DirectoryListSeparator);
796 configure_path=DestroyString(configure_path);
799#if defined(MAGICKCORE_INSTALLED_SUPPORT)
800#if defined(MAGICKCORE_SHARE_PATH)
801 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
803#if defined(MAGICKCORE_SHAREARCH_PATH)
804 (void) AppendValueToLinkedList(paths,ConstantString(
805 MAGICKCORE_SHAREARCH_PATH));
807#if defined(MAGICKCORE_CONFIGURE_PATH)
808 (void) AppendValueToLinkedList(paths,ConstantString(
809 MAGICKCORE_CONFIGURE_PATH));
811#if defined(MAGICKCORE_DOCUMENTATION_PATH)
812 (void) AppendValueToLinkedList(paths,ConstantString(
813 MAGICKCORE_DOCUMENTATION_PATH));
815#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
823 key_value=NTRegistryKeyLookup(
"ConfigurePath");
824 if (key_value != (
unsigned char *) NULL)
826 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",(
char *)
827 key_value,DirectorySeparator);
828 (void) AppendValueToLinkedList(paths,ConstantString(path));
829 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
841 home=GetEnvironmentValue(
"MAGICK_HOME");
842 if (home != (
char *) NULL)
844#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
845 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",home,
847 (void) AppendValueToLinkedList(paths,ConstantString(path));
849 (void) FormatLocaleString(path,MagickPathExtent,
"%s/etc/%s/",home,
850 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
851 (void) AppendValueToLinkedList(paths,ConstantString(path));
852 (void) FormatLocaleString(path,MagickPathExtent,
"%s/share/%s/",home,
853 MAGICKCORE_SHARE_RELATIVE_PATH);
854 (void) AppendValueToLinkedList(paths,ConstantString(path));
855 (void) FormatLocaleString(path,MagickPathExtent,
"%s",
856 MAGICKCORE_SHAREARCH_PATH);
857 (void) AppendValueToLinkedList(paths,ConstantString(path));
859 home=DestroyString(home);
862 if (*GetClientPath() !=
'\0')
864#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
865 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",GetClientPath(),
867 (void) AppendValueToLinkedList(paths,ConstantString(path));
870 prefix[MagickPathExtent];
875 (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
876 ChopPathComponents(prefix,1);
877 (void) FormatLocaleString(path,MagickPathExtent,
"%s/etc/%s/",prefix,
878 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
879 (void) AppendValueToLinkedList(paths,ConstantString(path));
880 (void) FormatLocaleString(path,MagickPathExtent,
"%s/share/%s/",prefix,
881 MAGICKCORE_SHARE_RELATIVE_PATH);
882 (void) AppendValueToLinkedList(paths,ConstantString(path));
883 (void) FormatLocaleString(path,MagickPathExtent,
"%s",
884 MAGICKCORE_SHAREARCH_PATH);
885 (void) AppendValueToLinkedList(paths,ConstantString(path));
891 (void) AppendValueToLinkedList(paths,ConstantString(
""));
897 home=GetEnvironmentValue(
"XDG_CONFIG_HOME");
898#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
899 if (home == (
char *) NULL)
900 home=GetEnvironmentValue(
"LOCALAPPDATA");
901 if (home == (
char *) NULL)
902 home=GetEnvironmentValue(
"APPDATA");
903 if (home == (
char *) NULL)
904 home=GetEnvironmentValue(
"USERPROFILE");
906 if (home != (
char *) NULL)
911 (void) FormatLocaleString(path,MagickPathExtent,
"%s%sImageMagick%s",
912 home,DirectorySeparator,DirectorySeparator);
913 (void) AppendValueToLinkedList(paths,ConstantString(path));
914 home=DestroyString(home);
916 home=GetEnvironmentValue(
"HOME");
917 if (home != (
char *) NULL)
922 (void) FormatLocaleString(path,MagickPathExtent,
923 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
924 DirectorySeparator,DirectorySeparator);
925 (void) AppendValueToLinkedList(paths,ConstantString(path));
926 home=DestroyString(home);
929#if defined(MAGICKCORE_WINDOWS_SUPPORT)
932 module_path[MagickPathExtent];
934#if defined(_MAGICKDLL_)
935 if ((NTGetModulePath(
"CORE_RL_MagickCore_.dll",module_path) != MagickFalse) ||
936 (NTGetModulePath(
"CORE_DB_MagickCore_.dll",module_path) != MagickFalse))
944 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",module_path,
946 key_value=NTRegistryKeyLookup(
"ConfigurePath");
947 if (key_value == (
unsigned char *) NULL)
948 (void) AppendValueToLinkedList(paths,ConstantString(path));
950 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
953 if (NTGetModulePath(
"Magick.dll",module_path) != MagickFalse)
958 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",module_path,
960 (void) AppendValueToLinkedList(paths,ConstantString(path));
961 (void) FormatLocaleString(path,MagickPathExtent,
"%s%s",module_path,
962 "\\inc\\lib\\auto\\Image\\Magick\\");
963 (void) AppendValueToLinkedList(paths,ConstantString(path));
967 if (GetNumberOfElementsInLinkedList(paths) == 0)
968 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
969 "no configuration paths found",
"`%s'",filename);
995MagickExport
const char *GetConfigureValue(
const ConfigureInfo *configure_info)
997 if (IsEventLogging() != MagickFalse)
998 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
1000 assert(configure_info->signature == MagickCoreSignature);
1001 return(configure_info->value);
1027static MagickBooleanType IsConfigureCacheInstantiated(
ExceptionInfo *exception)
1032 ActivateSemaphoreInfo(&configure_semaphore);
1033 LockSemaphoreInfo(configure_semaphore);
1035 configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1036 UnlockSemaphoreInfo(configure_semaphore);
1038 return(configure_cache != (
LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1065MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1085 if (file == (
const FILE *) NULL)
1087 configure_info=GetConfigureInfoList(
"*",&number_options,exception);
1089 return(MagickFalse);
1090 path=(
const char *) NULL;
1091 for (i=0; i < (ssize_t) number_options; i++)
1093 if (configure_info[i]->stealth != MagickFalse)
1095 if ((path == (
const char *) NULL) ||
1096 (LocaleCompare(path,configure_info[i]->path) != 0))
1098 if (configure_info[i]->path != (
char *) NULL)
1099 (void) FormatLocaleFile(file,
"\nPath: %s\n\n",
1100 configure_info[i]->path);
1101 (void) FormatLocaleFile(file,
"Name Value\n");
1102 (void) FormatLocaleFile(file,
1103 "-------------------------------------------------"
1104 "------------------------------\n");
1106 path=configure_info[i]->path;
1108 if (configure_info[i]->name != (
char *) NULL)
1109 name=configure_info[i]->name;
1110 (void) FormatLocaleFile(file,
"%s",name);
1111 for (j=(ssize_t) strlen(name); j <= 20; j++)
1112 (
void) FormatLocaleFile(file,
" ");
1113 (void) FormatLocaleFile(file,
" ");
1115 if (configure_info[i]->value != (
char *) NULL)
1116 value=configure_info[i]->value;
1117 (void) FormatLocaleFile(file,
"%s",value);
1118 (void) FormatLocaleFile(file,
"\n");
1120 (void) fflush(file);
1121 configure_info=(
const ConfigureInfo **) RelinquishMagickMemory((
void *)
1126#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
1158static MagickBooleanType LoadConfigureCache(
LinkedListInfo *cache,
1159 const char *xml,
const char *filename,
const size_t depth,
1163 keyword[MagickPathExtent],
1181 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1182 "Loading configure file \"%s\" ...",filename);
1185 token=AcquireString(xml);
1186 extent=strlen(token)+MagickPathExtent;
1187 for (q=(
char *) xml; *q !=
'\0'; )
1192 (void) GetNextToken(q,&q,extent,token);
1195 (void) CopyMagickString(keyword,token,MagickPathExtent);
1196 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
1201 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
1202 (void) GetNextToken(q,&q,extent,token);
1205 if (LocaleNCompare(keyword,
"<!--",4) == 0)
1210 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
1211 (void) GetNextToken(q,&q,extent,token);
1214 if (LocaleCompare(keyword,
"<include") == 0)
1219 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
1221 (void) CopyMagickString(keyword,token,MagickPathExtent);
1222 (void) GetNextToken(q,&q,extent,token);
1225 (void) GetNextToken(q,&q,extent,token);
1226 if (LocaleCompare(keyword,
"file") == 0)
1228 if (depth > MagickMaxRecursionDepth)
1229 (void) ThrowMagickException(exception,GetMagickModule(),
1230 ConfigureError,
"IncludeElementNestedTooDeeply",
"`%s'",token);
1234 path[MagickPathExtent],
1237 GetPathComponent(filename,HeadPath,path);
1239 (void) ConcatenateMagickString(path,DirectorySeparator,
1241 if (*token == *DirectorySeparator)
1242 (void) CopyMagickString(path,token,MagickPathExtent);
1244 (
void) ConcatenateMagickString(path,token,MagickPathExtent);
1245 file_xml=FileToXML(path,~0UL);
1246 if (file_xml != (
char *) NULL)
1248 status&=(MagickStatusType) LoadConfigureCache(cache,
1249 file_xml,path,depth+1,exception);
1250 file_xml=DestroyString(file_xml);
1257 if (LocaleCompare(keyword,
"<configure") == 0)
1263 sizeof(*configure_info));
1264 (void) memset(configure_info,0,
sizeof(*configure_info));
1265 configure_info->path=ConstantString(filename);
1266 configure_info->exempt=MagickFalse;
1267 configure_info->signature=MagickCoreSignature;
1272 if ((LocaleCompare(keyword,
"/>") == 0) ||
1273 (LocaleCompare(keyword,
"</policy>") == 0))
1275 status=AppendValueToLinkedList(cache,configure_info);
1276 if (status == MagickFalse)
1277 (void) ThrowMagickException(exception,GetMagickModule(),
1278 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
1279 configure_info->name);
1286 (void) GetNextToken(q,(
const char **) NULL,extent,token);
1289 (void) GetNextToken(q,&q,extent,token);
1290 (void) GetNextToken(q,&q,extent,token);
1296 if (LocaleCompare((
char *) keyword,
"name") == 0)
1298 configure_info->name=ConstantString(token);
1306 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
1308 configure_info->stealth=IsStringTrue(token);
1316 if (LocaleCompare((
char *) keyword,
"value") == 0)
1318 configure_info->value=ConstantString(token);
1327 token=(
char *) RelinquishMagickMemory(token);
1328 return(status != 0 ? MagickTrue : MagickFalse);