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