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