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