• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                  M   M   OOO   DDDD   U   U  L      EEEEE                   %
7 %                  MM MM  O   O  D   D  U   U  L      E                       %
8 %                  M M M  O   O  D   D  U   U  L      EEE                     %
9 %                  M   M  O   O  D   D  U   U  L      E                       %
10 %                  M   M   OOO   DDDD    UUU   LLLLL  EEEEE                   %
11 %                                                                             %
12 %                                                                             %
13 %                          MagickCore Module Methods                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                              Bob Friesenhahn                                %
17 %                                March 2000                                   %
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 
40 /*
41   Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/coder.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/configure.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/linked-list.h"
52 #include "MagickCore/magic.h"
53 #include "MagickCore/magick.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/module.h"
56 #include "MagickCore/module-private.h"
57 #include "MagickCore/nt-base-private.h"
58 #include "MagickCore/policy.h"
59 #include "MagickCore/semaphore.h"
60 #include "MagickCore/splay-tree.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67 #if defined(MAGICKCORE_MODULES_SUPPORT)
68 #if defined(MAGICKCORE_LTDL_DELEGATE)
69 #include "ltdl.h"
70 typedef lt_dlhandle ModuleHandle;
71 #else
72 typedef void *ModuleHandle;
73 #endif
74 
75 /*
76   Define declarations.
77 */
78 #if defined(MAGICKCORE_LTDL_DELEGATE)
79 #  define ModuleGlobExpression "*.la"
80 #else
81 #  if defined(_DEBUG)
82 #    define ModuleGlobExpression "IM_MOD_DB_*.dll"
83 #  else
84 #    define ModuleGlobExpression "IM_MOD_RL_*.dll"
85 #  endif
86 #endif
87 
88 /*
89   Global declarations.
90 */
91 static SemaphoreInfo
92   *module_semaphore = (SemaphoreInfo *) NULL;
93 
94 static SplayTreeInfo
95   *module_list = (SplayTreeInfo *) NULL;
96 
97 /*
98   Forward declarations.
99 */
100 static const ModuleInfo
101   *RegisterModule(const ModuleInfo *,ExceptionInfo *);
102 
103 static MagickBooleanType
104   GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
105   IsModuleTreeInstantiated(),
106   UnregisterModule(const ModuleInfo *,ExceptionInfo *);
107 
108 static void
109   TagToCoderModuleName(const char *,char *),
110   TagToFilterModuleName(const char *,char *),
111   TagToModuleName(const char *,const char *,char *);
112 
113 /*
114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 %                                                                             %
116 %                                                                             %
117 %                                                                             %
118 %   A c q u i r e M o d u l e I n f o                                         %
119 %                                                                             %
120 %                                                                             %
121 %                                                                             %
122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 %
124 %  AcquireModuleInfo() allocates the ModuleInfo structure.
125 %
126 %  The format of the AcquireModuleInfo method is:
127 %
128 %      ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
129 %
130 %  A description of each parameter follows:
131 %
132 %    o path: the path associated with the tag.
133 %
134 %    o tag: a character string that represents the image format we are
135 %      looking for.
136 %
137 */
AcquireModuleInfo(const char * path,const char * tag)138 MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
139 {
140   ModuleInfo
141     *module_info;
142 
143   module_info=(ModuleInfo *) AcquireMagickMemory(sizeof(*module_info));
144   if (module_info == (ModuleInfo *) NULL)
145     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
146   (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
147   if (path != (const char *) NULL)
148     module_info->path=ConstantString(path);
149   if (tag != (const char *) NULL)
150     module_info->tag=ConstantString(tag);
151   module_info->timestamp=time(0);
152   module_info->signature=MagickCoreSignature;
153   return(module_info);
154 }
155 
156 /*
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 %                                                                             %
159 %                                                                             %
160 %                                                                             %
161 %   D e s t r o y M o d u l e L i s t                                         %
162 %                                                                             %
163 %                                                                             %
164 %                                                                             %
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166 %
167 %  DestroyModuleList() unregisters any previously loaded modules and exits
168 %  the module loaded environment.
169 %
170 %  The format of the DestroyModuleList module is:
171 %
172 %      void DestroyModuleList(void)
173 %
174 */
DestroyModuleList(void)175 MagickExport void DestroyModuleList(void)
176 {
177   /*
178     Destroy magick modules.
179   */
180   LockSemaphoreInfo(module_semaphore);
181 #if defined(MAGICKCORE_MODULES_SUPPORT)
182   if (module_list != (SplayTreeInfo *) NULL)
183     module_list=DestroySplayTree(module_list);
184 #endif
185   UnlockSemaphoreInfo(module_semaphore);
186 }
187 
188 /*
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190 %                                                                             %
191 %                                                                             %
192 %                                                                             %
193 %   G e t M o d u l e I n f o                                                 %
194 %                                                                             %
195 %                                                                             %
196 %                                                                             %
197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198 %
199 %  GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
200 %  specified tag.  If tag is NULL, the head of the module list is returned. If
201 %  no modules are loaded, or the requested module is not found, NULL is
202 %  returned.
203 %
204 %  The format of the GetModuleInfo module is:
205 %
206 %      ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
207 %
208 %  A description of each parameter follows:
209 %
210 %    o tag: a character string that represents the image format we are
211 %      looking for.
212 %
213 %    o exception: return any errors or warnings in this structure.
214 %
215 */
GetModuleInfo(const char * tag,ExceptionInfo * exception)216 MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
217 {
218   ModuleInfo
219     *module_info;
220 
221   if (IsModuleTreeInstantiated() == MagickFalse)
222     return((ModuleInfo *) NULL);
223   LockSemaphoreInfo(module_semaphore);
224   ResetSplayTreeIterator(module_list);
225   if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
226     {
227 #if defined(MAGICKCORE_MODULES_SUPPORT)
228       if (LocaleCompare(tag,"*") == 0)
229         (void) OpenModules(exception);
230 #endif
231       module_info=(ModuleInfo *) GetNextValueInSplayTree(module_list);
232       UnlockSemaphoreInfo(module_semaphore);
233       return(module_info);
234     }
235   module_info=(ModuleInfo *) GetValueFromSplayTree(module_list,tag);
236   UnlockSemaphoreInfo(module_semaphore);
237   return(module_info);
238 }
239 
240 /*
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %   G e t M o d u l e I n f o L i s t                                         %
246 %                                                                             %
247 %                                                                             %
248 %                                                                             %
249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 %
251 %  GetModuleInfoList() returns any modules that match the specified pattern.
252 %
253 %  The format of the GetModuleInfoList function is:
254 %
255 %      const ModuleInfo **GetModuleInfoList(const char *pattern,
256 %        size_t *number_modules,ExceptionInfo *exception)
257 %
258 %  A description of each parameter follows:
259 %
260 %    o pattern: Specifies a pointer to a text string containing a pattern.
261 %
262 %    o number_modules:  This integer returns the number of modules in the list.
263 %
264 %    o exception: return any errors or warnings in this structure.
265 %
266 */
267 
268 #if defined(__cplusplus) || defined(c_plusplus)
269 extern "C" {
270 #endif
271 
ModuleInfoCompare(const void * x,const void * y)272 static int ModuleInfoCompare(const void *x,const void *y)
273 {
274   const ModuleInfo
275     **p,
276     **q;
277 
278   p=(const ModuleInfo **) x,
279   q=(const ModuleInfo **) y;
280   if (LocaleCompare((*p)->path,(*q)->path) == 0)
281     return(LocaleCompare((*p)->tag,(*q)->tag));
282   return(LocaleCompare((*p)->path,(*q)->path));
283 }
284 
285 #if defined(__cplusplus) || defined(c_plusplus)
286 }
287 #endif
288 
GetModuleInfoList(const char * pattern,size_t * number_modules,ExceptionInfo * exception)289 MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
290   size_t *number_modules,ExceptionInfo *exception)
291 {
292   const ModuleInfo
293     **modules;
294 
295   register const ModuleInfo
296     *p;
297 
298   register ssize_t
299     i;
300 
301   /*
302     Allocate module list.
303   */
304   assert(pattern != (char *) NULL);
305   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
306   assert(number_modules != (size_t *) NULL);
307   *number_modules=0;
308   p=GetModuleInfo("*",exception);
309   if (p == (const ModuleInfo *) NULL)
310     return((const ModuleInfo **) NULL);
311   modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
312     GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
313   if (modules == (const ModuleInfo **) NULL)
314     return((const ModuleInfo **) NULL);
315   /*
316     Generate module list.
317   */
318   LockSemaphoreInfo(module_semaphore);
319   ResetSplayTreeIterator(module_list);
320   p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
321   for (i=0; p != (const ModuleInfo *) NULL; )
322   {
323     if ((p->stealth == MagickFalse) &&
324         (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
325       modules[i++]=p;
326     p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
327   }
328   UnlockSemaphoreInfo(module_semaphore);
329   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
330   modules[i]=(ModuleInfo *) NULL;
331   *number_modules=(size_t) i;
332   return(modules);
333 }
334 
335 /*
336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337 %                                                                             %
338 %                                                                             %
339 %                                                                             %
340 %   G e t M o d u l e L i s t                                                 %
341 %                                                                             %
342 %                                                                             %
343 %                                                                             %
344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
345 %
346 %  GetModuleList() returns any image format modules that match the specified
347 %  pattern.
348 %
349 %  The format of the GetModuleList function is:
350 %
351 %      char **GetModuleList(const char *pattern,const MagickModuleType type,
352 %        size_t *number_modules,ExceptionInfo *exception)
353 %
354 %  A description of each parameter follows:
355 %
356 %    o pattern: Specifies a pointer to a text string containing a pattern.
357 %
358 %    o type: choose from MagickImageCoderModule or MagickImageFilterModule.
359 %
360 %    o number_modules:  This integer returns the number of modules in the
361 %      list.
362 %
363 %    o exception: return any errors or warnings in this structure.
364 %
365 */
366 
367 #if defined(__cplusplus) || defined(c_plusplus)
368 extern "C" {
369 #endif
370 
ModuleCompare(const void * x,const void * y)371 static int ModuleCompare(const void *x,const void *y)
372 {
373   register const char
374     **p,
375     **q;
376 
377    p=(const char **) x;
378   q=(const char **) y;
379   return(LocaleCompare(*p,*q));
380 }
381 
382 #if defined(__cplusplus) || defined(c_plusplus)
383 }
384 #endif
385 
MagickReadDirectory(DIR * directory,struct dirent * entry,struct dirent ** result)386 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
387   struct dirent **result)
388 {
389 #if defined(MAGICKCORE_HAVE_READDIR_R)
390   return(readdir_r(directory,entry,result));
391 #else
392   (void) entry;
393   errno=0;
394   *result=readdir(directory);
395   return(errno);
396 #endif
397 }
398 
GetModuleList(const char * pattern,const MagickModuleType type,size_t * number_modules,ExceptionInfo * exception)399 MagickExport char **GetModuleList(const char *pattern,
400   const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
401 {
402 #define MaxModules  511
403 
404   char
405     **modules,
406     filename[MagickPathExtent],
407     module_path[MagickPathExtent],
408     path[MagickPathExtent];
409 
410   DIR
411     *directory;
412 
413   MagickBooleanType
414     status;
415 
416   register ssize_t
417     i;
418 
419   size_t
420     max_entries;
421 
422   struct dirent
423     *buffer,
424     *entry;
425 
426   /*
427     Locate all modules in the image coder or filter path.
428   */
429   switch (type)
430   {
431     case MagickImageCoderModule:
432     default:
433     {
434       TagToCoderModuleName("magick",filename);
435       status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
436         exception);
437       break;
438     }
439     case MagickImageFilterModule:
440     {
441       TagToFilterModuleName("analyze",filename);
442       status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
443         exception);
444       break;
445     }
446   }
447   if (status == MagickFalse)
448     return((char **) NULL);
449   GetPathComponent(module_path,HeadPath,path);
450   max_entries=MaxModules;
451   modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
452     sizeof(*modules));
453   if (modules == (char **) NULL)
454     return((char **) NULL);
455   *modules=(char *) NULL;
456   directory=opendir(path);
457   if (directory == (DIR *) NULL)
458     {
459       modules=(char **) RelinquishMagickMemory(modules);
460       return((char **) NULL);
461     }
462   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
463   if (buffer == (struct dirent *) NULL)
464     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
465   i=0;
466   while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
467          (entry != (struct dirent *) NULL))
468   {
469     status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
470     if (status == MagickFalse)
471       continue;
472     if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
473       continue;
474     if (i >= (ssize_t) max_entries)
475       {
476         modules=(char **) NULL;
477         if (~max_entries > max_entries)
478           modules=(char **) ResizeQuantumMemory(modules,(size_t)
479             (max_entries << 1),sizeof(*modules));
480         max_entries<<=1;
481         if (modules == (char **) NULL)
482           break;
483       }
484     /*
485       Add new module name to list.
486     */
487     modules[i]=AcquireString((char *) NULL);
488     GetPathComponent(entry->d_name,BasePath,modules[i]);
489     if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
490       {
491         (void) CopyMagickString(modules[i],modules[i]+10,MagickPathExtent);
492         modules[i][strlen(modules[i])-1]='\0';
493       }
494     i++;
495   }
496   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
497   (void) closedir(directory);
498   if (modules == (char **) NULL)
499     {
500       (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
501         "MemoryAllocationFailed","`%s'",pattern);
502       return((char **) NULL);
503     }
504   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
505   modules[i]=(char *) NULL;
506   *number_modules=(size_t) i;
507   return(modules);
508 }
509 
510 /*
511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
512 %                                                                             %
513 %                                                                             %
514 %                                                                             %
515 %  G e t M a g i c k M o d u l e P a t h                                      %
516 %                                                                             %
517 %                                                                             %
518 %                                                                             %
519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 %
521 %  GetMagickModulePath() finds a module with the specified module type and
522 %  filename.
523 %
524 %  The format of the GetMagickModulePath module is:
525 %
526 %      MagickBooleanType GetMagickModulePath(const char *filename,
527 %        MagickModuleType module_type,char *path,ExceptionInfo *exception)
528 %
529 %  A description of each parameter follows:
530 %
531 %    o filename: the module file name.
532 %
533 %    o module_type: the module type: MagickImageCoderModule or
534 %      MagickImageFilterModule.
535 %
536 %    o path: the path associated with the filename.
537 %
538 %    o exception: return any errors or warnings in this structure.
539 %
540 */
GetMagickModulePath(const char * filename,MagickModuleType module_type,char * path,ExceptionInfo * exception)541 static MagickBooleanType GetMagickModulePath(const char *filename,
542   MagickModuleType module_type,char *path,ExceptionInfo *exception)
543 {
544   char
545     *module_path;
546 
547   assert(filename != (const char *) NULL);
548   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
549   assert(path != (char *) NULL);
550   assert(exception != (ExceptionInfo *) NULL);
551   if (strchr(filename,'/') != (char *) NULL)
552     return(MagickFalse);
553   (void) CopyMagickString(path,filename,MagickPathExtent);
554   module_path=(char *) NULL;
555   switch (module_type)
556   {
557     case MagickImageCoderModule:
558     default:
559     {
560       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
561         "Searching for coder module file \"%s\" ...",filename);
562       module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
563 #if defined(MAGICKCORE_CODER_PATH)
564       if (module_path == (char *) NULL)
565         module_path=AcquireString(MAGICKCORE_CODER_PATH);
566 #endif
567       break;
568     }
569     case MagickImageFilterModule:
570     {
571       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
572         "Searching for filter module file \"%s\" ...",filename);
573       module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
574 #if defined(MAGICKCORE_FILTER_PATH)
575       if (module_path == (char *) NULL)
576         module_path=AcquireString(MAGICKCORE_FILTER_PATH);
577 #endif
578       break;
579     }
580   }
581   if (module_path != (char *) NULL)
582     {
583       register char
584         *p,
585         *q;
586 
587       for (p=module_path-1; p != (char *) NULL; )
588       {
589         (void) CopyMagickString(path,p+1,MagickPathExtent);
590         q=strchr(path,DirectoryListSeparator);
591         if (q != (char *) NULL)
592           *q='\0';
593         q=path+strlen(path)-1;
594         if ((q >= path) && (*q != *DirectorySeparator))
595           (void) ConcatenateMagickString(path,DirectorySeparator,
596             MagickPathExtent);
597         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
598         if (IsPathAccessible(path) != MagickFalse)
599           {
600             module_path=DestroyString(module_path);
601             return(MagickTrue);
602           }
603         p=strchr(p+1,DirectoryListSeparator);
604       }
605       module_path=DestroyString(module_path);
606     }
607 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
608   else
609 #if defined(MAGICKCORE_CODER_PATH)
610     {
611       const char
612         *directory;
613 
614       /*
615         Search hard coded paths.
616       */
617       switch (module_type)
618       {
619         case MagickImageCoderModule:
620         default:
621         {
622           directory=MAGICKCORE_CODER_PATH;
623           break;
624         }
625         case MagickImageFilterModule:
626         {
627           directory=MAGICKCORE_FILTER_PATH;
628           break;
629         }
630       }
631       (void) FormatLocaleString(path,MagickPathExtent,"%s%s",directory,
632         filename);
633       if (IsPathAccessible(path) == MagickFalse)
634         {
635           ThrowFileException(exception,ConfigureWarning,
636             "UnableToOpenModuleFile",path);
637           return(MagickFalse);
638         }
639       return(MagickTrue);
640     }
641 #else
642 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
643     {
644       const char
645         *registery_key;
646 
647       unsigned char
648         *key_value;
649 
650       /*
651         Locate path via registry key.
652       */
653       switch (module_type)
654       {
655         case MagickImageCoderModule:
656         default:
657         {
658           registery_key="CoderModulesPath";
659           break;
660         }
661         case MagickImageFilterModule:
662         {
663           registery_key="FilterModulesPath";
664           break;
665         }
666       }
667       key_value=NTRegistryKeyLookup(registery_key);
668       if (key_value == (unsigned char *) NULL)
669         {
670           ThrowMagickException(exception,GetMagickModule(),ConfigureError,
671             "RegistryKeyLookupFailed","`%s'",registery_key);
672           return(MagickFalse);
673         }
674       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",(char *)
675         key_value,DirectorySeparator,filename);
676       key_value=(unsigned char *) RelinquishMagickMemory(key_value);
677       if (IsPathAccessible(path) == MagickFalse)
678         {
679           ThrowFileException(exception,ConfigureWarning,
680             "UnableToOpenModuleFile",path);
681           return(MagickFalse);
682         }
683       return(MagickTrue);
684     }
685 #endif
686 #endif
687 #if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
688 # error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
689 #endif
690 #else
691   {
692     char
693       *home;
694 
695     home=GetEnvironmentValue("MAGICK_HOME");
696     if (home != (char *) NULL)
697       {
698         /*
699           Search MAGICK_HOME.
700         */
701 #if !defined(MAGICKCORE_POSIX_SUPPORT)
702         (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",home,
703           DirectorySeparator,filename);
704 #else
705         const char
706           *directory;
707 
708         switch (module_type)
709         {
710           case MagickImageCoderModule:
711           default:
712           {
713             directory=MAGICKCORE_CODER_RELATIVE_PATH;
714             break;
715           }
716           case MagickImageFilterModule:
717           {
718             directory=MAGICKCORE_FILTER_RELATIVE_PATH;
719             break;
720           }
721         }
722         (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s",home,
723           directory,filename);
724 #endif
725         home=DestroyString(home);
726         if (IsPathAccessible(path) != MagickFalse)
727           return(MagickTrue);
728       }
729   }
730   if (*GetClientPath() != '\0')
731     {
732       /*
733         Search based on executable directory.
734       */
735 #if !defined(MAGICKCORE_POSIX_SUPPORT)
736       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
737         DirectorySeparator,filename);
738 #else
739       char
740         prefix[MagickPathExtent];
741 
742       const char
743         *directory;
744 
745       switch (module_type)
746       {
747         case MagickImageCoderModule:
748         default:
749         {
750           directory="coders";
751           break;
752         }
753         case MagickImageFilterModule:
754         {
755           directory="filters";
756           break;
757         }
758       }
759       (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
760       ChopPathComponents(prefix,1);
761       (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s/%s",prefix,
762         MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
763 #endif
764       if (IsPathAccessible(path) != MagickFalse)
765         return(MagickTrue);
766     }
767 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
768   {
769     /*
770       Search module path.
771     */
772     if ((NTGetModulePath("CORE_RL_MagickCore_.dll",path) != MagickFalse) ||
773         (NTGetModulePath("CORE_DB_MagickCore_.dll",path) != MagickFalse))
774       {
775         (void) ConcatenateMagickString(path,DirectorySeparator,
776           MagickPathExtent);
777         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
778         if (IsPathAccessible(path) != MagickFalse)
779           return(MagickTrue);
780       }
781   }
782 #endif
783   {
784     char
785       *home;
786 
787     home=GetEnvironmentValue("XDG_CONFIG_HOME");
788     if (home == (char *) NULL)
789       home=GetEnvironmentValue("LOCALAPPDATA");
790     if (home == (char *) NULL)
791       home=GetEnvironmentValue("APPDATA");
792     if (home == (char *) NULL)
793       home=GetEnvironmentValue("USERPROFILE");
794     if (home != (char *) NULL)
795       {
796         /*
797           Search $XDG_CONFIG_HOME/ImageMagick.
798         */
799         (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s%s",
800           home,DirectorySeparator,DirectorySeparator,filename);
801         home=DestroyString(home);
802         if (IsPathAccessible(path) != MagickFalse)
803           return(MagickTrue);
804       }
805     home=GetEnvironmentValue("HOME");
806     if (home != (char *) NULL)
807       {
808         /*
809           Search $HOME/.config/ImageMagick.
810         */
811         (void) FormatLocaleString(path,MagickPathExtent,
812           "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
813           DirectorySeparator,DirectorySeparator,filename);
814         home=DestroyString(home);
815         if (IsPathAccessible(path) != MagickFalse)
816           return(MagickTrue);
817       }
818   }
819   /*
820     Search current directory.
821   */
822   if (IsPathAccessible(path) != MagickFalse)
823     return(MagickTrue);
824   if (exception->severity < ConfigureError)
825     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
826       path);
827 #endif
828   return(MagickFalse);
829 }
830 
831 /*
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %                                                                             %
834 %                                                                             %
835 %                                                                             %
836 %   I s M o d u l e T r e e I n s t a n t i a t e d                           %
837 %                                                                             %
838 %                                                                             %
839 %                                                                             %
840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 %
842 %  IsModuleTreeInstantiated() determines if the module tree is instantiated.
843 %  If not, it instantiates the tree and returns it.
844 %
845 %  The format of the IsModuleTreeInstantiated() method is:
846 %
847 %      IsModuleTreeInstantiated()
848 %
849 */
850 
DestroyModuleNode(void * module_info)851 static void *DestroyModuleNode(void *module_info)
852 {
853   ExceptionInfo
854     *exception;
855 
856   register ModuleInfo
857     *p;
858 
859   exception=AcquireExceptionInfo();
860   p=(ModuleInfo *) module_info;
861   if (UnregisterModule(p,exception) == MagickFalse)
862     CatchException(exception);
863   if (p->tag != (char *) NULL)
864     p->tag=DestroyString(p->tag);
865   if (p->path != (char *) NULL)
866     p->path=DestroyString(p->path);
867   exception=DestroyExceptionInfo(exception);
868   return(RelinquishMagickMemory(p));
869 }
870 
IsModuleTreeInstantiated()871 static MagickBooleanType IsModuleTreeInstantiated()
872 {
873   if (module_list == (SplayTreeInfo *) NULL)
874     {
875       if (module_semaphore == (SemaphoreInfo *) NULL)
876         ActivateSemaphoreInfo(&module_semaphore);
877       LockSemaphoreInfo(module_semaphore);
878       if (module_list == (SplayTreeInfo *) NULL)
879         {
880           MagickBooleanType
881             status;
882 
883           ModuleInfo
884             *module_info;
885 
886           module_list=NewSplayTree(CompareSplayTreeString,
887             (void *(*)(void *)) NULL,DestroyModuleNode);
888           if (module_list == (SplayTreeInfo *) NULL)
889             ThrowFatalException(ResourceLimitFatalError,
890               "MemoryAllocationFailed");
891           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
892           module_info->stealth=MagickTrue;
893           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
894           if (status == MagickFalse)
895             ThrowFatalException(ResourceLimitFatalError,
896               "MemoryAllocationFailed");
897           if (lt_dlinit() != 0)
898             ThrowFatalException(ModuleFatalError,
899               "UnableToInitializeModuleLoader");
900         }
901       UnlockSemaphoreInfo(module_semaphore);
902     }
903   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
904 }
905 
906 /*
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 %                                                                             %
909 %                                                                             %
910 %                                                                             %
911 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
912 %                                                                             %
913 %                                                                             %
914 %                                                                             %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 %
917 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
918 %
919 %  The format of the InvokeDynamicImageFilter module is:
920 %
921 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
922 %        const int argc,const char **argv,ExceptionInfo *exception)
923 %
924 %  A description of each parameter follows:
925 %
926 %    o tag: a character string that represents the name of the particular
927 %      module.
928 %
929 %    o image: the image.
930 %
931 %    o argc: a pointer to an integer describing the number of elements in the
932 %      argument vector.
933 %
934 %    o argv: a pointer to a text array containing the command line arguments.
935 %
936 %    o exception: return any errors or warnings in this structure.
937 %
938 */
InvokeDynamicImageFilter(const char * tag,Image ** images,const int argc,const char ** argv,ExceptionInfo * exception)939 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
940   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
941 {
942   char
943     name[MagickPathExtent],
944     path[MagickPathExtent];
945 
946   ImageFilterHandler
947     *image_filter;
948 
949   MagickBooleanType
950     status;
951 
952   ModuleHandle
953     handle;
954 
955   PolicyRights
956     rights;
957 
958   /*
959     Find the module.
960   */
961   assert(images != (Image **) NULL);
962   assert((*images)->signature == MagickCoreSignature);
963   if ((*images)->debug != MagickFalse)
964     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
965       (*images)->filename);
966 #if !defined(MAGICKCORE_BUILD_MODULES)
967   {
968     MagickBooleanType
969       status;
970 
971     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
972     if (status != MagickFalse)
973       return(status);
974   }
975 #endif
976   rights=ReadPolicyRights;
977   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
978     {
979       errno=EPERM;
980       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
981         "NotAuthorized","`%s'",tag);
982       return(MagickFalse);
983     }
984   TagToFilterModuleName(tag,name);
985   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
986   if (status == MagickFalse)
987     {
988       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
989         "UnableToLoadModule","'%s': %s",name,path);
990       return(MagickFalse);
991     }
992   /*
993     Open the module.
994   */
995   handle=(ModuleHandle) lt_dlopen(path);
996   if (handle == (ModuleHandle) NULL)
997     {
998       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
999         "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1000       return(MagickFalse);
1001     }
1002   /*
1003     Locate the module.
1004   */
1005 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1006   (void) FormatLocaleString(name,MagickPathExtent,"%sImage",tag);
1007 #else
1008   (void) FormatLocaleString(name,MagickPathExtent,"%s%sImage",
1009     MAGICKCORE_NAMESPACE_PREFIX,tag);
1010 #endif
1011   /*
1012     Execute the module.
1013   */
1014   ClearMagickException(exception);
1015   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
1016   if (image_filter == (ImageFilterHandler *) NULL)
1017     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1018       "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1019   else
1020     {
1021       size_t
1022         signature;
1023 
1024       if ((*images)->debug != MagickFalse)
1025         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1026           "Invoking \"%s\" dynamic image filter",tag);
1027       signature=image_filter(images,argc,argv,exception);
1028       if ((*images)->debug != MagickFalse)
1029         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1030           tag);
1031       if (signature != MagickImageFilterSignature)
1032         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1033           "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1034           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
1035     }
1036   /*
1037     Close the module.
1038   */
1039   if (lt_dlclose(handle) != 0)
1040     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1041       "UnableToCloseModule","'%s': %s",name,lt_dlerror());
1042   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
1043 }
1044 
1045 /*
1046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1047 %                                                                             %
1048 %                                                                             %
1049 %                                                                             %
1050 %  L i s t M o d u l e I n f o                                                %
1051 %                                                                             %
1052 %                                                                             %
1053 %                                                                             %
1054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1055 %
1056 %  ListModuleInfo() lists the module info to a file.
1057 %
1058 %  The format of the ListModuleInfo module is:
1059 %
1060 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1061 %
1062 %  A description of each parameter follows.
1063 %
1064 %    o file:  An pointer to a FILE.
1065 %
1066 %    o exception: return any errors or warnings in this structure.
1067 %
1068 */
ListModuleInfo(FILE * file,ExceptionInfo * exception)1069 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1070   ExceptionInfo *exception)
1071 {
1072   char
1073     filename[MagickPathExtent],
1074     module_path[MagickPathExtent],
1075     **modules,
1076     path[MagickPathExtent];
1077 
1078   register ssize_t
1079     i;
1080 
1081   size_t
1082     number_modules;
1083 
1084   if (file == (const FILE *) NULL)
1085     file=stdout;
1086   /*
1087     List image coders.
1088   */
1089   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1090   if (modules == (char **) NULL)
1091     return(MagickFalse);
1092   TagToCoderModuleName("magick",filename);
1093   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1094     exception);
1095   GetPathComponent(module_path,HeadPath,path);
1096   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1097   (void) FormatLocaleFile(file,"Image Coder\n");
1098   (void) FormatLocaleFile(file,
1099     "-------------------------------------------------"
1100     "------------------------------\n");
1101   for (i=0; i < (ssize_t) number_modules; i++)
1102   {
1103     (void) FormatLocaleFile(file,"%s",modules[i]);
1104     (void) FormatLocaleFile(file,"\n");
1105   }
1106   (void) fflush(file);
1107   /*
1108     Relinquish resources.
1109   */
1110   for (i=0; i < (ssize_t) number_modules; i++)
1111     modules[i]=DestroyString(modules[i]);
1112   modules=(char **) RelinquishMagickMemory(modules);
1113   /*
1114     List image filters.
1115   */
1116   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1117   if (modules == (char **) NULL)
1118     return(MagickFalse);
1119   TagToFilterModuleName("analyze",filename);
1120   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1121     exception);
1122   GetPathComponent(module_path,HeadPath,path);
1123   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1124   (void) FormatLocaleFile(file,"Image Filter\n");
1125   (void) FormatLocaleFile(file,
1126     "-------------------------------------------------"
1127     "------------------------------\n");
1128   for (i=0; i < (ssize_t) number_modules; i++)
1129   {
1130     (void) FormatLocaleFile(file,"%s",modules[i]);
1131     (void) FormatLocaleFile(file,"\n");
1132   }
1133   (void) fflush(file);
1134   /*
1135     Relinquish resources.
1136   */
1137   for (i=0; i < (ssize_t) number_modules; i++)
1138     modules[i]=DestroyString(modules[i]);
1139   modules=(char **) RelinquishMagickMemory(modules);
1140   return(MagickTrue);
1141 }
1142 
1143 /*
1144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145 %                                                                             %
1146 %                                                                             %
1147 %                                                                             %
1148 +   M o d u l e C o m p o n e n t G e n e s i s                               %
1149 %                                                                             %
1150 %                                                                             %
1151 %                                                                             %
1152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1153 %
1154 %  ModuleComponentGenesis() instantiates the module component.
1155 %
1156 %  The format of the ModuleComponentGenesis method is:
1157 %
1158 %      MagickBooleanType ModuleComponentGenesis(void)
1159 %
1160 */
ModuleComponentGenesis(void)1161 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
1162 {
1163   MagickBooleanType
1164     status;
1165 
1166   if (module_semaphore == (SemaphoreInfo *) NULL)
1167     module_semaphore=AcquireSemaphoreInfo();
1168   status=IsModuleTreeInstantiated();
1169   return(status);
1170 }
1171 
1172 /*
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1174 %                                                                             %
1175 %                                                                             %
1176 %                                                                             %
1177 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
1178 %                                                                             %
1179 %                                                                             %
1180 %                                                                             %
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1182 %
1183 %  ModuleComponentTerminus() destroys the module component.
1184 %
1185 %  The format of the ModuleComponentTerminus method is:
1186 %
1187 %      ModuleComponentTerminus(void)
1188 %
1189 */
ModuleComponentTerminus(void)1190 MagickPrivate void ModuleComponentTerminus(void)
1191 {
1192   if (module_semaphore == (SemaphoreInfo *) NULL)
1193     ActivateSemaphoreInfo(&module_semaphore);
1194   DestroyModuleList();
1195   RelinquishSemaphoreInfo(&module_semaphore);
1196 }
1197 
1198 /*
1199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1200 %                                                                             %
1201 %                                                                             %
1202 %                                                                             %
1203 %   O p e n M o d u l e                                                       %
1204 %                                                                             %
1205 %                                                                             %
1206 %                                                                             %
1207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1208 %
1209 %  OpenModule() loads a module, and invokes its registration module.  It
1210 %  returns MagickTrue on success, and MagickFalse if there is an error.
1211 %
1212 %  The format of the OpenModule module is:
1213 %
1214 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1215 %
1216 %  A description of each parameter follows:
1217 %
1218 %    o module: a character string that indicates the module to load.
1219 %
1220 %    o exception: return any errors or warnings in this structure.
1221 %
1222 */
OpenModule(const char * module,ExceptionInfo * exception)1223 MagickPrivate MagickBooleanType OpenModule(const char *module,
1224   ExceptionInfo *exception)
1225 {
1226   char
1227     filename[MagickPathExtent],
1228     module_name[MagickPathExtent],
1229     name[MagickPathExtent],
1230     path[MagickPathExtent];
1231 
1232   MagickBooleanType
1233     status;
1234 
1235   ModuleHandle
1236     handle;
1237 
1238   ModuleInfo
1239     *module_info;
1240 
1241   register const CoderInfo
1242     *p;
1243 
1244   size_t
1245     signature;
1246 
1247   /*
1248     Assign module name from alias.
1249   */
1250   assert(module != (const char *) NULL);
1251   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1252   if (module_info != (ModuleInfo *) NULL)
1253     return(MagickTrue);
1254   (void) CopyMagickString(module_name,module,MagickPathExtent);
1255   p=GetCoderInfo(module,exception);
1256   if (p != (CoderInfo *) NULL)
1257     (void) CopyMagickString(module_name,p->name,MagickPathExtent);
1258   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1259     return(MagickTrue);  /* module already opened, return */
1260   /*
1261     Locate module.
1262   */
1263   handle=(ModuleHandle) NULL;
1264   TagToCoderModuleName(module_name,filename);
1265   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1266     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1267   *path='\0';
1268   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1269   if (status == MagickFalse)
1270     return(MagickFalse);
1271   /*
1272     Load module
1273   */
1274   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1275     "Opening module at path \"%s\"",path);
1276   handle=(ModuleHandle) lt_dlopen(path);
1277   if (handle == (ModuleHandle) NULL)
1278     {
1279       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1280         "UnableToLoadModule","'%s': %s",path,lt_dlerror());
1281       return(MagickFalse);
1282     }
1283   /*
1284     Register module.
1285   */
1286   module_info=AcquireModuleInfo(path,module_name);
1287   module_info->handle=handle;
1288   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1289     return(MagickFalse);
1290   /*
1291     Define RegisterFORMATImage method.
1292   */
1293   TagToModuleName(module_name,"Register%sImage",name);
1294   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1295   if (module_info->register_module == (size_t (*)(void)) NULL)
1296     {
1297       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1298         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1299       return(MagickFalse);
1300     }
1301   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1302     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1303     (void *) module_info->register_module);
1304   /*
1305     Define UnregisterFORMATImage method.
1306   */
1307   TagToModuleName(module_name,"Unregister%sImage",name);
1308   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1309   if (module_info->unregister_module == (void (*)(void)) NULL)
1310     {
1311       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1312         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1313       return(MagickFalse);
1314     }
1315   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1316     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1317     (void *) module_info->unregister_module);
1318   signature=module_info->register_module();
1319   if (signature != MagickImageCoderSignature)
1320     {
1321       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1322         "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
1323         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
1324       return(MagickFalse);
1325     }
1326   return(MagickTrue);
1327 }
1328 
1329 /*
1330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1331 %                                                                             %
1332 %                                                                             %
1333 %                                                                             %
1334 %   O p e n M o d u l e s                                                     %
1335 %                                                                             %
1336 %                                                                             %
1337 %                                                                             %
1338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1339 %
1340 %  OpenModules() loads all available modules.
1341 %
1342 %  The format of the OpenModules module is:
1343 %
1344 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
1345 %
1346 %  A description of each parameter follows:
1347 %
1348 %    o exception: return any errors or warnings in this structure.
1349 %
1350 */
OpenModules(ExceptionInfo * exception)1351 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
1352 {
1353   char
1354     **modules;
1355 
1356   register ssize_t
1357     i;
1358 
1359   size_t
1360     number_modules;
1361 
1362   /*
1363     Load all modules.
1364   */
1365   (void) GetMagickInfo((char *) NULL,exception);
1366   number_modules=0;
1367   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1368   if ((modules == (char **) NULL) || (*modules == (char *) NULL))
1369     {
1370       if (modules != (char **) NULL)
1371         modules=(char **) RelinquishMagickMemory(modules);
1372       return(MagickFalse);
1373     }
1374   for (i=0; i < (ssize_t) number_modules; i++)
1375     (void) OpenModule(modules[i],exception);
1376   /*
1377     Relinquish resources.
1378   */
1379   for (i=0; i < (ssize_t) number_modules; i++)
1380     modules[i]=DestroyString(modules[i]);
1381   modules=(char **) RelinquishMagickMemory(modules);
1382   return(MagickTrue);
1383 }
1384 
1385 /*
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 %                                                                             %
1388 %                                                                             %
1389 %                                                                             %
1390 %   R e g i s t e r M o d u l e                                               %
1391 %                                                                             %
1392 %                                                                             %
1393 %                                                                             %
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395 %
1396 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
1397 %  the registered entry on success.
1398 %
1399 %  The format of the RegisterModule module is:
1400 %
1401 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1402 %        ExceptionInfo *exception)
1403 %
1404 %  A description of each parameter follows:
1405 %
1406 %    o info: a pointer to the registered entry is returned.
1407 %
1408 %    o module_info: a pointer to the ModuleInfo structure to register.
1409 %
1410 %    o exception: return any errors or warnings in this structure.
1411 %
1412 */
RegisterModule(const ModuleInfo * module_info,ExceptionInfo * exception)1413 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1414   ExceptionInfo *exception)
1415 {
1416   MagickBooleanType
1417     status;
1418 
1419   assert(module_info != (ModuleInfo *) NULL);
1420   assert(module_info->signature == MagickCoreSignature);
1421   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1422   if (module_list == (SplayTreeInfo *) NULL)
1423     return((const ModuleInfo *) NULL);
1424   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1425   if (status == MagickFalse)
1426     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1427       "MemoryAllocationFailed","`%s'",module_info->tag);
1428   return(module_info);
1429 }
1430 
1431 /*
1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1433 %                                                                             %
1434 %                                                                             %
1435 %                                                                             %
1436 %  T a g T o C o d e r M o d u l e N a m e                                    %
1437 %                                                                             %
1438 %                                                                             %
1439 %                                                                             %
1440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441 %
1442 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
1443 %  corresponding module.
1444 %
1445 %  The format of the TagToCoderModuleName module is:
1446 %
1447 %      char *TagToCoderModuleName(const char *tag,char *name)
1448 %
1449 %  A description of each parameter follows:
1450 %
1451 %    o tag: a character string representing the module tag.
1452 %
1453 %    o name: return the module name here.
1454 %
1455 */
TagToCoderModuleName(const char * tag,char * name)1456 static void TagToCoderModuleName(const char *tag,char *name)
1457 {
1458   assert(tag != (char *) NULL);
1459   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1460   assert(name != (char *) NULL);
1461 #if defined(MAGICKCORE_LTDL_DELEGATE)
1462   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1463   (void) LocaleLower(name);
1464 #else
1465 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1466   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1467     (void) CopyMagickString(name,tag,MagickPathExtent);
1468   else
1469     {
1470 #if defined(_DEBUG)
1471       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_DB_%s_.dll",tag);
1472 #else
1473       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_RL_%s_.dll",tag);
1474 #endif
1475     }
1476 #endif
1477 #endif
1478 }
1479 
1480 /*
1481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1482 %                                                                             %
1483 %                                                                             %
1484 %                                                                             %
1485 %  T a g T o F i l t e r M o d u l e N a m e                                  %
1486 %                                                                             %
1487 %                                                                             %
1488 %                                                                             %
1489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1490 %
1491 %  TagToFilterModuleName() munges a module tag and returns the filename of the
1492 %  corresponding filter module.
1493 %
1494 %  The format of the TagToFilterModuleName module is:
1495 %
1496 %      void TagToFilterModuleName(const char *tag,char name)
1497 %
1498 %  A description of each parameter follows:
1499 %
1500 %    o tag: a character string representing the module tag.
1501 %
1502 %    o name: return the filter name here.
1503 %
1504 */
TagToFilterModuleName(const char * tag,char * name)1505 static void TagToFilterModuleName(const char *tag,char *name)
1506 {
1507   assert(tag != (char *) NULL);
1508   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1509   assert(name != (char *) NULL);
1510 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1511   (void) FormatLocaleString(name,MagickPathExtent,"FILTER_%s_.dll",tag);
1512 #elif !defined(MAGICKCORE_LTDL_DELEGATE)
1513   (void) FormatLocaleString(name,MagickPathExtent,"%s.dll",tag);
1514 #else
1515   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1516 #endif
1517 }
1518 
1519 /*
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521 %                                                                             %
1522 %                                                                             %
1523 %                                                                             %
1524 %   T a g T o M o d u l e N a m e                                             %
1525 %                                                                             %
1526 %                                                                             %
1527 %                                                                             %
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1529 %
1530 %  TagToModuleName() munges the module tag name and returns an upper-case tag
1531 %  name as the input string, and a user-provided format.
1532 %
1533 %  The format of the TagToModuleName module is:
1534 %
1535 %      TagToModuleName(const char *tag,const char *format,char *module)
1536 %
1537 %  A description of each parameter follows:
1538 %
1539 %    o tag: the module tag.
1540 %
1541 %    o format: a sprintf-compatible format string containing %s where the
1542 %      upper-case tag name is to be inserted.
1543 %
1544 %    o module: pointer to a destination buffer for the formatted result.
1545 %
1546 */
TagToModuleName(const char * tag,const char * format,char * module)1547 static void TagToModuleName(const char *tag,const char *format,char *module)
1548 {
1549   char
1550     name[MagickPathExtent];
1551 
1552   assert(tag != (const char *) NULL);
1553   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1554   assert(format != (const char *) NULL);
1555   assert(module != (char *) NULL);
1556   (void) CopyMagickString(name,tag,MagickPathExtent);
1557   LocaleUpper(name);
1558 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1559   (void) FormatLocaleString(module,MagickPathExtent,format,name);
1560 #else
1561   {
1562     char
1563       prefix_format[MagickPathExtent];
1564 
1565     (void) FormatLocaleString(prefix_format,MagickPathExtent,"%s%s",
1566       MAGICKCORE_NAMESPACE_PREFIX,format);
1567     (void) FormatLocaleString(module,MagickPathExtent,prefix_format,name);
1568   }
1569 #endif
1570 }
1571 
1572 /*
1573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1574 %                                                                             %
1575 %                                                                             %
1576 %                                                                             %
1577 %   U n r e g i s t e r M o d u l e                                           %
1578 %                                                                             %
1579 %                                                                             %
1580 %                                                                             %
1581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1582 %
1583 %  UnregisterModule() unloads a module, and invokes its de-registration module.
1584 %  Returns MagickTrue on success, and MagickFalse if there is an error.
1585 %
1586 %  The format of the UnregisterModule module is:
1587 %
1588 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1589 %        ExceptionInfo *exception)
1590 %
1591 %  A description of each parameter follows:
1592 %
1593 %    o module_info: the module info.
1594 %
1595 %    o exception: return any errors or warnings in this structure.
1596 %
1597 */
UnregisterModule(const ModuleInfo * module_info,ExceptionInfo * exception)1598 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1599   ExceptionInfo *exception)
1600 {
1601   /*
1602     Locate and execute UnregisterFORMATImage module.
1603   */
1604   assert(module_info != (const ModuleInfo *) NULL);
1605   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1606   assert(exception != (ExceptionInfo *) NULL);
1607   if (module_info->unregister_module == NULL)
1608     return(MagickTrue);
1609   module_info->unregister_module();
1610   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1611     {
1612       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1613         "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
1614       return(MagickFalse);
1615     }
1616   return(MagickTrue);
1617 }
1618 #else
1619 
1620 #if !defined(MAGICKCORE_BUILD_MODULES)
1621 extern size_t
1622   analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1623 #endif
1624 
ListModuleInfo(FILE * magick_unused (file),ExceptionInfo * magick_unused (exception))1625 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1626   ExceptionInfo *magick_unused(exception))
1627 {
1628   return(MagickTrue);
1629 }
1630 
InvokeDynamicImageFilter(const char * tag,Image ** image,const int argc,const char ** argv,ExceptionInfo * exception)1631 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1632   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1633 {
1634   PolicyRights
1635     rights;
1636 
1637   assert(image != (Image **) NULL);
1638   assert((*image)->signature == MagickCoreSignature);
1639   if ((*image)->debug != MagickFalse)
1640     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1641   rights=ReadPolicyRights;
1642   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1643     {
1644       errno=EPERM;
1645       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1646         "NotAuthorized","`%s'",tag);
1647       return(MagickFalse);
1648     }
1649 #if defined(MAGICKCORE_BUILD_MODULES)
1650   (void) tag;
1651   (void) argc;
1652   (void) argv;
1653   (void) exception;
1654 #else
1655   {
1656     ImageFilterHandler
1657       *image_filter;
1658 
1659     image_filter=(ImageFilterHandler *) NULL;
1660     if (LocaleCompare("analyze",tag) == 0)
1661       image_filter=(ImageFilterHandler *) analyzeImage;
1662     if (image_filter == (ImageFilterHandler *) NULL)
1663       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1664         "UnableToLoadModule","`%s'",tag);
1665     else
1666       {
1667         size_t
1668           signature;
1669 
1670         if ((*image)->debug != MagickFalse)
1671           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1672             "Invoking \"%s\" static image filter",tag);
1673         signature=image_filter(image,argc,argv,exception);
1674         if ((*image)->debug != MagickFalse)
1675           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
1676             tag);
1677         if (signature != MagickImageFilterSignature)
1678           {
1679             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1680               "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1681               (unsigned long) signature,(unsigned long)
1682               MagickImageFilterSignature);
1683             return(MagickFalse);
1684           }
1685       }
1686   }
1687 #endif
1688   return(MagickTrue);
1689 }
1690 #endif
1691