~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to magick/delegate.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
% Copyright (C) 2003 GraphicsMagick Group
 
3
% Copyright (C) 2002 ImageMagick Studio
 
4
%
 
5
% This program is covered by multiple licenses, which are described in
 
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
 
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
 
8
%
 
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
10
%                                                                             %
 
11
%                                                                             %
 
12
%           DDDD   EEEEE  L      EEEEE   GGGG   AAA   TTTTT  EEEEE            %
 
13
%           D   D  E      L      E      G      A   A    T    E                %
 
14
%           D   D  EEE    L      EEE    G  GG  AAAAA    T    EEE              %
 
15
%           D   D  E      L      E      G   G  A   A    T    E                %
 
16
%           DDDD   EEEEE  LLLLL  EEEEE   GGG   A   A    T    EEEEE            %
 
17
%                                                                             %
 
18
%                                                                             %
 
19
%                   Methods to Read/Write/Invoke Delegates                    %
 
20
%                                                                             %
 
21
%                                                                             %
 
22
%                             Software Design                                 %
 
23
%                               John Cristy                                   %
 
24
%                               October 1998                                  %
 
25
%                                                                             %
 
26
%                                                                             %
 
27
%                                                                             %
 
28
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
29
%
 
30
%  The Delegates methods associate a set of commands with a particular
 
31
%  image format.  GraphicsMagick uses delegates for formats it does not handle
 
32
%  directly.
 
33
%
 
34
%  Thanks to Bob Friesenhahn for the initial inspiration and design of the
 
35
%  delegates methods.
 
36
%
 
37
%
 
38
*/
 
39
 
 
40
/*
 
41
  Include declarations.
 
42
*/
 
43
#include "magick/studio.h"
 
44
#include "magick/blob.h"
 
45
#include "magick/constitute.h"
 
46
#include "magick/delegate.h"
 
47
#if defined(WIN32) || defined(__CYGWIN__)
 
48
# include "magick/nt_feature.h"
 
49
#endif
 
50
#include "magick/semaphore.h"
 
51
#include "magick/tempfile.h"
 
52
#include "magick/utility.h"
 
53
 
 
54
/*
 
55
  Define declarations.
 
56
*/
 
57
#define DelegateFilename  "delegates.mgk"
 
58
 
 
59
/*
 
60
  Declare delegate map.
 
61
*/
 
62
static char
 
63
  *DelegateMap = (char *)
 
64
    "<?xml version=\"1.0\"?>"
 
65
    "<delegatemap>"
 
66
    "  <delegate stealth=\"True\" />"
 
67
    "</delegatemap>";
 
68
 
 
69
/*
 
70
  Global declaractions.
 
71
*/
 
72
static SemaphoreInfo
 
73
  *delegate_semaphore = (SemaphoreInfo *) NULL;
 
74
 
 
75
static DelegateInfo
 
76
  *delegate_list = (DelegateInfo *) NULL;
 
77
 
 
78
/*
 
79
  Forward declaractions.
 
80
*/
 
81
static unsigned int
 
82
  ReadConfigureFile(const char *,const unsigned long,ExceptionInfo *);
 
83
 
 
84
/*
 
85
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
86
%                                                                             %
 
87
%                                                                             %
 
88
%                                                                             %
 
89
%   D e s t r o y D e l e g a t e I n f o                                     %
 
90
%                                                                             %
 
91
%                                                                             %
 
92
%                                                                             %
 
93
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
94
%
 
95
%  Method DestroyDelegateInfo deallocates memory associated with the delegates
 
96
%  list.
 
97
%
 
98
%  The format of the DestroyDelegateInfo method is:
 
99
%
 
100
%      DestroyDelegateInfo(void)
 
101
%
 
102
*/
 
103
MagickExport void DestroyDelegateInfo(void)
 
104
{
 
105
  DelegateInfo
 
106
    *delegate_info;
 
107
 
 
108
  register DelegateInfo
 
109
    *p;
 
110
 
 
111
  AcquireSemaphoreInfo(&delegate_semaphore);
 
112
  for (p=delegate_list; p != (DelegateInfo *) NULL; )
 
113
  {
 
114
    delegate_info=p;
 
115
    p=p->next;
 
116
    if (delegate_info->path != (char *) NULL)
 
117
      MagickFreeMemory(delegate_info->path);
 
118
    if (delegate_info->decode != (char *) NULL)
 
119
      MagickFreeMemory(delegate_info->decode);
 
120
    if (delegate_info->encode != (char *) NULL)
 
121
      MagickFreeMemory(delegate_info->encode);
 
122
    if (delegate_info->commands != (char *) NULL)
 
123
      MagickFreeMemory(delegate_info->commands);
 
124
    MagickFreeMemory(delegate_info);
 
125
  }
 
126
  delegate_list=(DelegateInfo *) NULL;
 
127
  LiberateSemaphoreInfo(&delegate_semaphore);
 
128
  DestroySemaphoreInfo(&delegate_semaphore);
 
129
}
 
130
 
 
131
/*
 
132
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
133
%                                                                             %
 
134
%                                                                             %
 
135
%                                                                             %
 
136
%   G e t D e l e g a t e C o m m a n d                                       %
 
137
%                                                                             %
 
138
%                                                                             %
 
139
%                                                                             %
 
140
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
141
%
 
142
%  Method GetDelegateCommand replaces any embedded formatting characters with
 
143
%  the appropriate image attribute and returns the resulting command.
 
144
%
 
145
%  The format of the GetDelegateCommand method is:
 
146
%
 
147
%      char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
 
148
%        const char *decode,const char *encode,ExceptionInfo *exception)
 
149
%
 
150
%  A description of each parameter follows:
 
151
%
 
152
%    o command: Method GetDelegateCommand returns the command associated
 
153
%      with specified delegate tag.
 
154
%
 
155
%    o image_info: The image info.
 
156
%
 
157
%    o image: The image.
 
158
%
 
159
%    o decode: Specifies the decode delegate we are searching for as a
 
160
%      character string.
 
161
%
 
162
%    o encode: Specifies the encode delegate we are searching for as a
 
163
%      character string.
 
164
%
 
165
%    o exception: Return any errors or warnings in this structure.
 
166
%
 
167
%
 
168
*/
 
169
MagickExport char *GetDelegateCommand(const ImageInfo *image_info,Image *image,
 
170
  const char *decode,const char *encode,ExceptionInfo *exception)
 
171
{
 
172
  char
 
173
    *command,
 
174
    **commands;
 
175
 
 
176
  const DelegateInfo
 
177
    *delegate_info;
 
178
 
 
179
  register long
 
180
    i;
 
181
 
 
182
  assert(image_info != (ImageInfo *) NULL);
 
183
  assert(image_info->signature == MagickSignature);
 
184
  assert(image != (Image *) NULL);
 
185
  assert(image->signature == MagickSignature);
 
186
  delegate_info=GetDelegateInfo(decode,encode,exception);
 
187
  if (delegate_info == (const DelegateInfo *) NULL)
 
188
    {
 
189
      ThrowException(exception,DelegateError,NoTagFound,
 
190
        decode ? decode : encode);
 
191
      return((char *) NULL);
 
192
    }
 
193
  commands=StringToList(delegate_info->commands);
 
194
  if (commands == (char **) NULL)
 
195
    {
 
196
      ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
 
197
        decode ? decode : encode);
 
198
      return((char *) NULL);
 
199
    }
 
200
  command=TranslateText(image_info,image,commands[0]);
 
201
  if (command == (char *) NULL)
 
202
    ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,
 
203
      commands[0]);
 
204
  /*
 
205
    Free resources.
 
206
  */
 
207
  for (i=0; commands[i] != (char *) NULL; i++)
 
208
    MagickFreeMemory(commands[i]);
 
209
  MagickFreeMemory(commands);
 
210
  return(command);
 
211
}
 
212
 
 
213
/*
 
214
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
215
%                                                                             %
 
216
%                                                                             %
 
217
%                                                                             %
 
218
%   G e t D e l e g a t e I n f o                                             %
 
219
%                                                                             %
 
220
%                                                                             %
 
221
%                                                                             %
 
222
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
223
%
 
224
%  Method GetDelegateInfo returns any delegates associated with the specified
 
225
%  tag.
 
226
%
 
227
%  The format of the GetDelegateInfo method is:
 
228
%
 
229
%      const DelegateInfo *GetDelegateInfo(const char *decode,
 
230
%        const char *encode,ExceptionInfo *exception)
 
231
%
 
232
%  A description of each parameter follows:
 
233
%
 
234
%    o delgate_info: Method GetDelegateInfo returns any delegates associated
 
235
%      with the specified tag.
 
236
%
 
237
%    o decode: Specifies the decode delegate we are searching for as a
 
238
%      character string.
 
239
%
 
240
%    o encode: Specifies the encode delegate we are searching for as a
 
241
%      character string.
 
242
%
 
243
%    o exception: Return any errors or warnings in this structure.
 
244
%
 
245
%
 
246
*/
 
247
MagickExport const DelegateInfo *GetDelegateInfo(const char *decode,
 
248
  const char *encode,ExceptionInfo *exception)
 
249
{
 
250
  register DelegateInfo
 
251
    *p;
 
252
 
 
253
  if (delegate_list == (DelegateInfo *) NULL)
 
254
    {
 
255
      AcquireSemaphoreInfo(&delegate_semaphore);
 
256
      if (delegate_list == (DelegateInfo *) NULL)
 
257
        (void) ReadConfigureFile(DelegateFilename,0,exception);
 
258
      LiberateSemaphoreInfo(&delegate_semaphore);
 
259
    }
 
260
  if ((LocaleCompare(decode,"*") == 0) && (LocaleCompare(encode,"*") == 0))
 
261
    return((const DelegateInfo *) delegate_list);
 
262
  /*
 
263
    Search for requested delegate.
 
264
  */
 
265
  AcquireSemaphoreInfo(&delegate_semaphore);
 
266
  for (p=delegate_list; p != (const DelegateInfo *) NULL; p=p->next)
 
267
  {
 
268
    if (p->mode > 0)
 
269
      {
 
270
        if (LocaleCompare(p->decode,decode) == 0)
 
271
          break;
 
272
        continue;
 
273
      }
 
274
    if (p->mode < 0)
 
275
      {
 
276
        if (LocaleCompare(p->encode,encode) == 0)
 
277
          break;
 
278
        continue;
 
279
      }
 
280
    if (LocaleCompare(decode,p->decode) == 0)
 
281
      if (LocaleCompare(encode,p->encode) == 0)
 
282
        break;
 
283
    if (LocaleCompare(decode,"*") == 0)
 
284
      if (LocaleCompare(encode,p->encode) == 0)
 
285
        break;
 
286
    if (LocaleCompare(decode,p->decode) == 0)
 
287
      if (LocaleCompare(encode,"*") == 0)
 
288
        break;
 
289
  }
 
290
  if (p != (DelegateInfo *) NULL)
 
291
    if (p != delegate_list)
 
292
      {
 
293
        /*
 
294
          Self-adjusting list.
 
295
        */
 
296
        if (p->previous != (DelegateInfo *) NULL)
 
297
          p->previous->next=p->next;
 
298
        if (p->next != (DelegateInfo *) NULL)
 
299
          p->next->previous=p->previous;
 
300
        p->previous=(DelegateInfo *) NULL;
 
301
        p->next=delegate_list;
 
302
        delegate_list->previous=p;
 
303
        delegate_list=p;
 
304
      }
 
305
  LiberateSemaphoreInfo(&delegate_semaphore);
 
306
  return((const DelegateInfo *) p);
 
307
}
 
308
 
 
309
/*
 
310
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
311
%                                                                             %
 
312
%                                                                             %
 
313
%                                                                             %
 
314
%   I n v o k e D e l e g a t e                                               %
 
315
%                                                                             %
 
316
%                                                                             %
 
317
%                                                                             %
 
318
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
319
%
 
320
%  Method InvokeDelegate replaces any embedded formatting characters with
 
321
%  the appropriate image attribute and executes the resulting command.  False
 
322
%  is returned if the commands execute with success otherwise True.
 
323
%
 
324
%  The format of the InvokeDelegate method is:
 
325
%
 
326
%      unsigned int InvokeDelegate(ImageInfo *image_info,Image *image,
 
327
%        const char *decode,const char *encode,ExceptionInfo *exception)
 
328
%
 
329
%  A description of each parameter follows:
 
330
%
 
331
%    o image_info: The imageInfo.
 
332
%
 
333
%    o image: The image.
 
334
%
 
335
%    o exception: Return any errors or warnings in this structure.
 
336
%
 
337
%
 
338
*/
 
339
MagickExport unsigned int InvokeDelegate(ImageInfo *image_info,Image *image,
 
340
  const char *decode,const char *encode,ExceptionInfo *exception)
 
341
{
 
342
  char
 
343
    *command,
 
344
    **commands,
 
345
    filename[MaxTextExtent];
 
346
 
 
347
  const DelegateInfo
 
348
    *delegate_info;
 
349
 
 
350
  register long
 
351
    i;
 
352
 
 
353
  unsigned int
 
354
    status,
 
355
    temporary_image_filename;
 
356
 
 
357
  /*
 
358
    Get delegate.
 
359
  */
 
360
  assert(image_info != (ImageInfo *) NULL);
 
361
  assert(image_info->signature == MagickSignature);
 
362
  assert(image != (Image *) NULL);
 
363
  assert(image->signature == MagickSignature);
 
364
  temporary_image_filename=(*image->filename == '\0');
 
365
  if (temporary_image_filename)
 
366
    {
 
367
      /* Allocate a temporary filename if image is unnamed.  */
 
368
      if(!AcquireTemporaryFileName(image->filename))
 
369
        {
 
370
          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image->filename);
 
371
          return(False);
 
372
        }
 
373
    }
 
374
  (void) strncpy(filename,image->filename,MaxTextExtent-1);
 
375
  delegate_info=GetDelegateInfo(decode,encode,exception);
 
376
  if (delegate_info == (DelegateInfo *) NULL)
 
377
    {
 
378
      if (temporary_image_filename)
 
379
        LiberateTemporaryFile(image->filename);
 
380
      (void) ThrowException(exception,DelegateError,NoTagFound,
 
381
        decode ? decode : encode);
 
382
      return(False);
 
383
    }
 
384
 
 
385
  if (*image_info->filename == '\0')
 
386
    {
 
387
      /* ReadImage will normally have already set image_info->filename
 
388
         to the name of a temporary file.  If not, then assign
 
389
         one. Setting image_info->temporary to True indicates that
 
390
         there is a temporary file to be removed later.  */
 
391
      if(!AcquireTemporaryFileName(image_info->filename))
 
392
        {
 
393
          if (temporary_image_filename)
 
394
            LiberateTemporaryFile(image->filename);
 
395
          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->filename);
 
396
          return(False);
 
397
        }
 
398
      image_info->temporary=True;
 
399
    }
 
400
 
 
401
  if (delegate_info->mode != 0)
 
402
    if ((decode && (delegate_info->encode != (char *) NULL)) ||
 
403
        (encode && (delegate_info->decode != (char *) NULL)))
 
404
      {
 
405
        char
 
406
          filename[MaxTextExtent],
 
407
          *magick;
 
408
 
 
409
        ImageInfo
 
410
          *clone_info;
 
411
 
 
412
        register Image
 
413
          *p;
 
414
 
 
415
        /*
 
416
          Delegate requires a particular image format.
 
417
        */
 
418
 
 
419
        if (!AcquireTemporaryFileName(image_info->unique))
 
420
        {
 
421
          if (temporary_image_filename)
 
422
            LiberateTemporaryFile(image->filename);
 
423
          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->unique);
 
424
          return(False);
 
425
        }
 
426
 
 
427
        if (!AcquireTemporaryFileName(image_info->zero))
 
428
        {
 
429
          if (temporary_image_filename)
 
430
            LiberateTemporaryFile(image->filename);
 
431
          LiberateTemporaryFile(image_info->unique);
 
432
          (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->zero);
 
433
          return(False);
 
434
        }
 
435
        /* Expand sprintf-style codes in delegate command to command string */
 
436
        magick=TranslateText(image_info,image,decode != (char *) NULL ?
 
437
          delegate_info->encode : delegate_info->decode);
 
438
        if (magick == (char *) NULL)
 
439
          {
 
440
            LiberateTemporaryFile(image_info->unique);
 
441
            LiberateTemporaryFile(image_info->zero);
 
442
            if (temporary_image_filename)
 
443
              LiberateTemporaryFile(image->filename);
 
444
            (void) ThrowException(exception,DelegateError,DelegateFailed,
 
445
              decode ? decode : encode);
 
446
            return(False);
 
447
          }
 
448
        LocaleUpper(magick);
 
449
        clone_info=CloneImageInfo(image_info);
 
450
        (void) strncpy((char *) clone_info->magick,magick,MaxTextExtent-1);
 
451
        (void) strncpy(image->magick,magick,MaxTextExtent-1);
 
452
        MagickFreeMemory(magick);
 
453
        (void) strncpy(filename,image->filename,MaxTextExtent-1);
 
454
        FormatString(clone_info->filename,"%.1024s:",delegate_info->decode);
 
455
        (void) SetImageInfo(clone_info,True,exception);
 
456
        (void) strncpy(clone_info->filename,image_info->filename,
 
457
          MaxTextExtent-1);
 
458
        for (p=image; p != (Image *) NULL; p=p->next)
 
459
        {
 
460
          FormatString(p->filename,"%.1024s:%.1024s",delegate_info->decode,
 
461
            filename);
 
462
          status=WriteImage(clone_info,p);
 
463
          if (status == False)
 
464
            {
 
465
              LiberateTemporaryFile(image_info->unique);
 
466
              LiberateTemporaryFile(image_info->zero);
 
467
              if (temporary_image_filename)
 
468
                LiberateTemporaryFile(image->filename);
 
469
              DestroyImageInfo(clone_info);
 
470
              (void) ThrowException(exception,DelegateError,DelegateFailed,
 
471
                decode ? decode : encode);
 
472
              return(False);
 
473
            }
 
474
          if (clone_info->adjoin)
 
475
            break;
 
476
        }
 
477
        LiberateTemporaryFile(image_info->unique);
 
478
        LiberateTemporaryFile(image_info->zero);
 
479
        DestroyImageInfo(clone_info);
 
480
      }
 
481
  /*
 
482
    Invoke delegate.
 
483
  */
 
484
  (void) strncpy(image->filename,filename,MaxTextExtent-1);
 
485
  commands=StringToList(delegate_info->commands);
 
486
  if (commands == (char **) NULL)
 
487
    {
 
488
      if (temporary_image_filename)
 
489
        LiberateTemporaryFile(image->filename);
 
490
      (void) ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,decode ? decode : encode);
 
491
      return(False);
 
492
    }
 
493
  command=(char *) NULL;
 
494
  status=True;
 
495
  /* For each delegate command ... */
 
496
  for (i=0; commands[i] != (char *) NULL; i++)
 
497
  {
 
498
    status=True;
 
499
    /* Allocate convenience temporary files */
 
500
    if (!AcquireTemporaryFileName(image_info->unique))
 
501
    {
 
502
      (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->unique);
 
503
      status=False;
 
504
      goto error_exit;
 
505
    }
 
506
    if (!AcquireTemporaryFileName(image_info->zero))
 
507
    {
 
508
      (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->zero);
 
509
      LiberateTemporaryFile(image_info->unique);
 
510
      status=False;
 
511
      goto error_exit;
 
512
    }
 
513
    /* Expand sprintf-style codes in delegate command to command string */
 
514
    command=TranslateText(image_info,image,commands[i]);
 
515
    if (command == (char *) NULL)
 
516
      break;
 
517
    /* Handle commands which should be backgrounded */
 
518
    if (delegate_info->spawn)
 
519
      (void) ConcatenateString(&command," &");
 
520
    /* Execute delegate.  */
 
521
    status=SystemCommand(image_info->verbose,command);
 
522
    MagickFreeMemory(command);
 
523
    /* Liberate convenience temporary files */
 
524
    LiberateTemporaryFile(image_info->unique);
 
525
    LiberateTemporaryFile(image_info->zero);
 
526
    if (status != False)
 
527
      {
 
528
        (void) ThrowException(exception,DelegateError,DelegateFailed,
 
529
          commands[i]);
 
530
        goto error_exit;
 
531
      }
 
532
    MagickFreeMemory(commands[i]);
 
533
  }
 
534
  /*
 
535
    Free resources.
 
536
  */
 
537
 error_exit:
 
538
  if (temporary_image_filename)
 
539
    LiberateTemporaryFile(image->filename);
 
540
  for ( ; commands[i] != (char *) NULL; i++)
 
541
    MagickFreeMemory(commands[i]);
 
542
  MagickFreeMemory(commands);
 
543
  return(status != False);
 
544
}
 
545
 
 
546
/*
 
547
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
548
%                                                                             %
 
549
%                                                                             %
 
550
%                                                                             %
 
551
%   I n v o k e P o s t s r i p t D e l e g a t e                             %
 
552
%                                                                             %
 
553
%                                                                             %
 
554
%                                                                             %
 
555
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
556
%
 
557
%  InvokePostscriptDelegate() executes the postscript interpreter with the
 
558
%  specified command.
 
559
%
 
560
%  The format of the InvokePostscriptDelegate method is:
 
561
%
 
562
%      unsigned int InvokePostscriptDelegate(const unsigned int verbose,
 
563
%        const char *command)
 
564
%
 
565
%  A description of each parameter follows:
 
566
%
 
567
%    o status:  Method InvokePostscriptDelegate returns True is the command
 
568
%      is successfully executed, otherwise False.
 
569
%
 
570
%    o verbose: A value other than zero displays the command prior to
 
571
%      executing it.
 
572
%
 
573
%    o command: The address of a character string containing the command to
 
574
%      execute.
 
575
%
 
576
%
 
577
*/
 
578
MagickExport unsigned int InvokePostscriptDelegate(const unsigned int verbose,
 
579
  const char *command)
 
580
{
 
581
#if defined(HasGS) || defined(WIN32)
 
582
  char
 
583
    **argv;
 
584
 
 
585
  gs_main_instance
 
586
    *interpreter;
 
587
 
 
588
  int
 
589
    argc,
 
590
    code,
 
591
    status;
 
592
 
 
593
  register long
 
594
    i;
 
595
 
 
596
#if defined(WIN32)
 
597
  const GhostscriptVectors
 
598
    *gs_func;
 
599
 
 
600
  gs_func=NTGhostscriptDLLVectors();
 
601
#elif defined(HasGS)
 
602
  GhostscriptVectors
 
603
    gs_func_struct;
 
604
 
 
605
  const GhostscriptVectors
 
606
    *gs_func;
 
607
 
 
608
  gs_func=(&gs_func_struct);
 
609
  gs_func_struct.exit=gsapi_exit;
 
610
  gs_func_struct.init_with_args=gsapi_init_with_args;
 
611
  gs_func_struct.new_instance=gsapi_new_instance;
 
612
  gs_func_struct.run_string=gsapi_run_string;
 
613
  gs_func_struct.delete_instance=gsapi_delete_instance;
 
614
#endif
 
615
  if (gs_func == (GhostscriptVectors *) NULL)
 
616
    {
 
617
      if (verbose)
 
618
        (void) fputs(command,stdout);
 
619
      return(SystemCommand(verbose,command));
 
620
    }
 
621
  if (verbose)
 
622
    {
 
623
      (void) fputs("[ghostscript library]",stdout);
 
624
      (void) fputs(strchr(command,' '),stdout);
 
625
    }
 
626
  status=(gs_func->new_instance)(&interpreter,(void *) NULL);
 
627
  if (status < 0)
 
628
    return(False);
 
629
  argv=StringToArgv(command,&argc);
 
630
  if (argv == (char **) NULL)
 
631
    return(False);
 
632
  status=(gs_func->init_with_args)(interpreter,argc-1,argv+1);
 
633
  if (status == 0)
 
634
    status=(gs_func->run_string)
 
635
     (interpreter,"systemdict /start get exec\n",0,&code);
 
636
  (gs_func->exit)(interpreter);
 
637
  (gs_func->delete_instance)(interpreter);
 
638
  for (i=0; i < argc; i++)
 
639
    MagickFreeMemory(argv[i]);
 
640
  MagickFreeMemory(argv);
 
641
  if ((status == 0) || (status == -101))
 
642
    return(False);
 
643
  return(True);
 
644
#else
 
645
  return(SystemCommand(verbose,command));
 
646
#endif
 
647
}
 
648
 
 
649
/*
 
650
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
651
%                                                                             %
 
652
%                                                                             %
 
653
%                                                                             %
 
654
%  L i s t D e l e g a t e I n f o                                            %
 
655
%                                                                             %
 
656
%                                                                             %
 
657
%                                                                             %
 
658
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
659
%
 
660
%  Method ListDelegateInfo lists the image formats to a file.
 
661
%
 
662
%  The format of the ListDelegateInfo method is:
 
663
%
 
664
%      unsigned int ListDelegateInfo(FILE *file,ExceptionInfo *exception)
 
665
%
 
666
%  A description of each parameter follows.
 
667
%
 
668
%    o file:  An pointer to a FILE.
 
669
%
 
670
%    o exception: Return any errors or warnings in this structure.
 
671
%
 
672
%
 
673
*/
 
674
MagickExport unsigned int ListDelegateInfo(FILE *file,ExceptionInfo *exception)
 
675
{
 
676
  char
 
677
    **commands,
 
678
    delegate[MaxTextExtent];
 
679
 
 
680
  register long
 
681
    i;
 
682
 
 
683
  register const DelegateInfo
 
684
    *p;
 
685
 
 
686
  if (file == (const FILE *) NULL)
 
687
    file=stdout;
 
688
  (void) GetDelegateInfo("*","*",exception);
 
689
  AcquireSemaphoreInfo(&delegate_semaphore);
 
690
  for (p=delegate_list; p != (const DelegateInfo *) NULL; p=p->next)
 
691
  {
 
692
    if ((p->previous == (DelegateInfo *) NULL) ||
 
693
        (LocaleCompare(p->path,p->previous->path) != 0))
 
694
      {
 
695
        if (p->previous != (DelegateInfo *) NULL)
 
696
          (void) fprintf(file,"\n");
 
697
        if (p->path != (char *) NULL)
 
698
          (void) fprintf(file,"Path: %.1024s\n\n",p->path);
 
699
        (void) fprintf(file,"Delegate             Command\n");
 
700
        (void) fprintf(file,"-------------------------------------------------"
 
701
          "------------------------------\n");
 
702
      }
 
703
    if (p->stealth)
 
704
      continue;
 
705
    *delegate='\0';
 
706
    if (p->encode != (char *) NULL)
 
707
      (void) strncpy(delegate,p->encode,MaxTextExtent-1);
 
708
    (void) strcat(delegate,"        ");
 
709
    delegate[8]='\0';
 
710
    commands=StringToList(p->commands);
 
711
    if (commands == (char **) NULL)
 
712
      continue;
 
713
    {
 
714
      int
 
715
        command_start_column,
 
716
        command_length,
 
717
        formatted_chars=0,
 
718
        length=0,
 
719
        screen_width=79,
 
720
        strip_length;
 
721
      
 
722
      char
 
723
        *s;
 
724
 
 
725
      /* Format output so that command spans multiple lines if
 
726
         necessary */
 
727
      if (getenv("COLUMNS"))
 
728
        screen_width=atoi(getenv("COLUMNS"))-1;
 
729
      command_length=strlen(commands[0]);
 
730
      command_start_column=fprintf(file,"%8s%c=%c%s  ",p->decode ? p->decode : "",
 
731
        p->mode <= 0 ? '<' : ' ',p->mode >= 0 ? '>' : ' ',delegate);
 
732
      for (s=commands[0]; length < command_length; s+=formatted_chars)
 
733
        {
 
734
          if (s != commands[0])
 
735
            fprintf(file,"%*s",command_start_column,"");
 
736
          strip_length=screen_width-command_start_column;
 
737
          if (length+strip_length < command_length)
 
738
            {
 
739
              char
 
740
                *e;
 
741
 
 
742
              for(e=s+strip_length; (*e != ' ') && (e > s) ; e--);
 
743
              strip_length=e-s;
 
744
            }
 
745
          formatted_chars=fprintf(file,"%.*s",strip_length,s);
 
746
          length+=formatted_chars;
 
747
          fprintf(file,"\n");
 
748
          if (formatted_chars <= 0)
 
749
            break;
 
750
        }
 
751
    }
 
752
    for (i=0; commands[i] != (char *) NULL; i++)
 
753
      MagickFreeMemory(commands[i]);
 
754
  }
 
755
  (void) fflush(file);
 
756
  LiberateSemaphoreInfo(&delegate_semaphore);
 
757
  return(True);
 
758
}
 
759
 
 
760
/*
 
761
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
762
%                                                                             %
 
763
%                                                                             %
 
764
%                                                                             %
 
765
+   R e a d C o n f i g u r e F i l e                                         %
 
766
%                                                                             %
 
767
%                                                                             %
 
768
%                                                                             %
 
769
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
770
%
 
771
%  Method ReadConfigureFile reads the color configuration file which maps
 
772
%  color strings with a particular image format.
 
773
%
 
774
%  The format of the ReadConfigureFile method is:
 
775
%
 
776
%      unsigned int ReadConfigureFile(const char *basename,
 
777
%        const unsigned long depth,ExceptionInfo *exception)
 
778
%
 
779
%  A description of each parameter follows:
 
780
%
 
781
%    o status: Method ReadConfigureFile returns True if at least one color
 
782
%      is defined otherwise False.
 
783
%
 
784
%    o basename:  The color configuration filename.
 
785
%
 
786
%    o depth: depth of <include /> statements.
 
787
%
 
788
%    o exception: Return any errors or warnings in this structure.
 
789
%
 
790
%
 
791
*/
 
792
#if defined(WIN32)
 
793
static void CatDelegatePath(char *path,
 
794
                               const char *binpath,
 
795
                               const char *command)
 
796
{
 
797
  strcpy(path,binpath);
 
798
  strcat(path,command);
 
799
  if (IsAccessibleNoLogging(path))
 
800
    return;
 
801
 
 
802
  strcpy(path,command);
 
803
  return;
 
804
}
 
805
#endif /* defined(WIN32) */
 
806
static unsigned int ReadConfigureFile(const char *basename,
 
807
  const unsigned long depth,ExceptionInfo *exception)
 
808
{
 
809
  char
 
810
    keyword[MaxTextExtent],
 
811
    path[MaxTextExtent],
 
812
    *q,
 
813
    *token,
 
814
    *xml;
 
815
 
 
816
  size_t
 
817
    length;
 
818
 
 
819
  /*
 
820
    Read the delegates configure file.
 
821
  */
 
822
  (void) strcpy(path,basename);
 
823
  if (depth == 0)
 
824
    xml=(char *) GetConfigureBlob(basename,path,&length,exception);
 
825
  else
 
826
    xml=(char *) FileToBlob(basename,&length,exception);
 
827
  if (xml == (char *) NULL)
 
828
    xml=AllocateString(DelegateMap);
 
829
  token=AllocateString(xml);
 
830
  for (q=xml; *q != '\0'; )
 
831
    {
 
832
      /*
 
833
        Interpret XML.
 
834
      */
 
835
      GetToken(q,&q,token);
 
836
      if (*token == '\0')
 
837
        break;
 
838
      (void) strncpy(keyword,token,MaxTextExtent-1);
 
839
      if (LocaleNCompare(keyword,"<!--",4) == 0)
 
840
        {
 
841
          /*
 
842
            Comment element.
 
843
          */
 
844
          while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
 
845
            GetToken(q,&q,token);
 
846
          continue;
 
847
        }
 
848
      if (LocaleCompare(keyword,"<include") == 0)
 
849
        {
 
850
          /*
 
851
            Include element.
 
852
          */
 
853
          while ((*token != '>') && (*q != '\0'))
 
854
            {
 
855
              (void) strncpy(keyword,token,MaxTextExtent-1);
 
856
              GetToken(q,&q,token);
 
857
              if (*token != '=')
 
858
                continue;
 
859
              GetToken(q,&q,token);
 
860
              if (LocaleCompare(keyword,"file") == 0)
 
861
                {
 
862
                  if (depth > 200)
 
863
                    ThrowException(exception,ConfigureError,IncludeElementNestedTooDeeply,path);
 
864
                  else
 
865
                    {
 
866
                      char
 
867
                        filename[MaxTextExtent];
 
868
 
 
869
                      GetPathComponent(path,HeadPath,filename);
 
870
                      if (*filename != '\0')
 
871
                        (void) strcat(filename,DirectorySeparator);
 
872
                      (void) strncat(filename,token,MaxTextExtent-
 
873
                                     strlen(filename)-1);
 
874
                      (void) ReadConfigureFile(filename,depth+1,exception);
 
875
                    }
 
876
                  if (delegate_list != (DelegateInfo *) NULL)
 
877
                    while (delegate_list->next != (DelegateInfo *) NULL)
 
878
                      delegate_list=delegate_list->next;
 
879
                }
 
880
            }
 
881
          continue;
 
882
        }
 
883
      if (LocaleCompare(keyword,"<delegate") == 0)
 
884
        {
 
885
          DelegateInfo
 
886
            *delegate_info;
 
887
 
 
888
          /*
 
889
            Allocate memory for the delegate list.
 
890
          */
 
891
          delegate_info=MagickAllocateMemory(DelegateInfo *,sizeof(DelegateInfo));
 
892
          if (delegate_info == (DelegateInfo *) NULL)
 
893
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
 
894
                             UnableToAllocateDelegateInfo);
 
895
          (void) memset(delegate_info,0,sizeof(DelegateInfo));
 
896
          delegate_info->path=AcquireString(path);
 
897
          delegate_info->signature=MagickSignature;
 
898
          if (delegate_list == (DelegateInfo *) NULL)
 
899
            {
 
900
              delegate_list=delegate_info;
 
901
              continue;
 
902
            }
 
903
          delegate_list->next=delegate_info;
 
904
          delegate_info->previous=delegate_list;
 
905
          delegate_list=delegate_list->next;
 
906
          continue;
 
907
        }
 
908
      if (delegate_list == (DelegateInfo *) NULL)
 
909
        continue;
 
910
      GetToken(q,(char **) NULL,token);
 
911
      if (*token != '=')
 
912
        continue;
 
913
      GetToken(q,&q,token);
 
914
      GetToken(q,&q,token);
 
915
      switch (*keyword)
 
916
        {
 
917
        case 'C':
 
918
        case 'c':
 
919
          {
 
920
            if (LocaleCompare((char *) keyword,"command") == 0)
 
921
              {
 
922
                delegate_list->commands=AllocateString(token);
 
923
#if defined(WIN32)
 
924
                if (strchr(delegate_list->commands,'@') != (char *) NULL)
 
925
                  {
 
926
                    char
 
927
                      BinPath[MaxTextExtent],
 
928
                      path[MaxTextExtent];
 
929
 
 
930
                    BinPath[0]=0;
 
931
                    /* Substitute @PSDelegate@ with path to Ghostscript */
 
932
                    NTGhostscriptEXE(path,MaxTextExtent-1);
 
933
                    SubstituteString((char **) &delegate_list->commands,
 
934
                                     "@PSDelegate@",path);
 
935
 
 
936
# if defined(UseInstalledMagick)
 
937
#  if defined(MagickBinPath)
 
938
                    strcpy(BinPath,MagickBinPath);
 
939
#  else
 
940
                    {
 
941
                      char
 
942
                        *key,
 
943
                        *key_value;
 
944
                    
 
945
                      /* Obtain installation path from registry */
 
946
                      key="BinPath";
 
947
                      key_value=NTRegistryKeyLookup(key);
 
948
                      if (!key_value)
 
949
                        {
 
950
                          ThrowException(exception,ConfigureError,
 
951
                              RegistryKeyLookupFailed,key);
 
952
                        }
 
953
                      else
 
954
                        {
 
955
                          strcpy(BinPath,key_value);
 
956
                          MagickFreeMemory(key_value);
 
957
                        }
 
958
                    }
 
959
#  endif /* defined(MagickBinPath) */
 
960
# else
 
961
                    /* Base path off of client path */
 
962
                    strcpy(BinPath,SetClientPath(NULL));
 
963
# endif /* defined(UseInstalledMagick) */
 
964
                    if ((BinPath[0] != 0) &&
 
965
                        (BinPath[strlen(BinPath)-1] != *DirectorySeparator))
 
966
                      strcat(BinPath,DirectorySeparator);
 
967
 
 
968
                    /* Substitute @GMDelegate@ with path to gm.exe */
 
969
                    CatDelegatePath(path,BinPath,"gm.exe");
 
970
                    SubstituteString((char **) &delegate_list->commands,
 
971
                                     "@GMDelegate@",path);
 
972
 
 
973
                    /* Substitute @GMDisplayDelegate@ with path to
 
974
                       gmdisplay.exe */
 
975
                    CatDelegatePath(path,BinPath,"gmdisplay.exe");
 
976
                    SubstituteString((char **) &delegate_list->commands,
 
977
                                     "@GMDisplayDelegate@",path);
 
978
 
 
979
                    /* Substitute @MPEGDecodeDelegate@ with path to
 
980
                       mpeg2dec.exe */
 
981
                    CatDelegatePath(path,BinPath,"mpeg2dec.exe");
 
982
                    SubstituteString((char **) &delegate_list->commands,
 
983
                                     "@MPEGDecodeDelegate@",path);
 
984
 
 
985
                    /* Substitute @MPEGEncodeDelegate@ with path to
 
986
                       mpeg2enc.exe */
 
987
                    CatDelegatePath(path,BinPath,"mpeg2enc.exe");
 
988
                    SubstituteString((char **) &delegate_list->commands,
 
989
                                     "@MPEGEncodeDelegate@",path);
 
990
 
 
991
                    /* Substitute @HPGLDecodeDelegate@ with path to
 
992
                       hp2xx.exe */
 
993
                    CatDelegatePath(path,BinPath,"hp2xx.exe");
 
994
                    SubstituteString((char **) &delegate_list->commands,
 
995
                                     "@HPGLDecodeDelegate@",path);
 
996
                  }
 
997
#endif /* defined(WIN32) */
 
998
              } /* LocaleCompare */
 
999
            break;
 
1000
          }
 
1001
        case 'D':
 
1002
        case 'd':
 
1003
          {
 
1004
            if (LocaleCompare((char *) keyword,"decode") == 0)
 
1005
              {
 
1006
                delegate_list->decode=AcquireString(token);
 
1007
                delegate_list->mode=1;
 
1008
                break;
 
1009
              }
 
1010
            break;
 
1011
          }
 
1012
        case 'E':
 
1013
        case 'e':
 
1014
          {
 
1015
            if (LocaleCompare((char *) keyword,"encode") == 0)
 
1016
              {
 
1017
                delegate_list->encode=AcquireString(token);
 
1018
                delegate_list->mode=(-1);
 
1019
                break;
 
1020
              }
 
1021
            break;
 
1022
          }
 
1023
        case 'M':
 
1024
        case 'm':
 
1025
          {
 
1026
            if (LocaleCompare((char *) keyword,"mode") == 0)
 
1027
              {
 
1028
                delegate_list->mode=1;
 
1029
                if (LocaleCompare(token,"bi") == 0)
 
1030
                  delegate_list->mode=0;
 
1031
                else
 
1032
                  if (LocaleCompare(token,"encode") == 0)
 
1033
                    delegate_list->mode=(-1);
 
1034
                break;
 
1035
              }
 
1036
            break;
 
1037
          }
 
1038
        case 'S':
 
1039
        case 's':
 
1040
          {
 
1041
            if (LocaleCompare((char *) keyword,"spawn") == 0)
 
1042
              {
 
1043
                delegate_list->spawn=LocaleCompare(token,"True") == 0;
 
1044
                break;
 
1045
              }
 
1046
            if (LocaleCompare((char *) keyword,"stealth") == 0)
 
1047
              {
 
1048
                delegate_list->stealth=LocaleCompare(token,"True") == 0;
 
1049
                break;
 
1050
              }
 
1051
            break;
 
1052
          }
 
1053
        default:
 
1054
          break;
 
1055
        }
 
1056
    }
 
1057
  MagickFreeMemory(token);
 
1058
  MagickFreeMemory(xml);
 
1059
  if (delegate_list == (DelegateInfo *) NULL)
 
1060
    return(False);
 
1061
  while (delegate_list->previous != (DelegateInfo *) NULL)
 
1062
    delegate_list=delegate_list->previous;
 
1063
  return(True);
 
1064
}
 
1065
 
 
1066
/*
 
1067
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1068
%                                                                             %
 
1069
%                                                                             %
 
1070
%                                                                             %
 
1071
%   S e t D e l e g a t e I n f o                                             %
 
1072
%                                                                             %
 
1073
%                                                                             %
 
1074
%                                                                             %
 
1075
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
1076
%
 
1077
%  Method SetDelegateInfo adds or replaces a delegate in the delegate list and
 
1078
%  returns the address of the first delegate.  If the delegate is NULL, just
 
1079
%  the address of the first delegate is returned.
 
1080
%
 
1081
%  The format of the SetDelegateInfo method is:
 
1082
%
 
1083
%      DelegateInfo *SetDelegateInfo(DelegateInfo *delegate_info)
 
1084
%
 
1085
%  A description of each parameter follows:
 
1086
%
 
1087
%    o delegate_info: Method SetDelegateInfo returns the address of the
 
1088
%      first delegate in the delegates list.
 
1089
%
 
1090
%    o delegate_info:  A structure of type DelegateInfo.  This information
 
1091
%      is added to the end of the delegates linked-list.
 
1092
%
 
1093
%
 
1094
*/
 
1095
MagickExport DelegateInfo *SetDelegateInfo(DelegateInfo *delegate_info)
 
1096
{
 
1097
  register DelegateInfo
 
1098
    *p;
 
1099
 
 
1100
  DelegateInfo
 
1101
    *delegate;
 
1102
 
 
1103
  /*
 
1104
    Initialize new delegate.
 
1105
  */
 
1106
  assert(delegate_info != (DelegateInfo *) NULL);
 
1107
  assert(delegate_info->signature == MagickSignature);
 
1108
  delegate=MagickAllocateMemory(DelegateInfo *,sizeof(DelegateInfo));
 
1109
  if (delegate == (DelegateInfo *) NULL)
 
1110
    return((DelegateInfo *) delegate_list);
 
1111
  delegate->decode=AcquireString(delegate_info->decode);
 
1112
  delegate->encode=AcquireString(delegate_info->encode);
 
1113
  delegate->mode=delegate_info->mode;
 
1114
  delegate->commands=(char *) NULL;
 
1115
  if (delegate_info->commands != (char *) NULL)
 
1116
    delegate->commands=AllocateString(delegate_info->commands);
 
1117
  delegate->previous=(DelegateInfo *) NULL;
 
1118
  delegate->next=(DelegateInfo *) NULL;
 
1119
  if (delegate_list == (DelegateInfo *) NULL)
 
1120
    {
 
1121
      delegate_list=delegate;
 
1122
      return((DelegateInfo *) delegate_list);
 
1123
    }
 
1124
  for (p=delegate_list; p != (DelegateInfo *) NULL; p=p->next)
 
1125
  {
 
1126
    if ((LocaleCompare(p->decode,delegate_info->decode) == 0) &&
 
1127
        (LocaleCompare(p->encode,delegate_info->encode) == 0) &&
 
1128
        (p->mode == delegate_info->mode))
 
1129
      {
 
1130
        /*
 
1131
          Delegate overrides an existing one with the same tags.
 
1132
        */
 
1133
        MagickFreeMemory(p->commands);
 
1134
        p->commands=delegate->commands;
 
1135
        MagickFreeMemory(delegate);
 
1136
        return((DelegateInfo *) delegate_list);
 
1137
      }
 
1138
    if (p->next == (DelegateInfo *) NULL)
 
1139
      break;
 
1140
  }
 
1141
  /*
 
1142
    Place new delegate at the end of the delegate list.
 
1143
  */
 
1144
  delegate->previous=p;
 
1145
  p->next=delegate;
 
1146
  return((DelegateInfo *) delegate_list);
 
1147
}