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"
87 static MagickBooleanType
90 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
91 static MagickBooleanType
92 LoadConfigureCache(
LinkedListInfo *,
const char *,
const char *,
const size_t,
122 static 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);
140 static LinkedListInfo *AcquireConfigureCache(
const char *filename,
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());
208 MagickExport MagickBooleanType ConfigureComponentGenesis(
void)
211 configure_semaphore=AllocateSemaphoreInfo();
234 static 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);
253 MagickExport
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);
289 static void *DestroyOptions(
void *option)
291 return(DestroyStringInfo((
StringInfo *) option));
297 return(DestroyLinkedList(options,DestroyOptions));
329 MagickExport
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)
396 static 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)
413 MagickExport
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)
493 static int ConfigureCompare(
const void *x,
const void *y)
501 return(LocaleCompare(*p,*q));
504 #if defined(__cplusplus) || defined(c_plusplus)
508 MagickExport
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;
574 MagickExport
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));
625 MagickExport
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);
717 MagickExport
LinkedListInfo *GetConfigurePaths(
const char *filename,
720 #define RegistryKey "ConfigurePath"
721 #define MagickCoreDLL "CORE_RL_magick_.dll"
722 #define MagickCoreDebugDLL "CORE_DB_magick_.dll"
730 assert(filename != (
const char *) NULL);
732 if (IsEventLogging() != MagickFalse)
733 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"%s",filename);
735 (void) CopyMagickString(path,filename,MaxTextExtent);
736 paths=NewLinkedList(0);
744 configure_path=GetEnvironmentValue(
"MAGICK_CONFIGURE_PATH");
745 if (configure_path != (
char *) NULL)
751 for (p=configure_path-1; p != (
char *) NULL; )
753 (void) CopyMagickString(path,p+1,MaxTextExtent);
754 q=strchr(path,DirectoryListSeparator);
755 if (q != (
char *) NULL)
757 q=path+strlen(path)-1;
758 if ((q >= path) && (*q != *DirectorySeparator))
759 (void) ConcatenateMagickString(path,DirectorySeparator,
761 (void) AppendValueToLinkedList(paths,ConstantString(path));
762 p=strchr(p+1,DirectoryListSeparator);
764 configure_path=DestroyString(configure_path);
767 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
768 #if defined(MAGICKCORE_SHARE_PATH)
769 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
771 #if defined(MAGICKCORE_SHAREARCH_PATH)
772 (void) AppendValueToLinkedList(paths,ConstantString(
773 MAGICKCORE_SHAREARCH_PATH));
775 #if defined(MAGICKCORE_CONFIGURE_PATH)
776 (void) AppendValueToLinkedList(paths,ConstantString(
777 MAGICKCORE_CONFIGURE_PATH));
779 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
780 (void) AppendValueToLinkedList(paths,ConstantString(
781 MAGICKCORE_DOCUMENTATION_PATH));
783 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
791 key_value=NTRegistryKeyLookup(RegistryKey);
792 if (key_value != (
unsigned char *) NULL)
794 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",(
char *) key_value,
796 (void) AppendValueToLinkedList(paths,ConstantString(path));
797 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
809 home=GetEnvironmentValue(
"MAGICK_HOME");
810 if (home != (
char *) NULL)
812 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
813 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",home,
815 (void) AppendValueToLinkedList(paths,ConstantString(path));
817 (void) FormatLocaleString(path,MaxTextExtent,
"%s/etc/%s/",home,
818 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
819 (void) AppendValueToLinkedList(paths,ConstantString(path));
820 (void) FormatLocaleString(path,MaxTextExtent,
"%s/share/%s/",home,
821 MAGICKCORE_SHARE_RELATIVE_PATH);
822 (void) AppendValueToLinkedList(paths,ConstantString(path));
823 (void) FormatLocaleString(path,MaxTextExtent,
"%s",
824 MAGICKCORE_SHAREARCH_PATH);
825 (void) AppendValueToLinkedList(paths,ConstantString(path));
827 home=DestroyString(home);
830 if (*GetClientPath() !=
'\0')
832 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
833 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",GetClientPath(),
835 (void) AppendValueToLinkedList(paths,ConstantString(path));
838 prefix[MaxTextExtent];
843 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
844 ChopPathComponents(prefix,1);
845 (void) FormatLocaleString(path,MaxTextExtent,
"%s/etc/%s/",prefix,
846 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
847 (void) AppendValueToLinkedList(paths,ConstantString(path));
848 (void) FormatLocaleString(path,MaxTextExtent,
"%s/share/%s/",prefix,
849 MAGICKCORE_SHARE_RELATIVE_PATH);
850 (void) AppendValueToLinkedList(paths,ConstantString(path));
851 (void) FormatLocaleString(path,MaxTextExtent,
"%s",
852 MAGICKCORE_SHAREARCH_PATH);
853 (void) AppendValueToLinkedList(paths,ConstantString(path));
859 (void) AppendValueToLinkedList(paths,ConstantString(
""));
865 home=GetEnvironmentValue(
"XDG_CONFIG_HOME");
866 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
867 if (home == (
char *) NULL)
868 home=GetEnvironmentValue(
"LOCALAPPDATA");
869 if (home == (
char *) NULL)
870 home=GetEnvironmentValue(
"APPDATA");
871 if (home == (
char *) NULL)
872 home=GetEnvironmentValue(
"USERPROFILE");
874 if (home != (
char *) NULL)
879 (void) FormatLocaleString(path,MaxTextExtent,
"%s%sImageMagick%s",
880 home,DirectorySeparator,DirectorySeparator);
881 (void) AppendValueToLinkedList(paths,ConstantString(path));
882 home=DestroyString(home);
884 home=GetEnvironmentValue(
"HOME");
885 if (home != (
char *) NULL)
890 (void) FormatLocaleString(path,MaxTextExtent,
891 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
892 DirectorySeparator,DirectorySeparator);
893 (void) AppendValueToLinkedList(paths,ConstantString(path));
897 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s.magick%s",home,
898 DirectorySeparator,DirectorySeparator);
899 (void) AppendValueToLinkedList(paths,ConstantString(path));
900 home=DestroyString(home);
903 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
906 module_path[MaxTextExtent];
908 if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
909 (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
917 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
919 key_value=NTRegistryKeyLookup(RegistryKey);
920 if (key_value == (
unsigned char *) NULL)
921 (void) AppendValueToLinkedList(paths,ConstantString(path));
923 key_value=(
unsigned char *) RelinquishMagickMemory(key_value);
925 if (NTGetModulePath(
"Magick.dll",module_path) != MagickFalse)
930 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
932 (void) AppendValueToLinkedList(paths,ConstantString(path));
933 (void) FormatLocaleString(path,MaxTextExtent,
"%s%s",module_path,
934 "\\inc\\lib\\auto\\Image\\Magick\\");
935 (void) AppendValueToLinkedList(paths,ConstantString(path));
939 if (GetNumberOfElementsInLinkedList(paths) == 0)
940 (
void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
941 "no configuration paths found",
"`%s'",filename);
967 MagickExport
const char *GetConfigureValue(
const ConfigureInfo *configure_info)
969 if (IsEventLogging() != MagickFalse)
970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),
"...");
972 assert(configure_info->signature == MagickCoreSignature);
973 return(configure_info->value);
999 static MagickBooleanType IsConfigureCacheInstantiated(
ExceptionInfo *exception)
1004 ActivateSemaphoreInfo(&configure_semaphore);
1005 LockSemaphoreInfo(configure_semaphore);
1007 configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1008 UnlockSemaphoreInfo(configure_semaphore);
1010 return(configure_cache != (
LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1037 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1057 if (file == (
const FILE *) NULL)
1059 configure_info=GetConfigureInfoList(
"*",&number_options,exception);
1061 return(MagickFalse);
1062 path=(
const char *) NULL;
1063 for (i=0; i < (ssize_t) number_options; i++)
1065 if (configure_info[i]->stealth != MagickFalse)
1067 if ((path == (
const char *) NULL) ||
1068 (LocaleCompare(path,configure_info[i]->path) != 0))
1070 if (configure_info[i]->path != (
char *) NULL)
1071 (
void) FormatLocaleFile(file,
"\nPath: %s\n\n",
1072 configure_info[i]->path);
1073 (void) FormatLocaleFile(file,
"Name Value\n");
1074 (void) FormatLocaleFile(file,
1075 "-------------------------------------------------"
1076 "------------------------------\n");
1078 path=configure_info[i]->path;
1080 if (configure_info[i]->name != (
char *) NULL)
1081 name=configure_info[i]->name;
1082 (void) FormatLocaleFile(file,
"%s",name);
1083 for (j=(ssize_t) strlen(name); j <= 13; j++)
1084 (
void) FormatLocaleFile(file,
" ");
1085 (void) FormatLocaleFile(file,
" ");
1087 if (configure_info[i]->value != (
char *) NULL)
1088 value=configure_info[i]->value;
1089 (void) FormatLocaleFile(file,
"%s",value);
1090 (void) FormatLocaleFile(file,
"\n");
1092 (void) fflush(file);
1093 configure_info=(
const ConfigureInfo **) RelinquishMagickMemory((
void *)
1098 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
1130 static MagickBooleanType LoadConfigureCache(
LinkedListInfo *cache,
1131 const char *xml,
const char *filename,
const size_t depth,
1135 keyword[MaxTextExtent],
1153 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1154 "Loading configure file \"%s\" ...",filename);
1157 token=AcquireString(xml);
1158 extent=strlen(token)+MaxTextExtent;
1159 for (q=(
char *) xml; *q !=
'\0'; )
1164 (void) GetNextToken(q,&q,extent,token);
1167 (void) CopyMagickString(keyword,token,MaxTextExtent);
1168 if (LocaleNCompare(keyword,
"<!DOCTYPE",9) == 0)
1173 while ((LocaleNCompare(q,
"]>",2) != 0) && (*q !=
'\0'))
1174 (
void) GetNextToken(q,&q,extent,token);
1177 if (LocaleNCompare(keyword,
"<!--",4) == 0)
1182 while ((LocaleNCompare(q,
"->",2) != 0) && (*q !=
'\0'))
1183 (void) GetNextToken(q,&q,extent,token);
1186 if (LocaleCompare(keyword,
"<include") == 0)
1191 while (((*token !=
'/') && (*(token+1) !=
'>')) && (*q !=
'\0'))
1193 (void) CopyMagickString(keyword,token,MaxTextExtent);
1194 (void) GetNextToken(q,&q,extent,token);
1197 (void) GetNextToken(q,&q,extent,token);
1198 if (LocaleCompare(keyword,
"file") == 0)
1200 if (depth > MagickMaxRecursionDepth)
1201 (void) ThrowMagickException(exception,GetMagickModule(),
1202 ConfigureError,
"IncludeElementNestedTooDeeply",
"`%s'",token);
1206 path[MaxTextExtent],
1209 GetPathComponent(filename,HeadPath,path);
1211 (void) ConcatenateMagickString(path,DirectorySeparator,
1213 if (*token == *DirectorySeparator)
1214 (void) CopyMagickString(path,token,MaxTextExtent);
1216 (
void) ConcatenateMagickString(path,token,MaxTextExtent);
1217 xml=FileToXML(path,~0UL);
1218 if (xml != (
char *) NULL)
1220 status&=LoadConfigureCache(cache,xml,path,
1222 xml=(
char *) RelinquishMagickMemory(xml);
1229 if (LocaleCompare(keyword,
"<configure") == 0)
1235 sizeof(*configure_info));
1237 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1238 (void) memset(configure_info,0,
sizeof(*configure_info));
1239 configure_info->path=ConstantString(filename);
1240 configure_info->exempt=MagickFalse;
1241 configure_info->signature=MagickCoreSignature;
1246 if ((LocaleCompare(keyword,
"/>") == 0) ||
1247 (LocaleCompare(keyword,
"</policy>") == 0))
1249 status=AppendValueToLinkedList(cache,configure_info);
1250 if (status == MagickFalse)
1251 (void) ThrowMagickException(exception,GetMagickModule(),
1252 ResourceLimitError,
"MemoryAllocationFailed",
"`%s'",
1253 configure_info->name);
1260 (void) GetNextToken(q,(
const char **) NULL,extent,token);
1263 (void) GetNextToken(q,&q,extent,token);
1264 (void) GetNextToken(q,&q,extent,token);
1270 if (LocaleCompare((
char *) keyword,
"name") == 0)
1272 configure_info->name=ConstantString(token);
1280 if (LocaleCompare((
char *) keyword,
"stealth") == 0)
1282 configure_info->stealth=IsMagickTrue(token);
1290 if (LocaleCompare((
char *) keyword,
"value") == 0)
1292 configure_info->value=ConstantString(token);
1301 token=(
char *) RelinquishMagickMemory(token);
1302 return(status != 0 ? MagickTrue : MagickFalse);