Coverage Report

Created: 2026-06-07 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/MagickCore/module.c
Line
Count
Source
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
{
865
  ExceptionInfo
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
898
          SplayTreeInfo
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
    {
984
      errno=EPERM;
985
      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
986
        "NotAuthorized","`%s'",tag);
987
      return(MagickFalse);
988
    }
989
#if !defined(MAGICKCORE_BUILD_MODULES)
990
  {
991
    MagickBooleanType
992
      status;
993
994
    status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
995
    if (status != MagickFalse)
996
      return(status);
997
  }
998
#endif
999
  TagToFilterModuleName(tag,name);
1000
  status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
1001
  if (status == MagickFalse)
1002
    {
1003
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1004
        "UnableToLoadModule","'%s': %s",name,path);
1005
      return(MagickFalse);
1006
    }
1007
  /*
1008
    Open the module.
1009
  */
1010
  handle=(ModuleHandle) lt_dlopen(path);
1011
  if (handle == (ModuleHandle) NULL)
1012
    {
1013
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1014
        "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1015
      return(MagickFalse);
1016
    }
1017
  /*
1018
    Locate the module.
1019
  */
1020
#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1021
  (void) FormatLocaleString(name,MagickPathExtent,"%sImage",tag);
1022
#else
1023
  (void) FormatLocaleString(name,MagickPathExtent,"%s%sImage",
1024
    MAGICKCORE_NAMESPACE_PREFIX_TAG,tag);
1025
#endif
1026
  /*
1027
    Execute the module.
1028
  */
1029
  ClearMagickException(exception);
1030
  image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
1031
  if (image_filter == (ImageFilterHandler *) NULL)
1032
    (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1033
      "UnableToLoadModule","'%s': %s",name,lt_dlerror());
1034
  else
1035
    {
1036
      size_t
1037
        signature;
1038
1039
      if (IsEventLogging() != MagickFalse)
1040
        (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1041
          "Invoking \"%s\" dynamic image filter",tag);
1042
      signature=image_filter(images,argc,argv,exception);
1043
      if (IsEventLogging() != MagickFalse)
1044
        (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1045
          tag);
1046
      if (signature != MagickImageFilterSignature)
1047
        (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1048
          "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1049
          (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
1050
    }
1051
  /*
1052
    Close the module.
1053
  */
1054
  if (lt_dlclose(handle) != 0)
1055
    (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1056
      "UnableToCloseModule","'%s': %s",name,lt_dlerror());
1057
  return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
1058
}
1059

1060
/*
1061
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062
%                                                                             %
1063
%                                                                             %
1064
%                                                                             %
1065
%  L i s t M o d u l e I n f o                                                %
1066
%                                                                             %
1067
%                                                                             %
1068
%                                                                             %
1069
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070
%
1071
%  ListModuleInfo() lists the module info to a file.
1072
%
1073
%  The format of the ListModuleInfo module is:
1074
%
1075
%      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1076
%
1077
%  A description of each parameter follows.
1078
%
1079
%    o file:  An pointer to a FILE.
1080
%
1081
%    o exception: return any errors or warnings in this structure.
1082
%
1083
*/
1084
MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1085
  ExceptionInfo *exception)
1086
{
1087
  char
1088
    filename[MagickPathExtent],
1089
    module_path[MagickPathExtent],
1090
    **modules,
1091
    path[MagickPathExtent];
1092
1093
  ssize_t
1094
    i;
1095
1096
  size_t
1097
    number_modules;
1098
1099
  if (file == (const FILE *) NULL)
1100
    file=stdout;
1101
  /*
1102
    List image coders.
1103
  */
1104
  modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1105
  if (modules == (char **) NULL)
1106
    return(MagickFalse);
1107
  TagToCoderModuleName("magick",filename);
1108
  (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
1109
    exception);
1110
  GetPathComponent(module_path,HeadPath,path);
1111
  (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1112
  (void) FormatLocaleFile(file,"Image Coder\n");
1113
  (void) FormatLocaleFile(file,
1114
    "-------------------------------------------------"
1115
    "------------------------------\n");
1116
  for (i=0; i < (ssize_t) number_modules; i++)
1117
  {
1118
    (void) FormatLocaleFile(file,"%s",modules[i]);
1119
    (void) FormatLocaleFile(file,"\n");
1120
  }
1121
  (void) fflush(file);
1122
  /*
1123
    Relinquish resources.
1124
  */
1125
  for (i=0; i < (ssize_t) number_modules; i++)
1126
    modules[i]=DestroyString(modules[i]);
1127
  modules=(char **) RelinquishMagickMemory(modules);
1128
  /*
1129
    List image filters.
1130
  */
1131
  modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
1132
  if (modules == (char **) NULL)
1133
    return(MagickFalse);
1134
  TagToFilterModuleName("analyze",filename);
1135
  (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
1136
    exception);
1137
  GetPathComponent(module_path,HeadPath,path);
1138
  (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
1139
  (void) FormatLocaleFile(file,"Image Filter\n");
1140
  (void) FormatLocaleFile(file,
1141
    "-------------------------------------------------"
1142
    "------------------------------\n");
1143
  for (i=0; i < (ssize_t) number_modules; i++)
1144
  {
1145
    (void) FormatLocaleFile(file,"%s",modules[i]);
1146
    (void) FormatLocaleFile(file,"\n");
1147
  }
1148
  (void) fflush(file);
1149
  /*
1150
    Relinquish resources.
1151
  */
1152
  for (i=0; i < (ssize_t) number_modules; i++)
1153
    modules[i]=DestroyString(modules[i]);
1154
  modules=(char **) RelinquishMagickMemory(modules);
1155
  return(MagickTrue);
1156
}
1157

1158
/*
1159
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1160
%                                                                             %
1161
%                                                                             %
1162
%                                                                             %
1163
+   M o d u l e C o m p o n e n t G e n e s i s                               %
1164
%                                                                             %
1165
%                                                                             %
1166
%                                                                             %
1167
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1168
%
1169
%  ModuleComponentGenesis() instantiates the module component.
1170
%
1171
%  The format of the ModuleComponentGenesis method is:
1172
%
1173
%      MagickBooleanType ModuleComponentGenesis(void)
1174
%
1175
*/
1176
MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
1177
{
1178
  MagickBooleanType
1179
    status;
1180
1181
  if (module_semaphore == (SemaphoreInfo *) NULL)
1182
    module_semaphore=AcquireSemaphoreInfo();
1183
  status=IsModuleTreeInstantiated();
1184
  return(status);
1185
}
1186

1187
/*
1188
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189
%                                                                             %
1190
%                                                                             %
1191
%                                                                             %
1192
+   M o d u l e C o m p o n e n t T e r m i n u s                             %
1193
%                                                                             %
1194
%                                                                             %
1195
%                                                                             %
1196
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1197
%
1198
%  ModuleComponentTerminus() destroys the module component.
1199
%
1200
%  The format of the ModuleComponentTerminus method is:
1201
%
1202
%      ModuleComponentTerminus(void)
1203
%
1204
*/
1205
MagickPrivate void ModuleComponentTerminus(void)
1206
{
1207
  if (module_semaphore == (SemaphoreInfo *) NULL)
1208
    ActivateSemaphoreInfo(&module_semaphore);
1209
  DestroyModuleList();
1210
  RelinquishSemaphoreInfo(&module_semaphore);
1211
}
1212

1213
/*
1214
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215
%                                                                             %
1216
%                                                                             %
1217
%                                                                             %
1218
%   O p e n M o d u l e                                                       %
1219
%                                                                             %
1220
%                                                                             %
1221
%                                                                             %
1222
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223
%
1224
%  OpenModule() loads a module, and invokes its registration module.  It
1225
%  returns MagickTrue on success, and MagickFalse if there is an error.
1226
%
1227
%  The format of the OpenModule module is:
1228
%
1229
%      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1230
%
1231
%  A description of each parameter follows:
1232
%
1233
%    o module: a character string that indicates the module to load.
1234
%
1235
%    o exception: return any errors or warnings in this structure.
1236
%
1237
*/
1238
MagickPrivate MagickBooleanType OpenModule(const char *module,
1239
  ExceptionInfo *exception)
1240
{
1241
  char
1242
    module_name[MagickPathExtent],
1243
    name[MagickPathExtent],
1244
    path[MagickPathExtent];
1245
1246
  MagickBooleanType
1247
    status;
1248
1249
  ModuleHandle
1250
    handle;
1251
1252
  ModuleInfo
1253
    *module_info;
1254
1255
  PolicyRights
1256
    rights;
1257
1258
  const CoderInfo
1259
    *p;
1260
1261
  size_t
1262
    signature;
1263
1264
  /*
1265
    Assign module name from alias.
1266
  */
1267
  assert(module != (const char *) NULL);
1268
  module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1269
  if (module_info != (ModuleInfo *) NULL)
1270
    return(MagickTrue);
1271
  (void) CopyMagickString(module_name,module,MagickPathExtent);
1272
  p=GetCoderInfo(module,exception);
1273
  if (p != (CoderInfo *) NULL)
1274
    (void) CopyMagickString(module_name,p->name,MagickPathExtent);
1275
  LocaleUpper(module_name);
1276
  rights=(PolicyRights) (ReadPolicyRights | WritePolicyRights);
1277
  if (IsRightsAuthorized(ModulePolicyDomain,rights,module_name) == MagickFalse)
1278
    {
1279
      errno=EPERM;
1280
      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1281
        "NotAuthorized","`%s'",module);
1282
      return(MagickFalse);
1283
    }
1284
  if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1285
    return(MagickTrue);  /* module already opened, return */
1286
  /*
1287
    Locate module.
1288
  */
1289
  handle=(ModuleHandle) NULL;
1290
  TagToCoderModuleName(module_name,name);
1291
  (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1292
    "Searching for module \"%s\" using filename \"%s\"",module_name,name);
1293
  *path='\0';
1294
  status=GetMagickModulePath(name,MagickImageCoderModule,path,exception);
1295
  if (status == MagickFalse)
1296
    return(MagickFalse);
1297
  /*
1298
    Load module
1299
  */
1300
  (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1301
    "Opening module at path \"%s\"",path);
1302
  handle=(ModuleHandle) lt_dlopen(path);
1303
  if (handle == (ModuleHandle) NULL)
1304
    {
1305
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1306
        "UnableToLoadModule","'%s': %s",path,lt_dlerror());
1307
      return(MagickFalse);
1308
    }
1309
  /*
1310
    Register module.
1311
  */
1312
  module_info=AcquireModuleInfo(path,module_name);
1313
  module_info->handle=handle;
1314
  if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1315
    return(MagickFalse);
1316
  /*
1317
    Define RegisterFORMATImage method.
1318
  */
1319
  TagToModuleName(module_name,"Register%sImage",name);
1320
  module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
1321
  if (module_info->register_module == (size_t (*)(void)) NULL)
1322
    {
1323
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1324
        "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1325
      return(MagickFalse);
1326
    }
1327
  (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1328
    "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1329
    (void *) module_info->register_module);
1330
  /*
1331
    Define UnregisterFORMATImage method.
1332
  */
1333
  TagToModuleName(module_name,"Unregister%sImage",name);
1334
  module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1335
  if (module_info->unregister_module == (void (*)(void)) NULL)
1336
    {
1337
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1338
        "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
1339
      return(MagickFalse);
1340
    }
1341
  (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1342
    "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1343
    (void *) module_info->unregister_module);
1344
  signature=module_info->register_module();
1345
  if (signature != MagickImageCoderSignature)
1346
    {
1347
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1348
        "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
1349
        (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
1350
      return(MagickFalse);
1351
    }
1352
  return(MagickTrue);
1353
}
1354

1355
/*
1356
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357
%                                                                             %
1358
%                                                                             %
1359
%                                                                             %
1360
%   O p e n M o d u l e s                                                     %
1361
%                                                                             %
1362
%                                                                             %
1363
%                                                                             %
1364
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1365
%
1366
%  OpenModules() loads all available modules.
1367
%
1368
%  The format of the OpenModules module is:
1369
%
1370
%      MagickBooleanType OpenModules(ExceptionInfo *exception)
1371
%
1372
%  A description of each parameter follows:
1373
%
1374
%    o exception: return any errors or warnings in this structure.
1375
%
1376
*/
1377
MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
1378
{
1379
  char
1380
    **modules;
1381
1382
  ssize_t
1383
    i;
1384
1385
  size_t
1386
    number_modules;
1387
1388
  /*
1389
    Load all modules.
1390
  */
1391
  (void) GetMagickInfo((char *) NULL,exception);
1392
  number_modules=0;
1393
  modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
1394
  if ((modules == (char **) NULL) || (*modules == (char *) NULL))
1395
    {
1396
      if (modules != (char **) NULL)
1397
        modules=(char **) RelinquishMagickMemory(modules);
1398
      return(MagickFalse);
1399
    }
1400
  for (i=0; i < (ssize_t) number_modules; i++)
1401
    (void) OpenModule(modules[i],exception);
1402
  /*
1403
    Relinquish resources.
1404
  */
1405
  for (i=0; i < (ssize_t) number_modules; i++)
1406
    modules[i]=DestroyString(modules[i]);
1407
  modules=(char **) RelinquishMagickMemory(modules);
1408
  return(MagickTrue);
1409
}
1410

1411
/*
1412
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413
%                                                                             %
1414
%                                                                             %
1415
%                                                                             %
1416
%   R e g i s t e r M o d u l e                                               %
1417
%                                                                             %
1418
%                                                                             %
1419
%                                                                             %
1420
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1421
%
1422
%  RegisterModule() adds an entry to the module list.  It returns a pointer to
1423
%  the registered entry on success.
1424
%
1425
%  The format of the RegisterModule module is:
1426
%
1427
%      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1428
%        ExceptionInfo *exception)
1429
%
1430
%  A description of each parameter follows:
1431
%
1432
%    o info: a pointer to the registered entry is returned.
1433
%
1434
%    o module_info: a pointer to the ModuleInfo structure to register.
1435
%
1436
%    o exception: return any errors or warnings in this structure.
1437
%
1438
*/
1439
static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1440
  ExceptionInfo *exception)
1441
{
1442
  MagickBooleanType
1443
    status;
1444
1445
  assert(module_info != (ModuleInfo *) NULL);
1446
  assert(module_info->signature == MagickCoreSignature);
1447
  if (IsEventLogging() != MagickFalse)
1448
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1449
  if (module_list == (SplayTreeInfo *) NULL)
1450
    return((const ModuleInfo *) NULL);
1451
  status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1452
  if (status == MagickFalse)
1453
    (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1454
      "MemoryAllocationFailed","`%s'",module_info->tag);
1455
  return(module_info);
1456
}
1457

1458
/*
1459
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460
%                                                                             %
1461
%                                                                             %
1462
%                                                                             %
1463
%  T a g T o C o d e r M o d u l e N a m e                                    %
1464
%                                                                             %
1465
%                                                                             %
1466
%                                                                             %
1467
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1468
%
1469
%  TagToCoderModuleName() munges a module tag and obtains the filename of the
1470
%  corresponding module.
1471
%
1472
%  The format of the TagToCoderModuleName module is:
1473
%
1474
%      char *TagToCoderModuleName(const char *tag,char *name)
1475
%
1476
%  A description of each parameter follows:
1477
%
1478
%    o tag: a character string representing the module tag.
1479
%
1480
%    o name: return the module name here.
1481
%
1482
*/
1483
static void TagToCoderModuleName(const char *tag,char *name)
1484
{
1485
  assert(tag != (char *) NULL);
1486
  assert(name != (char *) NULL);
1487
  if (IsEventLogging() != MagickFalse)
1488
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1489
#if defined(MAGICKCORE_LTDL_DELEGATE)
1490
  (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1491
  (void) LocaleLower(name);
1492
#else
1493
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1494
  if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1495
    (void) CopyMagickString(name,tag,MagickPathExtent);
1496
  else
1497
    {
1498
#if defined(_DEBUG)
1499
      (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_DB_%s_.dll",tag);
1500
#else
1501
      (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_RL_%s_.dll",tag);
1502
#endif
1503
    }
1504
#endif
1505
#endif
1506
}
1507

1508
/*
1509
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1510
%                                                                             %
1511
%                                                                             %
1512
%                                                                             %
1513
%  T a g T o F i l t e r M o d u l e N a m e                                  %
1514
%                                                                             %
1515
%                                                                             %
1516
%                                                                             %
1517
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1518
%
1519
%  TagToFilterModuleName() munges a module tag and returns the filename of the
1520
%  corresponding filter module.
1521
%
1522
%  The format of the TagToFilterModuleName module is:
1523
%
1524
%      void TagToFilterModuleName(const char *tag,char name)
1525
%
1526
%  A description of each parameter follows:
1527
%
1528
%    o tag: a character string representing the module tag.
1529
%
1530
%    o name: return the filter name here.
1531
%
1532
*/
1533
static void TagToFilterModuleName(const char *tag,char *name)
1534
{
1535
  assert(tag != (char *) NULL);
1536
  assert(name != (char *) NULL);
1537
  if (IsEventLogging() != MagickFalse)
1538
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1539
#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1540
#if defined(_DEBUG)
1541
 (void) FormatLocaleString(name,MagickPathExtent,"FILTER_DB_%s_.dll",tag);
1542
#else
1543
 (void) FormatLocaleString(name,MagickPathExtent,"FILTER_RL_%s_.dll",tag);
1544
#endif
1545
#elif !defined(MAGICKCORE_LTDL_DELEGATE)
1546
  (void) FormatLocaleString(name,MagickPathExtent,"%s.dll",tag);
1547
#else
1548
  (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
1549
#endif
1550
}
1551

1552
/*
1553
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554
%                                                                             %
1555
%                                                                             %
1556
%                                                                             %
1557
%   T a g T o M o d u l e N a m e                                             %
1558
%                                                                             %
1559
%                                                                             %
1560
%                                                                             %
1561
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562
%
1563
%  TagToModuleName() munges the module tag name and returns an upper-case tag
1564
%  name as the input string, and a user-provided format.
1565
%
1566
%  The format of the TagToModuleName module is:
1567
%
1568
%      void TagToModuleName(const char *tag,const char *format,char *module)
1569
%
1570
%  A description of each parameter follows:
1571
%
1572
%    o tag: the module tag.
1573
%
1574
%    o format: a sprintf-compatible format string containing %s where the
1575
%      upper-case tag name is to be inserted.
1576
%
1577
%    o module: pointer to a destination buffer for the formatted result.
1578
%
1579
*/
1580
static void TagToModuleName(const char *tag,const char *format,char *module)
1581
{
1582
  char
1583
    name[MagickPathExtent];
1584
1585
  assert(tag != (const char *) NULL);
1586
  assert(format != (const char *) NULL);
1587
  assert(module != (char *) NULL);
1588
  if (IsEventLogging() != MagickFalse)
1589
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1590
  (void) CopyMagickString(name,tag,MagickPathExtent);
1591
  LocaleUpper(name);
1592
#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1593
  (void) FormatLocaleString(module,MagickPathExtent,format,name);
1594
#else
1595
  {
1596
    char
1597
      prefix_format[MagickPathExtent];
1598
1599
    (void) FormatLocaleString(prefix_format,MagickPathExtent,"%s%s",
1600
      MAGICKCORE_NAMESPACE_PREFIX_TAG,format);
1601
    (void) FormatLocaleString(module,MagickPathExtent,prefix_format,name);
1602
  }
1603
#endif
1604
}
1605

1606
/*
1607
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1608
%                                                                             %
1609
%                                                                             %
1610
%                                                                             %
1611
%   U n r e g i s t e r M o d u l e                                           %
1612
%                                                                             %
1613
%                                                                             %
1614
%                                                                             %
1615
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1616
%
1617
%  UnregisterModule() unloads a module, and invokes its de-registration module.
1618
%  Returns MagickTrue on success, and MagickFalse if there is an error.
1619
%
1620
%  The format of the UnregisterModule module is:
1621
%
1622
%      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1623
%        ExceptionInfo *exception)
1624
%
1625
%  A description of each parameter follows:
1626
%
1627
%    o module_info: the module info.
1628
%
1629
%    o exception: return any errors or warnings in this structure.
1630
%
1631
*/
1632
static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1633
  ExceptionInfo *exception)
1634
{
1635
  /*
1636
    Locate and execute UnregisterFORMATImage module.
1637
  */
1638
  assert(module_info != (const ModuleInfo *) NULL);
1639
  assert(exception != (ExceptionInfo *) NULL);
1640
  if (IsEventLogging() != MagickFalse)
1641
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1642
  if (module_info->unregister_module == NULL)
1643
    return(MagickTrue);
1644
  module_info->unregister_module();
1645
  if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1646
    {
1647
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1648
        "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
1649
      return(MagickFalse);
1650
    }
1651
  return(MagickTrue);
1652
}
1653
#else
1654
1655
#if !defined(MAGICKCORE_BUILD_MODULES)
1656
extern size_t
1657
  analyzeImage(Image **,const int,const char **,ExceptionInfo *);
1658
#endif
1659
1660
MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1661
  ExceptionInfo *magick_unused(exception))
1662
0
{
1663
0
  magick_unreferenced(file);
1664
0
  magick_unreferenced(exception);
1665
0
  return(MagickTrue);
1666
0
}
1667
1668
MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1669
  Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1670
0
{
1671
0
  PolicyRights
1672
0
    rights;
1673
1674
0
  assert(image != (Image **) NULL);
1675
0
  assert((*image)->signature == MagickCoreSignature);
1676
0
  if (IsEventLogging() != MagickFalse)
1677
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
1678
0
  rights=ReadPolicyRights;
1679
0
  if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
1680
0
    {
1681
0
      errno=EPERM;
1682
0
      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1683
0
        "NotAuthorized","`%s'",tag);
1684
0
      return(MagickFalse);
1685
0
    }
1686
#if defined(MAGICKCORE_BUILD_MODULES)
1687
  (void) tag;
1688
  (void) argc;
1689
  (void) argv;
1690
  (void) exception;
1691
#else
1692
0
  {
1693
0
    ImageFilterHandler
1694
0
      *image_filter;
1695
1696
0
    image_filter=(ImageFilterHandler *) NULL;
1697
0
    if (LocaleCompare("analyze",tag) == 0)
1698
0
      image_filter=(ImageFilterHandler *) analyzeImage;
1699
0
    if (image_filter == (ImageFilterHandler *) NULL)
1700
0
      (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1701
0
        "UnableToLoadModule","`%s'",tag);
1702
0
    else
1703
0
      {
1704
0
        size_t
1705
0
          signature;
1706
1707
0
        if ((*image)->debug != MagickFalse)
1708
0
          (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1709
0
            "Invoking \"%s\" static image filter",tag);
1710
0
        signature=image_filter(image,argc,argv,exception);
1711
0
        if ((*image)->debug != MagickFalse)
1712
0
          (void) LogMagickEvent(TransformEvent,GetMagickModule(),
1713
0
            "\"%s\" completes",tag);
1714
0
        if (signature != MagickImageFilterSignature)
1715
0
          {
1716
0
            (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1717
0
              "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
1718
0
              (unsigned long) signature,(unsigned long)
1719
0
              MagickImageFilterSignature);
1720
0
            return(MagickFalse);
1721
0
          }
1722
0
      }
1723
0
  }
1724
0
#endif
1725
0
  return(MagickTrue);
1726
0
}
1727
#endif