Coverage Report

Created: 2026-09-14 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/magick/utility.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (c) 2000 Markus Friedl.  All rights reserved.
4
% Copyright (C) 2002 ImageMagick Studio
5
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
6
%
7
% This program is covered by multiple licenses, which are described in
8
% Copyright.txt. You should have received a copy of Copyright.txt with this
9
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
10
%
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
%                                                                             %
13
%                                                                             %
14
%                                                                             %
15
%             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
16
%             U   U    T      I    L        I      T     Y Y                  %
17
%             U   U    T      I    L        I      T      Y                   %
18
%             U   U    T      I    L        I      T      Y                   %
19
%              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
20
%                                                                             %
21
%                                                                             %
22
%                     GraphicsMagick Utility Methods                          %
23
%                                                                             %
24
%                                                                             %
25
%                             Software Design                                 %
26
%                               John Cristy                                   %
27
%                              January 1993                                   %
28
%                                                                             %
29
%                                                                             %
30
%                                                                             %
31
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32
%
33
%
34
*/
35

36
/*
37
  Include declarations.
38
*/
39
#include "magick/studio.h"
40
#include "magick/analyze.h"
41
#include "magick/attribute.h"
42
#include "magick/blob.h"
43
#include "magick/color.h"
44
#include "magick/confirm_access.h"
45
#include "magick/enum_strings.h"
46
#include "magick/log.h"
47
#include "magick/magick.h"
48
#include "magick/pixel_cache.h"
49
#include "magick/random.h"
50
#include "magick/signature.h"
51
#include "magick/tempfile.h"
52
#include "magick/utility.h"
53
54
#if defined(HAVE_MACH_O_DYLD_H)
55
/* Needed for _NSGetExecutablePath */
56
# include <mach-o/dyld.h>
57
#endif
58
59
#if defined(HAVE_SPAWNVP) && defined(HAVE_PROCESS_H)
60
#  include <process.h>
61
#endif
62
63
/*
64
  Static declarations.
65
*/
66
static const char
67
  Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
68
69
static const unsigned char
70
  AsciiMap[] =
71
  {
72
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
73
    0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
74
    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
75
    0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
76
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
77
    0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
78
    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
79
    0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
80
    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
81
    0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
82
    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
83
    0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
84
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
85
    0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
86
    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
87
    0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
88
    0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xc5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
89
    0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
90
    0xf8, 0xf9, 0xfa, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
91
    0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
92
    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
93
    0xfc, 0xfd, 0xfe, 0xff,
94
  };
95

96
/*
97
  Forward declaration.
98
*/
99
static int
100
  IsDirectory(const char *);
101
102
static int
103
  MagickStrToD(const char *start,char **end,double *value);
104
105
static MagickPassFail
106
  MagickStrToInt64(const char *start,char **end,magick_int64_t *value);
107

108
/*
109
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
%                                                                             %
111
%                                                                             %
112
%                                                                             %
113
%   A c q u i r e S t r i n g                                                 %
114
%                                                                             %
115
%                                                                             %
116
%                                                                             %
117
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118
%
119
%  AcquireString() allocates memory for a string and copies the source string
120
%  to that memory location (and returns it). This method is best used to
121
%  allocate constant strings since only enough memory to support the data
122
%  is allocated.
123
%
124
%  The format of the AcquireString method is:
125
%
126
%      char *AcquireString(const char *source)
127
%
128
%  A description of each parameter follows:
129
%
130
%    o allocated_string:  Method AcquireString returns a copy of the source
131
%      string.
132
%
133
%    o source: A character string.
134
%
135
%
136
*/
137
MagickExport char *AcquireString(const char *source)
138
36.9M
{
139
36.9M
  char
140
36.9M
    *destination;
141
142
36.9M
  size_t
143
36.9M
    length;
144
145
36.9M
  assert(source != (const char *) NULL);
146
36.9M
  length=strlen(source);
147
36.9M
  destination=MagickAllocateMemory(char *,length+1);
148
36.9M
  if (destination == (char *) NULL)
149
0
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
150
36.9M
      UnableToAllocateString);
151
36.9M
  if (length != 0)
152
32.7M
    (void) memcpy(destination,source,length);
153
36.9M
  destination[length]='\0';
154
36.9M
  return(destination);
155
36.9M
}
156

157
/*
158
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159
%                                                                             %
160
%                                                                             %
161
%                                                                             %
162
%   A l l o c a t e S t r i n g                                               %
163
%                                                                             %
164
%                                                                             %
165
%                                                                             %
166
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167
%
168
%  AllocateString() allocates memory for a string and copies the source string
169
%  to that memory location (and returns it). Additional memory is allocated
170
%  so that subsequent concatenations to the string are most efficient.
171
%
172
%  The format of the AllocateString method is:
173
%
174
%      char *AllocateString(const char *source)
175
%
176
%  A description of each parameter follows:
177
%
178
%    o allocated_string:  Method AllocateString returns a copy of the source
179
%      string.
180
%
181
%    o source: A character string.
182
%
183
%
184
*/
185
MagickExport char *AllocateString(const char *source)
186
4.71M
{
187
4.71M
  char
188
4.71M
    *destination;
189
190
4.71M
  size_t
191
4.71M
    allocation_length,
192
4.71M
    source_length;
193
194
4.71M
  allocation_length=MaxTextExtent;
195
4.71M
  source_length=0;
196
4.71M
  if (source != (char *) NULL)
197
4.71M
    {
198
4.71M
      source_length=strlen(source);
199
4.71M
      allocation_length=source_length+1;
200
4.71M
      MagickRoundUpStringLength(allocation_length);
201
4.71M
    }
202
4.71M
  destination=MagickAllocateMemory(char *,allocation_length);
203
4.71M
  if (destination == (char *) NULL)
204
0
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
205
4.71M
      UnableToAllocateString);
206
4.71M
  if (source_length != 0)
207
4.26M
    (void) memcpy(destination,source,source_length);
208
4.71M
  destination[source_length]='\0';
209
4.71M
  return(destination);
210
4.71M
}
211

212
/*
213
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214
%                                                                             %
215
%                                                                             %
216
%                                                                             %
217
%  A p p e n d I m a g e F o r m a t                                          %
218
%                                                                             %
219
%                                                                             %
220
%                                                                             %
221
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222
%
223
%  AppendImageFormat() appends the image format type to the filename.  If an
224
%  extension to the file already exists, it is first removed.
225
%
226
%  The format of the AppendImageFormat method is:
227
%
228
%      void AppendImageFormat(const char *format,char *filename)
229
%
230
%  A description of each parameter follows.
231
%
232
%   o  format:  Specifies a pointer to an array of characters.  This is the
233
%      format of the image.
234
%
235
%   o  filename:  Specifies a pointer to an array of characters.  The unique
236
%      file name is returned in this array.
237
%
238
%
239
*/
240
MagickExport void AppendImageFormat(const char *format,char *filename)
241
64.2k
{
242
64.2k
  char
243
64.2k
    root[MaxTextExtent];
244
245
64.2k
  assert(format != (char *) NULL);
246
64.2k
  assert(filename != (char *) NULL);
247
64.2k
  if ((*format == '\0') || (*filename == '\0'))
248
17
    return;
249
64.1k
  if (LocaleCompare(filename,"-") == 0)
250
0
    {
251
0
      char
252
0
        message[MaxTextExtent];
253
254
0
      MagickFormatString(message,sizeof(message),"%.1024s:%.1024s",format,filename);
255
0
      (void) strlcpy(filename,message,MaxTextExtent);
256
0
      return;
257
0
    }
258
64.1k
  GetPathComponent(filename,RootPath,root);
259
64.1k
  MagickFormatString(filename,MaxTextExtent,"%.1024s.%.1024s",root,format);
260
64.1k
}
261

262
/*
263
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264
%                                                                             %
265
%                                                                             %
266
%                                                                             %
267
%   B a s e 6 4 D e c o d e                                                   %
268
%                                                                             %
269
%                                                                             %
270
%                                                                             %
271
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
%
273
%  Base64Decode() decodes Base64-encoded text and returns its binary
274
%  equivalent.  NULL is returned if the text is not valid base64 data, or a
275
%  memory allocation failure occurs.
276
%
277
%  Contributed by Bob Friesenhahn.
278
%
279
%  The format of the Base64Decode method is:
280
%
281
%      unsigned char *Base64Decode(const char *source,length_t *length)
282
%
283
%  A description of each parameter follows:
284
%
285
%    o source:  A pointer to a Base64-encoded string.
286
%
287
%    o length: The number of bytes decoded.
288
%
289
*/
290
MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
291
31.9k
{
292
31.9k
  int
293
31.9k
    state;
294
295
31.9k
  register const char
296
31.9k
    *p,
297
31.9k
    *q;
298
299
31.9k
  register size_t
300
31.9k
    i;
301
302
31.9k
  size_t
303
31.9k
    max_length;
304
305
31.9k
  unsigned char
306
31.9k
    *decode;
307
308
31.9k
  assert(source != (char *) NULL);
309
31.9k
  assert(length != (size_t *) NULL);
310
31.9k
  *length=0;
311
31.9k
  max_length=3*strlen(source)/4+1;
312
31.9k
  decode=MagickAllocateMemory(unsigned char *,max_length);
313
31.9k
  if (decode == (unsigned char *) NULL)
314
0
    return((unsigned char *) NULL);
315
31.9k
  i=0;
316
31.9k
  state=0;
317
55.1M
  for (p=source; *p != '\0'; p++)
318
55.0M
  {
319
55.0M
    if (isspace((int)(unsigned char) *p))
320
1.02M
      continue;
321
54.0M
    if (*p == '=')
322
1.59k
      break;
323
54.0M
    q=strchr(Base64,*p);
324
54.0M
    if (q == (char *) NULL)
325
111
      {
326
111
        MagickFreeMemory(decode);
327
111
        return((unsigned char *) NULL);  /* non-base64 character */
328
111
      }
329
54.0M
    switch (state)
330
54.0M
    {
331
13.5M
      case 0:
332
13.5M
      {
333
13.5M
        decode[i]=(q-Base64) << 2;
334
13.5M
        state++;
335
13.5M
        break;
336
0
      }
337
13.5M
      case 1:
338
13.5M
      {
339
13.5M
        decode[i++]|=(q-Base64) >> 4;
340
13.5M
        decode[i]=((q-Base64) & 0x0f) << 4;
341
13.5M
        state++;
342
13.5M
        break;
343
0
      }
344
13.5M
      case 2:
345
13.5M
      {
346
13.5M
        decode[i++]|=(q-Base64) >> 2;
347
13.5M
        decode[i]=((q-Base64) & 0x03) << 6;
348
13.5M
        state++;
349
13.5M
        break;
350
0
      }
351
13.5M
      case 3:
352
13.5M
      {
353
13.5M
        decode[i++]|=(q-Base64);
354
13.5M
        state=0;
355
13.5M
        break;
356
0
      }
357
54.0M
    }
358
54.0M
  }
359
  /*
360
    Verify Base-64 string has proper terminal characters.
361
  */
362
31.8k
  if (*p != '=')
363
30.2k
    {
364
30.2k
      if (state != 0)
365
60
        {
366
60
          MagickFreeMemory(decode);
367
60
          return((unsigned char *) NULL);
368
60
        }
369
30.2k
    }
370
1.59k
  else
371
1.59k
    {
372
1.59k
      p++;
373
1.59k
      switch (state)
374
1.59k
      {
375
4
        case 0:
376
10
        case 1:
377
10
        {
378
          /*
379
            Unrecognized '=' character.
380
          */
381
10
          MagickFreeMemory(decode);
382
10
          return((unsigned char *) NULL);
383
4
        }
384
838
        case 2:
385
838
        {
386
1.37k
          for ( ; *p != '\0'; p++)
387
1.36k
            if (!isspace((int)(unsigned char)*p))
388
830
              break;
389
838
          if (*p != '=')
390
24
            {
391
24
              MagickFreeMemory(decode);
392
24
              return((unsigned char *) NULL);
393
24
            }
394
814
          p++;
395
814
          break;
396
838
        }
397
751
        case 3:
398
751
        {
399
1.29k
          for ( ; *p != '\0'; p++)
400
562
            if (!isspace((int)(unsigned char) *p))
401
16
              {
402
16
                MagickFreeMemory(decode);
403
16
                return((unsigned char *) NULL);
404
16
              }
405
735
          if (decode[i] != 0)
406
6
            {
407
6
              MagickFreeMemory(decode);
408
6
              return((unsigned char *) NULL);
409
6
            }
410
729
          break;
411
735
        }
412
1.59k
      }
413
1.59k
    }
414
31.7k
  *length=i;
415
31.7k
  assert(*length < max_length);
416
31.7k
  return(decode);
417
31.7k
}
418

419
/*
420
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421
%                                                                             %
422
%                                                                             %
423
%                                                                             %
424
%   B a s e 6 4 E n c o d e                                                   %
425
%                                                                             %
426
%                                                                             %
427
%                                                                             %
428
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429
%
430
%  Base64Encode() encodes arbitrary binary data to base64 encoded format as
431
%  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
432
%  returns the result as a null-terminated ASCII string.  NULL is returned if
433
%  a memory allocation failure occurs.
434
%
435
%  Contributed by Bob Friesenhahn.
436
%
437
%  The format of the Base64Encode method is:
438
%
439
%      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
440
%        size_t *encode_length)
441
%
442
%  A description of each parameter follows:
443
%
444
%    o blob:           A pointer to binary data to encode.
445
%
446
%    o blob_length:    The number of bytes to encode.
447
%
448
%    o encode_length:  The number of bytes encoded.
449
%
450
*/
451
61.3M
#define Index64(index) ((index) & 0x3f)
452
MagickExport char *Base64Encode(const unsigned char *blob,
453
  const size_t blob_length,size_t *encode_length)
454
3.13k
{
455
3.13k
  char
456
3.13k
    *encode;
457
458
3.13k
  register const unsigned char
459
3.13k
    *p;
460
461
3.13k
  register size_t
462
3.13k
    i;
463
464
3.13k
  size_t
465
3.13k
    max_length,
466
3.13k
    remaining;
467
468
3.13k
  assert(blob != (const unsigned char *) NULL);
469
3.13k
  assert(blob_length != 0);
470
3.13k
  assert(encode_length != (size_t *) NULL);
471
3.13k
  *encode_length=0;
472
3.13k
  max_length=MagickArraySize(4U,blob_length)/3U;
473
3.13k
  if (max_length)
474
3.13k
    max_length += 4U;
475
3.13k
  encode=MagickAllocateMemory(char *,max_length);
476
3.13k
  if (encode == (char *) NULL)
477
0
    return((char *) NULL);
478
3.13k
  i=0;
479
15.3M
  for (p=blob; p < (blob+blob_length-2); p+=3)
480
15.3M
  {
481
15.3M
    encode[i++]=Base64[Index64(*p >> 2)];
482
15.3M
    encode[i++]=Base64[Index64(((*p & 0x03) << 4)+(*(p+1) >> 4))];
483
15.3M
    encode[i++]=Base64[Index64(((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
484
15.3M
    encode[i++]=Base64[Index64(*(p+2))];
485
15.3M
  }
486
3.13k
  remaining=blob_length % 3;
487
3.13k
  if (remaining != 0)
488
2.19k
    {
489
2.19k
      long
490
2.19k
        j;
491
492
2.19k
      unsigned char
493
2.19k
        code[3];
494
495
2.19k
      code[0]='\0';
496
2.19k
      code[1]='\0';
497
2.19k
      code[2]='\0';
498
5.57k
      for (j=0; j < (long) remaining; j++)
499
3.38k
        code[j]=(*p++);
500
2.19k
      encode[i++]=Base64[Index64(code[0] >> 2)];
501
2.19k
      encode[i++]=Base64[Index64(((code[0] & 0x03) << 4)+(code[1] >> 4))];
502
2.19k
      if (remaining == 1)
503
1.00k
        encode[i++]='=';
504
1.19k
      else
505
1.19k
        encode[i++]=Base64[Index64(((code[1] & 0x0f) << 2)+(code[2] >> 6))];
506
2.19k
      encode[i++]='=';
507
2.19k
    }
508
3.13k
  *encode_length=i;
509
3.13k
  encode[i++]='\0';
510
3.13k
  assert(i <= max_length);
511
3.13k
  return(encode);
512
3.13k
}
513

514
/*
515
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516
%                                                                             %
517
%                                                                             %
518
%                                                                             %
519
%   C l o n e S t r i n g                                                     %
520
%                                                                             %
521
%                                                                             %
522
%                                                                             %
523
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524
%
525
%  Method CloneString allocates memory for the destination string and copies
526
%  the source string to that memory location.
527
%
528
%  The format of the CloneString method is:
529
%
530
%      MagickPassFail CloneString(char **destination,const char *source)
531
%
532
%  A description of each parameter follows:
533
%
534
%    o status:  Method CloneString returns MagickPass if the string is cloned,
535
%      otherwise MagickFail is returned.
536
%
537
%    o destination:  A pointer to a character string.
538
%
539
%    o source: A character string.
540
%
541
%
542
*/
543
MagickExport MagickPassFail CloneString(char **destination,const char *source)
544
565k
{
545
565k
  size_t
546
565k
    allocation_length,
547
565k
    string_length;
548
549
565k
  assert(destination != (char **) NULL);
550
565k
  if (source == (const char *) NULL)
551
0
    {
552
0
      MagickFreeMemory(*destination);
553
0
      return(MagickPass);
554
0
    }
555
565k
  string_length=strlen(source);
556
565k
  allocation_length=string_length+1;
557
565k
  MagickRoundUpStringLength(allocation_length);
558
565k
  MagickReallocMemory(char *,*destination,allocation_length);
559
565k
  if (*destination == (char *) NULL)
560
0
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
561
565k
      UnableToAllocateString);
562
565k
  if (0 != string_length)
563
531k
    (void) memcpy(*destination,source,string_length);
564
565k
  (*destination)[string_length]='\0';
565
565k
  return(MagickPass);
566
565k
}
567

568
/*
569
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570
%                                                                             %
571
%                                                                             %
572
%                                                                             %
573
%   C o n c a t e n a t e S t r i n g                                         %
574
%                                                                             %
575
%                                                                             %
576
%                                                                             %
577
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578
%
579
%  Method ConcatenateString appends a copy of string source, including
580
%  the terminating null character, to the end of string destination.
581
%
582
%  The format of the ConcatenateString method is:
583
%
584
%      MagickPassFail ConcatenateString(char **destination,const char *source)
585
%
586
%  A description of each parameter follows:
587
%
588
%    o status:  Method ConcatenateString returns MagickPass if the string is cloned,
589
%      otherwise MagickFail is returned.
590
%
591
%    o destination:  A pointer to a character string.
592
%
593
%    o source: A character string.
594
%
595
%
596
*/
597
MagickExport MagickPassFail ConcatenateString(char **destination,
598
  const char *source)
599
495k
{
600
495k
  size_t
601
495k
    allocation_length,
602
495k
    destination_length=0,
603
495k
    source_length;
604
605
495k
  assert(destination != (char **) NULL);
606
495k
  if (source == (const char *) NULL)
607
0
    return(MagickPass);
608
495k
  source_length=strlen(source);
609
495k
  if (*destination != (char *) NULL)
610
61.1k
    destination_length=strlen(*destination);
611
495k
  allocation_length=destination_length+source_length+1;
612
495k
  MagickRoundUpStringLength(allocation_length);
613
495k
  MagickReallocMemory(char *,(*destination),allocation_length);
614
495k
  if (*destination == (char *) NULL)
615
0
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
616
495k
      UnableToConcatenateString);
617
495k
  if (0 != source_length)
618
495k
    (void) memcpy(&(*destination)[destination_length],source,source_length);
619
495k
  (*destination)[destination_length+source_length]='\0';
620
495k
  return(MagickPass);
621
495k
}
622

623
/*
624
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625
%                                                                             %
626
%                                                                             %
627
%                                                                             %
628
%   D e f i n e C l i e n t N a m e                                           %
629
%                                                                             %
630
%                                                                             %
631
%                                                                             %
632
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
633
%
634
%  DefineClientName() this is a helper function that parses the passed string
635
%    in order to define the name of the client application.
636
%
637
%  The format of the DefineClientName method is:
638
%
639
%      void DefineClientName(const char *path)
640
%
641
%  A description of each parameter follows:
642
%
643
%    o path: A string that can also be a full path that contains the name of
644
%            application
645
%
646
*/
647
MagickExport void DefineClientName(const char *path)
648
252
{
649
252
  if ((path != (char *) NULL) && (*path != '\0'))
650
252
    {
651
252
      char
652
252
        component[MaxTextExtent];
653
654
252
      GetPathComponent(path,BasePath,component);
655
252
      (void) SetClientName(component);
656
252
    }
657
252
}
658

659
/*
660
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661
%                                                                             %
662
%                                                                             %
663
%                                                                             %
664
%   D e f i n e C l i e n t P a t h A n d N a m e                             %
665
%                                                                             %
666
%                                                                             %
667
%                                                                             %
668
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669
%
670
%  DefineClientPathAndName() this is a helper function that parses the passed
671
%  string in order to define several global settings related to the location of
672
%  the application. It sets the path, the filename, and the display name of the
673
%  client application based on the input string which is assumed to be the full
674
%  and valid path to the client.
675
%
676
%  The format of the DefineClientPathAndName method is:
677
%
678
%      void DefineClientPathAndName(const char *path)
679
%
680
%  A description of each parameter follows:
681
%
682
%    o path: A string that must be a full path that contains the name of
683
%            application
684
%
685
*/
686
MagickExport void DefineClientPathAndName(const char *path)
687
252
{
688
252
  if ((path != (char *) NULL) && (*path != '\0'))
689
252
    {
690
252
      char
691
252
        component[MaxTextExtent];
692
693
      /* This is the path only - including the parent folder */
694
252
      GetPathComponent(path,HeadPath,component);
695
252
      (void) SetClientPath(component);
696
      /* This is the file name AND the extension - of present */
697
252
      GetPathComponent(path,TailPath,component);
698
252
      (void) SetClientFilename(component);
699
      /* The last step is to define a human readable name for
700
         the help and error logging systems. */
701
252
      DefineClientName(component);
702
252
    }
703
252
}
704

705
/*
706
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707
%                                                                             %
708
%                                                                             %
709
%                                                                             %
710
%   E s c a p e S t r i n g                                                   %
711
%                                                                             %
712
%                                                                             %
713
%                                                                             %
714
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715
%
716
%  EscapeString() allocates memory for a backslash-escaped version of a
717
%  source text string, copies the escaped version of the text to that
718
%  memory location while adding backslash characters, and returns the
719
%  escaped string.
720
%
721
%  The format of the EscapeString method is:
722
%
723
%      char *EscapeString(const char *source,const char escape)
724
%
725
%  A description of each parameter follows:
726
%
727
%    o allocated_string:  Method EscapeString returns the escaped string.
728
%
729
%    o source: A character string.
730
%
731
%    o escape: The quoted string termination character to escape (e.g. '"').
732
%
733
*/
734
MagickExport char *EscapeString(const char *source,const char escape)
735
28.1k
{
736
28.1k
  char
737
28.1k
    *destination;
738
739
28.1k
  register char
740
28.1k
    *q;
741
742
28.1k
  register const char
743
28.1k
    *p;
744
745
28.1k
  size_t
746
28.1k
    length;
747
748
28.1k
  assert(source != (const char *) NULL);
749
750
  /*
751
    Use dry-run method to compute required string length.
752
  */
753
28.1k
  length=0;
754
30.2M
  for (p=source; *p; p++)
755
30.1M
    {
756
30.1M
      if ((*p == '\\') || (*p == escape))
757
58.5k
        length++;
758
30.1M
      length++;
759
30.1M
    }
760
28.1k
  destination=MagickAllocateMemory(char *,length+1);
761
28.1k
  if (destination == (char *) NULL)
762
0
    MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
763
28.1k
      UnableToEscapeString);
764
28.1k
  *destination='\0';
765
28.1k
  q=destination;
766
30.2M
  for (p=source; *p; p++)
767
30.1M
    {
768
30.1M
      if ((*p == '\\') || (*p == escape))
769
58.5k
        *q++= '\\';
770
30.1M
      *q++=(*p);
771
30.1M
    }
772
28.1k
  *q=0;
773
28.1k
  return(destination);
774
28.1k
}
775

776
/*
777
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
778
%                                                                             %
779
%                                                                             %
780
%                                                                             %
781
%   E x p a n d F i l e n a m e                                               %
782
%                                                                             %
783
%                                                                             %
784
%                                                                             %
785
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
786
%
787
%  Method ExpandFilename expands '~' in a filename.
788
%
789
%  The format of the ExpandFilename function is:
790
%
791
%      ExpandFilename(char *filename)
792
%
793
%  A description of each parameter follows:
794
%
795
%    o filename: Specifies a pointer to a character array that contains the
796
%      filename.
797
%
798
%
799
*/
800
MagickExport void ExpandFilename(char *filename)
801
0
{
802
0
  char
803
0
    expanded_filename[MaxTextExtent];
804
805
0
  register char
806
0
    *p;
807
808
0
  if (filename == (char *) NULL)
809
0
    return;
810
0
  if (*filename != '~')
811
0
    return;
812
0
  (void) strlcpy(expanded_filename,filename,MaxTextExtent);
813
0
  if (*(filename+1) == '/')
814
0
    {
815
      /*
816
        Substitute ~ with $HOME.
817
      */
818
0
      p=(char *) getenv("HOME");
819
0
      if (p == (char *) NULL)
820
0
        p=(char *) ".";
821
0
      (void) strlcpy(expanded_filename,p,MaxTextExtent);
822
0
      (void) strlcat(expanded_filename,filename+1,MaxTextExtent);
823
0
    }
824
0
  else
825
0
    {
826
0
#if defined(POSIX)
827
0
      char
828
0
        username[MaxTextExtent];
829
830
0
#  if defined(HAVE_GETPWNAM_R)
831
0
      struct  passwd
832
0
        pwd;
833
834
0
      long
835
0
        pwnam_buf_len_s;
836
837
0
      size_t
838
0
        pwnam_buf_len;
839
840
0
      char
841
0
        *pwnam_buf = (char *) NULL;
842
0
#  endif /* if defined(HAVE_GETPWNAM_R) */
843
844
0
      struct passwd
845
0
        *entry;
846
847
      /*
848
        Substitute ~ with home directory from password file.
849
      */
850
0
      (void) strlcpy(username,filename+1,MaxTextExtent);
851
0
      p=strchr(username,'/');
852
0
      if (p != (char *) NULL)
853
0
        *p='\0';
854
855
0
#  if defined(HAVE_GETPWNAM_R)
856
0
      entry=(struct passwd *) NULL;
857
0
      errno = 0;
858
0
      pwnam_buf_len_s = sysconf(_SC_GETPW_R_SIZE_MAX);
859
0
      if (pwnam_buf_len_s <= 0)
860
0
        return;
861
0
      pwnam_buf_len = (size_t) pwnam_buf_len_s;
862
0
      pwnam_buf=MagickAllocateMemory(char *,pwnam_buf_len);
863
0
      if (pwnam_buf != (char *) NULL)
864
0
        (void) getpwnam_r(username,&pwd,pwnam_buf,pwnam_buf_len,&entry);
865
#else
866
      entry=getpwnam(username); /* Thread-unsafe version */
867
#  endif /* if defined(HAVE_GETPWNAM_R) */
868
0
      if (entry != (struct passwd *) NULL)
869
0
        {
870
0
          (void) strncpy(expanded_filename,entry->pw_dir,MaxTextExtent-1);
871
0
          if (p != (char *) NULL)
872
0
            {
873
0
              (void) strlcat(expanded_filename,"/",sizeof(expanded_filename));
874
0
              (void) strlcat(expanded_filename,p+1,sizeof(expanded_filename));
875
0
            }
876
0
        }
877
0
#  if defined(HAVE_GETPWNAM_R)
878
0
      MagickFreeMemory(pwnam_buf);
879
0
#  endif /* if defined(HAVE_GETPWNAM_R) */
880
0
#endif
881
0
    }
882
0
  (void) strlcpy(filename,expanded_filename,MaxTextExtent);
883
0
}
884

885
/*
886
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
887
%                                                                             %
888
%                                                                             %
889
%                                                                             %
890
%   E x p a n d F i l e n a m e s                                             %
891
%                                                                             %
892
%                                                                             %
893
%                                                                             %
894
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895
%
896
%  Method ExpandFilenames checks each argument of the command line vector and
897
%  expands it if they have a wildcard character.  For example, *.jpg might
898
%  expand to:  bird.jpg rose.jpg tiki.jpg.
899
%
900
%  The format of the ExpandFilenames function is:
901
%
902
%      status=ExpandFilenames(int *argc,char ***argv)
903
%
904
%  A description of each parameter follows:
905
%
906
%    o argc: Specifies a pointer to an integer describing the number of
907
%      elements in the argument vector.
908
%
909
%    o argv: Specifies a pointer to a text array containing the command line
910
%      arguments.  The existing argument list is replaced.
911
%
912
%
913
*/
914
MagickExport MagickPassFail ExpandFilenames(int *argc,char ***argv)
915
24
{
916
24
  const
917
24
    size_t prealloc_entries = 1024;
918
919
24
  char
920
24
    current_directory[MaxTextExtent],
921
24
    *option,
922
24
    **vector;
923
924
24
  long
925
24
    count,
926
24
    number_files;
927
928
24
  register long
929
24
    i,
930
24
    j;
931
932
24
  MagickBool
933
24
    first;
934
935
  /*
936
    Allocate argument vector.
937
  */
938
24
  assert(argc != (int *) NULL);
939
24
  assert(argv != (char ***) NULL);
940
24
  vector=MagickAllocateMemory(char **,(*argc+prealloc_entries)*sizeof(char *));
941
24
  if (vector == (char **) NULL)
942
0
    return(MagickFail);
943
  /*
944
    Expand any wildcard filenames.
945
  */
946
24
  current_directory[0]='\0';
947
24
  count=0;
948
48
  for (i=0; i < *argc; i++)
949
24
    {
950
24
      char
951
24
        **filelist,
952
24
        filename[MaxTextExtent],
953
24
        magick[MaxTextExtent],
954
24
        path[MaxTextExtent],
955
24
        subimage[MaxTextExtent];
956
957
24
      option=(*argv)[i];
958
      /* Never throw options away, so copy here, then perhaps modify later */
959
24
      vector[count++]=AcquireString(option);
960
961
      /*
962
        Don't expand or process any VID: argument since the VID coder
963
        does its own expansion
964
      */
965
24
      if (LocaleNCompare("VID:",option,4) == 0)
966
0
        continue;
967
968
      /*
969
        Don't attempt to expand the argument to these options.
970
      */
971
24
      if ((LocaleNCompare("+define",option,7) == 0) ||
972
24
          (LocaleNCompare("+profile",option,8) == 0) ||
973
24
          (LocaleNCompare("-comment",option,8) == 0) ||
974
24
          (LocaleNCompare("-convolve",option,9) == 0) ||
975
24
          (LocaleNCompare("-draw",option,5) == 0) ||
976
24
          (LocaleNCompare("-font",option,5) == 0) ||
977
24
          (LocaleNCompare("-format",option,7) == 0) ||
978
24
          (LocaleNCompare("-label",option,6) == 0))
979
0
        {
980
0
          i++;
981
0
          if (i == *argc)
982
0
            continue;
983
0
          option=(*argv)[i];
984
0
          vector[count++]=AcquireString(option);
985
0
          continue;
986
0
        }
987
988
      /* Pass quotes through to the command-line parser */
989
24
      if ((*option == '"') || (*option == '\''))
990
0
        continue;
991
992
      /*
993
        Expand @filename to a list of arguments.
994
      */
995
24
      j=0;
996
24
      if ((option[0] == '@') && (!IsAccessibleNoLogging(option)))
997
0
        {
998
0
          FILE
999
0
            *file;
1000
1001
0
          file=fopen(option+1,"r");
1002
0
          if (file != (FILE *) NULL)
1003
0
            {
1004
1005
0
              first=MagickTrue;
1006
0
              number_files=0;
1007
0
              while (fgets(filename,sizeof(filename),file) != (char *) NULL)
1008
0
                {
1009
0
                  for (j=0; filename[j] != '\0'; j++)
1010
0
                    if (filename[j] == '\n')
1011
0
                      filename[j] = '\0';
1012
1013
0
                  if (filename[0] != '\0')
1014
0
                    {
1015
0
                      if ((number_files % prealloc_entries) == 0)
1016
0
                        {
1017
0
                          char **new_vector;
1018
0
                          new_vector=
1019
0
                            (char **) MagickRealloc(vector,
1020
0
                                                    MagickArraySize((size_t) *argc+count+prealloc_entries,
1021
0
                                                                    sizeof(char *)));
1022
0
                          if (new_vector == (char **) NULL)
1023
0
                            {
1024
0
                              for (j=0 ; j < count; j++)
1025
0
                                MagickFreeMemory(vector[j]);
1026
0
                              MagickFreeMemory(vector);
1027
0
                              fclose(file);
1028
0
                              return(MagickFail);
1029
0
                            }
1030
0
                          vector = new_vector;
1031
0
                        }
1032
1033
0
                      if (first)
1034
0
                        {
1035
                          /* Deallocate original option assigned above */
1036
0
                          --count;
1037
0
                          MagickFreeMemory(vector[count]);
1038
0
                          first=MagickFalse;
1039
0
                        }
1040
0
                      number_files++;
1041
0
                      vector[count++]=AcquireString(filename);
1042
0
                    }
1043
0
                }
1044
1045
0
              fclose(file);
1046
0
            }
1047
0
        }
1048
1049
      /*
1050
         Fast cycle options that are not expandable filename patterns.
1051
         ListFiles only expands patterns in the filename.  We also check
1052
         if the full option resolves to a file since ListFiles() obtains
1053
         a list of all the files in the directory and is thus very slow
1054
         if there are thousands of files.
1055
      */
1056
24
      GetPathComponent(option,TailPath,filename);
1057
24
      if ((!IsGlob(filename)) || IsAccessibleNoLogging(option))
1058
24
        continue;
1059
1060
      /* Chop the option to get its other filename components. */
1061
0
      GetPathComponent(option,MagickPath,magick);
1062
0
      GetPathComponent(option,HeadPath,path);
1063
0
      GetPathComponent(option,SubImagePath,subimage);
1064
1065
      /* GetPathComponent throws away the colon */
1066
0
      if (*magick != '\0')
1067
0
        (void) strlcat(magick,":",sizeof(magick));
1068
0
      ExpandFilename(path);
1069
1070
0
      if ('\0' == current_directory[0])
1071
0
        if (getcwd(current_directory,MaxTextExtent-1) == NULL)
1072
0
          MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1073
0
                           NULL);
1074
1075
      /* Get the list of matching file names. */
1076
0
      filelist=ListFiles(*path=='\0' ? current_directory : path,
1077
0
                         filename,&number_files);
1078
1079
0
      if (filelist != (char **) NULL)
1080
0
        for (j=0; j < number_files; j++)
1081
0
          if (IsDirectory(filelist[j]) <= 0)
1082
0
            break;
1083
1084
      /* ListFiles() may change current directory without restoring. */
1085
0
      if ((strlen(current_directory) > 0) && (chdir(current_directory) != 0))
1086
0
        {
1087
0
          if (filelist != (char **) NULL)
1088
0
            {
1089
0
              for (j=0; j < number_files; j++)
1090
0
                MagickFreeMemory(filelist[j]);
1091
0
              MagickFreeMemory(filelist);
1092
0
            }
1093
0
          MagickFatalError(ConfigureFatalError,UnableToRestoreCurrentDirectory,
1094
0
                           NULL);
1095
0
        }
1096
1097
0
      if (filelist == 0)
1098
0
        continue;
1099
1100
0
      if (j == number_files)
1101
0
        {
1102
          /*
1103
            Bourne/Bash shells passes through unchanged any glob patterns
1104
            not matching anything (abc* and there's no file starting with
1105
            abc). Do the same for behaviour consistent with that.
1106
          */
1107
0
          if (filelist != (char **) NULL)
1108
0
            {
1109
0
              for (j=0; j < number_files; j++)
1110
0
                MagickFreeMemory(filelist[j]);
1111
0
              MagickFreeMemory(filelist);
1112
0
            }
1113
0
          continue;
1114
0
        }
1115
1116
      /*
1117
        There's at least one matching filename.
1118
        Transfer file list to argument vector.
1119
      */
1120
0
      {
1121
0
         char **new_vector;
1122
0
         new_vector =
1123
0
           (char **) MagickRealloc(vector,
1124
0
                                   MagickArraySize((size_t) *argc+count+number_files+prealloc_entries,
1125
0
                                                   sizeof(char *)));
1126
0
         if (new_vector == (char **) NULL)
1127
0
           {
1128
0
             for (j=0 ; j < count; j++)
1129
0
               MagickFreeMemory(vector[j]);
1130
0
             MagickFreeMemory(vector);
1131
0
             if (filelist != (char **) NULL)
1132
0
               {
1133
0
                 for (j=0; j < number_files; j++)
1134
0
                   MagickFreeMemory(filelist[j]);
1135
0
                 MagickFreeMemory(filelist);
1136
0
               }
1137
0
             return(MagickFail);
1138
0
           }
1139
0
         vector=new_vector;
1140
0
      }
1141
1142
0
      first=MagickTrue;
1143
0
      for (j=0; j < number_files; j++)
1144
0
        {
1145
0
          char
1146
0
            filename_buffer[MaxTextExtent];
1147
1148
0
          if (filelist[j] == (const char *) NULL)
1149
0
            continue;
1150
0
          filename_buffer[0]='\0';
1151
0
          if (strlcat(filename_buffer,path,sizeof(filename_buffer))
1152
0
              >= sizeof(filename_buffer))
1153
0
            MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1154
0
                              filename_buffer);
1155
0
          if (*path != '\0')
1156
0
            {
1157
0
              if (strlcat(filename_buffer,DirectorySeparator,sizeof(filename_buffer))
1158
0
                  >= sizeof(filename_buffer))
1159
0
                MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1160
0
                                  filename_buffer);
1161
0
            }
1162
0
          if (strlcat(filename_buffer,filelist[j],sizeof(filename_buffer))
1163
0
              >= sizeof(filename_buffer))
1164
0
            MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1165
0
                              filename_buffer);
1166
          /* If it's a filename (not a directory) ... */
1167
0
          if (IsDirectory(filename_buffer) == 0)
1168
0
            {
1169
0
              char
1170
0
                formatted_buffer[MaxTextExtent];
1171
1172
0
              *formatted_buffer='\0';
1173
0
              if (strlcat(formatted_buffer,magick,sizeof(formatted_buffer))
1174
0
                  >= sizeof(formatted_buffer))
1175
0
                MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1176
0
                                  formatted_buffer);
1177
0
              if (strlcat(formatted_buffer,filename_buffer,sizeof(formatted_buffer))
1178
0
                  >= sizeof(formatted_buffer))
1179
0
                MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1180
0
                                  formatted_buffer);
1181
0
              if (strlcat(formatted_buffer,subimage,sizeof(formatted_buffer))
1182
0
                  >= sizeof(formatted_buffer))
1183
0
                MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
1184
0
                                  formatted_buffer);
1185
0
              if (first)
1186
0
                {
1187
                  /* Deallocate original option assigned above */
1188
0
                  --count;
1189
0
                  MagickFreeMemory(vector[count]);
1190
0
                  first=MagickFalse;
1191
0
                }
1192
0
              vector[count++]=AcquireString(formatted_buffer);
1193
0
            }
1194
0
          MagickFreeMemory(filelist[j]);
1195
0
        }
1196
0
      MagickFreeMemory(filelist);
1197
0
    }
1198
24
  *argc=count;
1199
24
  *argv=vector;
1200
24
  return(MagickPass);
1201
24
}
1202

1203
/*
1204
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1205
%                                                                             %
1206
%                                                                             %
1207
%                                                                             %
1208
%  F o r m a t S i z e                                                        %
1209
%                                                                             %
1210
%                                                                             %
1211
%                                                                             %
1212
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1213
%
1214
%  FormatSize() converts a size to a human readable format, for example,
1215
%  14kb, 234mb, 2.7gb, or 3.0tb.  Scaling is done by repetitively dividing by
1216
%  1024.
1217
%
1218
%  The format of the FormatSize method is:
1219
%
1220
%      char *FormatSize(const magick_int64_t size,char *format)
1221
%
1222
%  A description of each parameter follows:
1223
%
1224
%    o size:  convert this size to a human readable format.
1225
%
1226
%    o format:  human readable format.
1227
%
1228
%
1229
*/
1230
MagickExport void FormatSize(const magick_int64_t size,char *format)
1231
1.09M
{
1232
1.09M
  double
1233
1.09M
    length;
1234
1235
1.09M
  register unsigned int
1236
1.09M
    i;
1237
1238
1.09M
  length=size;
1239
1.55M
  for (i=0; length > 1024; i++)
1240
461k
    length/=1024.0;
1241
1.09M
  if (i > 0)
1242
390k
    MagickFormatString(format,MaxTextExtent,"%.1f",length);
1243
702k
  else
1244
702k
    MagickFormatString(format,MaxTextExtent,"%.0f",length);
1245
1.09M
  switch (i)
1246
1.09M
    {
1247
0
    default: break;
1248
702k
    case 0: break;
1249
327k
    case 1: (void) strlcat(format,"Ki",MaxTextExtent); break; /* kilo, 10^3 */
1250
55.7k
    case 2: (void) strlcat(format,"Mi",MaxTextExtent); break; /* mega, 10^6 */
1251
7.53k
    case 3: (void) strlcat(format,"Gi",MaxTextExtent); break; /* giga, 10^9 */
1252
0
    case 4: (void) strlcat(format,"Ti",MaxTextExtent); break; /* tera, 10^12 */
1253
0
    case 5: (void) strlcat(format,"Pi",MaxTextExtent); break; /* peta, 10^15 */
1254
0
    case 6: (void) strlcat(format,"Ei",MaxTextExtent); break; /* exa,  10^18 */
1255
1.09M
    }
1256
1.09M
}
1257

1258
/*
1259
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260
%                                                                             %
1261
%                                                                             %
1262
%                                                                             %
1263
%  F o r m a t S t r i n g                                                    %
1264
%                                                                             %
1265
%                                                                             %
1266
%                                                                             %
1267
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1268
%
1269
%  Method FormatString prints formatted output of a variable argument list
1270
%  buffer, limiting its output to MaxTextExtent.
1271
%  The formatted size (as would be returned by strlen()) is returned.
1272
%
1273
%  The format of the FormatString method is:
1274
%
1275
%      size_t FormatString(char *string,const char *format,...)
1276
%
1277
%  A description of each parameter follows.
1278
%
1279
%   o  string:  Method FormatString returns the formatted string in this
1280
%      character buffer. Buffer must be at least MaxTextExtent characters
1281
%      in size.
1282
%
1283
%   o  format:  A string describing the format to use to write the remaining
1284
%      arguments.
1285
%
1286
%
1287
*/
1288
MagickExport size_t FormatStringList(char *string,const char *format,
1289
                                     va_list operands)
1290
0
{
1291
0
  size_t
1292
0
    fls = 0;
1293
1294
0
  int
1295
0
    fli;
1296
1297
0
  fli=vsnprintf(string,MaxTextExtent,format,operands);
1298
0
  if (fli >= MaxTextExtent)
1299
0
    fls=MaxTextExtent-1;
1300
0
  else if (fli > 0)
1301
0
    fls=(size_t) fli;
1302
0
  return fls;
1303
0
}
1304
MagickExport size_t FormatString(char *string,const char *format,...)
1305
0
{
1306
0
  va_list
1307
0
    operands;
1308
1309
0
  size_t
1310
0
    formatted_len;
1311
1312
0
  va_start(operands,format);
1313
0
  formatted_len=MagickFormatStringList(string, MaxTextExtent, format, operands);
1314
0
  va_end(operands);
1315
0
  return formatted_len;
1316
0
}
1317

1318
/*
1319
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320
%                                                                             %
1321
%                                                                             %
1322
%                                                                             %
1323
%   G e t E x e c u t i o n P a t h                                           %
1324
%                                                                             %
1325
%                                                                             %
1326
%                                                                             %
1327
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1328
%
1329
%  GetExecutionPath() returns the pathname of the executable that started
1330
%  the process. The user-supplied buffer must be at least MaxTextExtent
1331
%  bytes long.  On success True is returned, otherwise False.
1332
%
1333
%  The format of the GetExecutionPath method is:
1334
%
1335
%      unsigned int GetExecutionPath(char *path)
1336
%
1337
%  A description of each parameter follows:
1338
%
1339
%    o path: The pathname of the executable that started the process.
1340
%
1341
*/
1342
MagickExport MagickPassFail GetExecutionPath(char *path)
1343
0
{
1344
0
  *path='\0';
1345
#if defined(MSWINDOWS)
1346
  /*
1347
    Microsoft Windows provides an means to obtain the path to the
1348
    currently executing executable or DLL.
1349
  */
1350
  return(NTGetExecutionPath(path));
1351
#endif
1352
#if defined(HAVE_GETEXECNAME)
1353
  {
1354
    /*
1355
      Sun's Solaris provides a getexecname() for obtaining the path to
1356
      this executable.
1357
    */
1358
    const char
1359
      *execution_path;
1360
1361
    execution_path=(const char *) getexecname();
1362
    if (execution_path != (const char *) NULL)
1363
      {
1364
        if (*execution_path != *DirectorySeparator)
1365
          {
1366
            if (getcwd(path,MaxTextExtent-1) == NULL)
1367
              MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1368
                               NULL);
1369
            (void) strlcat(path,"/",MaxTextExtent);
1370
          }
1371
        (void) strlcat(path,execution_path,MaxTextExtent);
1372
        if (IsAccessible(path))
1373
          return(MagickPass);
1374
      }
1375
  }
1376
#endif
1377
#if defined(HAVE__NSGETEXECUTABLEPATH) && defined(HAVE_REALPATH)
1378
  {
1379
    /*
1380
      Apple OS-X provides a _NSGetExecutablePath function for
1381
      obtaining the path to the executable.  The returned path may be
1382
      a symbolic link to the actual executable so use realpath() to
1383
      resolve the real path.  It is claimed that _NSGetExecutablePath
1384
      could possibly return a path longer than MAXPATHLEN.  Inspection
1385
      of <sys/param.h> on an OS-X system reveals that MAXPATHLEN is
1386
      defined to be PATH_MAX. So we will provide for PATH_MAX*2.
1387
    */
1388
    uint32_t
1389
      bufsize;
1390
1391
    char
1392
      executable_path[PATH_MAX*2],
1393
      real_path[PATH_MAX+1];
1394
1395
    bufsize=sizeof(executable_path);
1396
    if (_NSGetExecutablePath(executable_path,&bufsize) == 0)
1397
      if (realpath(executable_path,real_path) != NULL)
1398
        if (strlcpy(path,real_path,MaxTextExtent) < MaxTextExtent)
1399
          if (IsAccessible(path))
1400
            return(MagickPass);
1401
  }
1402
#endif
1403
0
#if defined(HAVE_GETPID) && defined(HAVE_READLINK)
1404
0
  {
1405
    /*
1406
      On Linux, the symbolic link "/proc/PID/exe" (where 'PID' is the
1407
      integer process ID) points to the physical executable.  FreeBSD
1408
      is similar except that the link path is "/proc/PID/file".  Maybe
1409
      some other systems use compatible schemes.
1410
    */
1411
0
    int
1412
0
      length;
1413
1414
0
    long
1415
0
      pid;
1416
1417
0
    char
1418
0
      link_path[MaxTextExtent],
1419
0
      real_path[PATH_MAX+1];
1420
1421
0
    pid=(long) getpid();
1422
    /* Linux format */
1423
0
    MagickFormatString(link_path,sizeof(link_path),"/proc/%ld/exe",pid);
1424
0
    length=readlink(link_path, real_path, PATH_MAX);
1425
0
    if (length == -1)
1426
0
      {
1427
        /* Try FreeBSD format */
1428
0
        MagickFormatString(link_path,sizeof(link_path),"/proc/%ld/file",pid);
1429
0
        length=readlink(link_path, real_path, PATH_MAX);
1430
0
      }
1431
0
    if ((length > 0) && (length <= PATH_MAX))
1432
0
      {
1433
0
        real_path[length]=0;
1434
0
        if (strlcpy(path,real_path,MaxTextExtent) < MaxTextExtent)
1435
0
          if (IsAccessible(path))
1436
0
            return(MagickPass);
1437
0
      }
1438
0
  }
1439
0
#endif
1440
0
  return(MagickFail);
1441
0
}
1442

1443
/*
1444
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1445
%                                                                             %
1446
%                                                                             %
1447
%                                                                             %
1448
%   G e t E x e c u t i o n P a t h U s i n g N a m e                         %
1449
%                                                                             %
1450
%                                                                             %
1451
%                                                                             %
1452
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1453
%
1454
%  GetExecutionPathUsingName() replaces the provided path with the full
1455
%  path to the directory containing the executable.  The replaced path
1456
%  is terminated by a directory separator.  The provided path may be
1457
%  a bare executable name, a relative path to the executable, or the
1458
%  full path to the executable.  The provided path is usually obtained
1459
%  from the argv[0] argument to main. If the path is a bare executable
1460
%  name, then the executable is located via the executable search path.
1461
%  If the path is replaced, then MagickPass is returned, otherwise
1462
%  MagickFail is returned.
1463
%
1464
%  The format of the GetExecutionPathUsingName method is:
1465
%
1466
%      unsigned int GetExecutionPathUsingName(char *path)
1467
%
1468
%  A description of each parameter follows:
1469
%
1470
%    o path: The path (partial or complete) to the executable.
1471
%
1472
*/
1473
MagickExport MagickPassFail GetExecutionPathUsingName(char *path)
1474
0
{
1475
0
  char
1476
0
    execution_path[MaxTextExtent],
1477
0
    original_cwd[MaxTextExtent],
1478
0
    temporary_path[MaxTextExtent],
1479
0
    *p;
1480
1481
0
  execution_path[0]='\0';
1482
1483
  /*
1484
    Save original working directory so it can be restored later.
1485
  */
1486
0
  if (getcwd(original_cwd,sizeof(original_cwd)-1) == NULL)
1487
0
              MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1488
0
                               NULL);
1489
1490
  /*
1491
    Check to see if path is a valid relative path from current
1492
    directory.
1493
  */
1494
0
  if (IsAccessibleNoLogging(path))
1495
0
    {
1496
      /*
1497
        If we can change directory to the path, then capture the full
1498
        path to it.  Otherwise, remove any trailing path component
1499
        (typically the program name) and try again.
1500
      */
1501
0
      if ((strlen(path) >0 ) && (chdir(path) == 0))
1502
0
        {
1503
0
          if (getcwd(execution_path,sizeof(execution_path)-2) == NULL)
1504
0
            MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1505
0
                             NULL);
1506
0
        }
1507
0
      else
1508
0
        {
1509
0
          (void) strlcpy(temporary_path,path,sizeof(execution_path));
1510
0
          p=strrchr(temporary_path,DirectorySeparator[0]);
1511
0
          if (p)
1512
0
            *p='\0';
1513
0
          if ((strlen(temporary_path) > 0) && (chdir(temporary_path) == 0))
1514
0
            {
1515
0
              if (getcwd(execution_path,sizeof(execution_path)-2) == NULL)
1516
0
                MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1517
0
                                 NULL);
1518
0
            }
1519
0
        }
1520
0
    }
1521
  /*
1522
    Otherwise, check to see if bare program name is available via the
1523
    executable search path.
1524
  */
1525
0
  if ((execution_path[0] == 0) && (strchr(path,DirectorySeparator[0]) == NULL ))
1526
0
  {
1527
0
    const char
1528
0
      *search_path;
1529
1530
0
    search_path=getenv("PATH");
1531
0
    if ( search_path )
1532
0
      {
1533
0
        const char
1534
0
          *end = NULL,
1535
0
          *start = search_path;
1536
1537
0
        end=start+strlen(start);
1538
0
        while ( start < end )
1539
0
          {
1540
0
            const char
1541
0
              *separator;
1542
1543
0
            size_t
1544
0
              length;
1545
1546
0
            separator = strchr(start,DirectoryListSeparator);
1547
0
            if (separator)
1548
0
              length=separator-start;
1549
0
            else
1550
0
              length=end-start;
1551
0
            if (length > MaxTextExtent-1)
1552
0
              length = MaxTextExtent-1;
1553
0
            (void) strlcpy(temporary_path,start,length+1);
1554
0
            if ((strlen(temporary_path) > 0) && (chdir(temporary_path) == 0))
1555
0
              {
1556
0
                if (temporary_path[length-1] != DirectorySeparator[0])
1557
0
                  (void) strlcat(temporary_path,DirectorySeparator,sizeof(temporary_path));
1558
0
                (void) strlcat(temporary_path,path,sizeof(temporary_path));
1559
0
                if (IsAccessibleNoLogging(temporary_path))
1560
0
                  {
1561
0
                    if (getcwd(execution_path,sizeof(execution_path)-2) == NULL)
1562
0
                      MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
1563
0
                                       NULL);
1564
0
                    break;
1565
0
                  }
1566
0
              }
1567
0
            start += length+1;
1568
0
          }
1569
0
      }
1570
0
  }
1571
1572
  /*
1573
    Restore original working directory.
1574
  */
1575
0
  if ((strlen(original_cwd) > 0) && (chdir(original_cwd) != 0))
1576
0
    return(MagickFail);
1577
1578
0
  if (execution_path[0] != '\0')
1579
0
    {
1580
0
      (void) strlcat(execution_path,DirectorySeparator,sizeof(execution_path));
1581
0
      (void) strlcpy(path,execution_path,MaxTextExtent);
1582
0
      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1583
0
                            "Path \"%.1024s\" is usable.",path);
1584
0
      errno=0;
1585
0
      return (MagickPass);
1586
0
    }
1587
1588
0
  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1589
0
                        "Path \"%.1024s\" is not valid.",path);
1590
0
  return(MagickFail);
1591
0
}
1592

1593
/*
1594
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1595
%                                                                             %
1596
%                                                                             %
1597
%                                                                             %
1598
%   G e t G e o m e t r y                                                     %
1599
%                                                                             %
1600
%                                                                             %
1601
%                                                                             %
1602
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603
%
1604
%  GetGeometry() parses a geometry specification and returns the width
1605
%  height, x, and y values.  It also returns flags that indicates which
1606
%  of the four values (width, height, x, y) were located in the string, and
1607
%  whether the x and y values are negative.  In addition, there are flags to
1608
%  report any meta characters (%, !, <,  >, @, and ^).
1609
%
1610
%  The format of the GetGeometry method is:
1611
%
1612
%      int GetGeometry(const char *image_geometry,long *x,long *y,
1613
%        unsigned long *width,unsigned long *height)
1614
%
1615
%  A description of each parameter follows:
1616
%
1617
%    o flags:  Method GetGeometry returns a bitmask that indicates
1618
%      which of the values from GeometryFlags (XValue, YValue, WidthValue,
1619
%      HeightValue, XNegative, YNegative, PercentValue, AspectValue, LessValue,
1620
%      GreaterValue, AreaValue, MinimumValue) were located in the geometry
1621
%      string.
1622
%
1623
%    o image_geometry:  Specifies a character string representing the geometry
1624
%      specification in the form
1625
%      <width>x<height>{+-}<x>{+-}<y>{%}{@}{!}{^}{<}{>}.
1626
%
1627
%    o x,y:  The x and y offset as determined by the geometry specification is
1628
%      returned here.
1629
%
1630
%    o width,height:  The width and height as determined by the geometry
1631
%      specification is returned here.
1632
%
1633
%
1634
*/
1635
286k
#define MagickULongRangeOk(double_val) ((double_val <= (double) ULONG_MAX) && (double_val >= 0.0))
1636
88.1k
#define MagickLongRangeOk(double_val) ((double_val <= (double) LONG_MAX) && (double_val >= (double) LONG_MIN))
1637
MagickExport int GetGeometry(const char *image_geometry,long *x,long *y,
1638
  unsigned long *width,unsigned long *height)
1639
180k
{
1640
180k
  const char
1641
180k
    *c;
1642
1643
180k
  char
1644
180k
    geometry[MaxTextExtent],
1645
180k
    *p,
1646
180k
    *q;
1647
1648
180k
  int
1649
180k
    count,
1650
180k
    flags,
1651
180k
    i;
1652
1653
180k
  double
1654
180k
    double_val;
1655
1656
180k
  RectangleInfo
1657
180k
    bounds;
1658
1659
  /*
1660
    Ensure the image geometry is valid.
1661
  */
1662
180k
  assert(x != (long *) NULL);
1663
180k
  assert(y != (long *) NULL);
1664
180k
  assert(width != (unsigned long *) NULL);
1665
180k
  assert(height != (unsigned long *) NULL);
1666
180k
  if ((image_geometry == (char *) NULL) || (*image_geometry == '\0') ||
1667
176k
      (strlen(image_geometry) > MaxTextExtent-1))
1668
3.88k
    return(NoValue);
1669
1670
  /*
1671
    Transfer base geometry while recording and stripping flags
1672
  */
1673
176k
  i=0;
1674
176k
  q=geometry;
1675
176k
  flags=NoValue;
1676
1677
5.10M
  for (c=image_geometry; *c != 0 ; c++)
1678
4.94M
    {
1679
4.94M
      if (isspace((int) (*c)))
1680
1.55k
        {
1681
1.55k
          continue;
1682
1.55k
        }
1683
4.93M
      else
1684
4.93M
        switch (*c)
1685
4.93M
          {
1686
3.61k
          case '%':
1687
3.61k
            {
1688
3.61k
              flags|=PercentValue;
1689
3.61k
              break;
1690
0
            }
1691
26.2k
          case '!':
1692
26.2k
            {
1693
26.2k
              flags|=AspectValue;
1694
26.2k
              break;
1695
0
            }
1696
2.93k
          case '<':
1697
2.93k
            {
1698
2.93k
              flags|=LessValue;
1699
2.93k
              break;
1700
0
            }
1701
18.3k
          case '>':
1702
18.3k
            {
1703
18.3k
              flags|=GreaterValue;
1704
18.3k
              break;
1705
0
            }
1706
11.1k
          case '@':
1707
11.1k
            {
1708
11.1k
              flags|=AreaValue;
1709
11.1k
              break;
1710
0
            }
1711
18.2k
          case '^':
1712
18.2k
            {
1713
18.2k
              flags|=MinimumValue;
1714
18.2k
              break;
1715
0
            }
1716
102k
          case '+':
1717
173k
          case '-':
1718
184k
          case '.':
1719
3.12M
          case '0':
1720
3.48M
          case '1':
1721
3.63M
          case '2':
1722
3.77M
          case '3':
1723
3.90M
          case '4':
1724
4.00M
          case '5':
1725
4.13M
          case '6':
1726
4.35M
          case '7':
1727
4.50M
          case '8':
1728
4.67M
          case '9':
1729
4.70M
          case 'X':
1730
4.84M
          case 'x':
1731
4.84M
            {
1732
              /* Check for too many characters. */
1733
4.84M
              i++;
1734
4.84M
              if (i == sizeof(geometry)-1)
1735
336
                return NoValue;
1736
1737
4.84M
              *q=*c;
1738
4.84M
              q++;
1739
4.84M
              break;
1740
4.84M
            }
1741
12.7k
          default:
1742
12.7k
            {
1743
              /* Illegal character fails entire geometry translation */
1744
12.7k
              return NoValue;
1745
4.84M
            }
1746
4.93M
          }
1747
4.94M
    }
1748
163k
  *q='\0';
1749
1750
  /*
1751
    Parse width/height/x/y.  At this point resize qualifiers have been
1752
    truncated from the original geometry string.
1753
  */
1754
163k
  bounds.width=0;
1755
163k
  bounds.height=0;
1756
163k
  bounds.x=0;
1757
163k
  bounds.y=0;
1758
163k
  p=geometry;
1759
163k
  while ((*p != '\0') && (isspace((int)(*p))))
1760
0
    p++;
1761
163k
  if (*p == '\0')
1762
1.84k
    return(flags);
1763
161k
  if (*p == '=')
1764
0
    p++;
1765
161k
  if ((*p != '+') && (*p != '-') && (*p != 'x') && (*p != 'X'))
1766
144k
    {
1767
      /*
1768
        Parse width.
1769
      */
1770
144k
      q=p;
1771
1772
144k
      count=MagickStrToD(p,&q,&double_val);
1773
144k
      if (count)
1774
141k
        {
1775
141k
          double_val=floor(double_val+0.5);
1776
141k
          if (MagickULongRangeOk(double_val))
1777
139k
            {
1778
139k
              bounds.width=(unsigned long) double_val;
1779
139k
              flags|=WidthValue;
1780
139k
            }
1781
141k
        }
1782
144k
      if ((*q == 'x') || (*q == 'X') || ((flags & AreaValue) && (*q == '\0')))
1783
133k
        p=q;
1784
10.3k
      else
1785
10.3k
        {
1786
10.3k
          count=MagickStrToD(p,&p,&double_val);
1787
10.3k
          if (count)
1788
7.39k
            {
1789
7.39k
              double_val=floor(double_val+0.5);
1790
7.39k
              if (MagickULongRangeOk(double_val))
1791
6.23k
                {
1792
6.23k
                  bounds.width=(unsigned long) double_val;
1793
6.23k
                  bounds.height=bounds.width;
1794
6.23k
                  flags|=HeightValue;
1795
6.23k
                }
1796
7.39k
            }
1797
10.3k
        }
1798
144k
    }
1799
161k
  if ((*p == 'x') || (*p == 'X'))
1800
141k
    {
1801
      /*
1802
        Parse height.
1803
      */
1804
141k
      p++;
1805
141k
      q=p;
1806
141k
      count=MagickStrToD(p,&p,&double_val);
1807
141k
      if (count)
1808
137k
        {
1809
137k
          double_val=floor(double_val+0.5);
1810
137k
          if (MagickULongRangeOk(double_val))
1811
130k
            {
1812
130k
              bounds.height=(unsigned long) double_val;
1813
130k
              flags|=HeightValue;
1814
130k
            }
1815
137k
        }
1816
141k
    }
1817
161k
  if ((*p == '+') || (*p == '-'))
1818
68.9k
    {
1819
      /*
1820
        Parse x value.
1821
      */
1822
68.9k
      if (*p == '+')
1823
47.4k
        {
1824
47.4k
          p++;
1825
47.4k
          q=p;
1826
47.4k
          count=MagickStrToD(p,&p,&double_val);
1827
47.4k
          if (count)
1828
38.8k
            {
1829
38.8k
              double_val=ceil(double_val-0.5);
1830
38.8k
              if (MagickLongRangeOk(double_val))
1831
37.2k
                {
1832
37.2k
                  bounds.x=(long) double_val;
1833
37.2k
                  flags|=XValue;
1834
37.2k
                }
1835
38.8k
            }
1836
47.4k
        }
1837
21.4k
      else
1838
21.4k
        {
1839
21.4k
          p++;
1840
21.4k
          q=p;
1841
21.4k
          count=MagickStrToD(p,&p,&double_val);
1842
21.4k
          if (count)
1843
7.39k
            {
1844
7.39k
              double_val=ceil(-double_val-0.5);
1845
7.39k
              if (MagickLongRangeOk(double_val))
1846
5.86k
                {
1847
5.86k
                  bounds.x=(long) double_val;
1848
5.86k
                  flags|=XValue;
1849
5.86k
                  flags|=XNegative;
1850
5.86k
                }
1851
7.39k
            }
1852
21.4k
        }
1853
68.9k
      if ((*p == '+') || (*p == '-'))
1854
54.3k
        {
1855
          /*
1856
            Parse y value.
1857
          */
1858
54.3k
          if (*p == '+')
1859
41.2k
            {
1860
41.2k
              p++;
1861
41.2k
              q=p;
1862
41.2k
              count=MagickStrToD(p,&p,&double_val);
1863
41.2k
              if (count)
1864
37.5k
                {
1865
37.5k
                  double_val = ceil(double_val-0.5);
1866
37.5k
                  if (MagickLongRangeOk(double_val))
1867
35.5k
                    {
1868
35.5k
                      bounds.y=(long) double_val;
1869
35.5k
                      flags|=YValue;
1870
35.5k
                    }
1871
37.5k
                }
1872
41.2k
            }
1873
13.1k
          else
1874
13.1k
            {
1875
13.1k
              p++;
1876
13.1k
              q=p;
1877
13.1k
              count=MagickStrToD(p,&p,&double_val);
1878
13.1k
              if (count)
1879
4.45k
                {
1880
4.45k
                  double_val=ceil(-double_val-0.5);
1881
4.45k
                  if (MagickLongRangeOk(double_val))
1882
3.18k
                    {
1883
3.18k
                      bounds.y=(long) ceil(double_val);
1884
3.18k
                      flags|=YValue;
1885
3.18k
                      flags|=YNegative;
1886
3.18k
                    }
1887
4.45k
                }
1888
13.1k
            }
1889
54.3k
        }
1890
68.9k
    }
1891
161k
  if (*p != '\0')
1892
18.5k
    return(flags);
1893
142k
  if (flags & XValue)
1894
40.5k
    *x=bounds.x;
1895
142k
  if (flags & YValue)
1896
38.3k
    *y=bounds.y;
1897
142k
  if (flags & WidthValue)
1898
125k
    *width=bounds.width;
1899
142k
  if (flags & HeightValue)
1900
123k
    *height=bounds.height;
1901
142k
  return(flags);
1902
161k
}
1903

1904
/*
1905
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1906
%                                                                             %
1907
%                                                                             %
1908
%                                                                             %
1909
+   G e t M a g i c k D i m e n s i o n                                       %
1910
%                                                                             %
1911
%                                                                             %
1912
%                                                                             %
1913
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1914
%
1915
%  GetMagickDimension() parses a string in the scanf form %lfx%lf+%lf+%lf
1916
%  to obtain WIDTHxHEIGHT+XOFF+YOFF values and returns the number of values
1917
%  successfully parsed. This function exists to overcome a new behavior of
1918
%  ANSI C'99 which supports hex parsing.
1919
%
1920
%  The format of the GetMagickDimension method is:
1921
%
1922
%      int GetMagickDimension(const char *str,double *width,double *height,
1923
%                             double *xoff,double *yoff)
1924
%
1925
%  A description of each parameter follows:
1926
%
1927
%    o str:    String to parse
1928
%
1929
%    o width:  First double value
1930
%
1931
%    o height: Second double value
1932
%
1933
%    o xoff:   Third double value (usually "x offset").  May be NULL.
1934
%
1935
%    o yoff:   Fourth double value (usually "y offset"). May be NULL.
1936
%
1937
*/
1938
static int MagickStrToD(const char *start,char **end,double *value)
1939
438k
{
1940
438k
  const char
1941
438k
    *p;
1942
1943
438k
  char
1944
438k
    buff[MaxTextExtent],
1945
438k
    *estr;
1946
1947
438k
  int
1948
438k
    i,
1949
438k
    n=0;
1950
1951
438k
  p=start;
1952
1953
8.54M
  for (i=0; (*p != 0) && (*p != 'x') && (*p != ',') && (i < MaxTextExtent-2); i++)
1954
8.10M
    buff[i]=*p++;
1955
438k
  buff[i]=0;
1956
438k
  errno=0;
1957
438k
  *value=strtod(buff,&estr);
1958
438k
  if (buff == estr)
1959
42.7k
    {
1960
42.7k
      *value=0.0;
1961
42.7k
    }
1962
395k
#if defined(INFINITY)
1963
395k
  else if ((*value == +INFINITY) || (*value == -INFINITY))
1964
7.07k
    {
1965
7.07k
      *value=0.0;
1966
7.07k
      errno=ERANGE;
1967
7.07k
    }
1968
388k
#endif
1969
388k
  else if (isnan(*value))
1970
791
    {
1971
791
      *value=0.0;
1972
791
      errno=ERANGE;
1973
791
    }
1974
  /*
1975
    Warning: Visual Studio 2008 64-bit returns errno 34 "Result too
1976
    large", even though a correct value is returned!
1977
  */
1978
387k
  else if (errno == 0)
1979
384k
    {
1980
384k
      n++;
1981
384k
    }
1982
438k
  *end=(char *) start+(estr-buff);
1983
1984
438k
  return (n);
1985
438k
}
1986
MagickExport int
1987
GetMagickDimension(const char *str,double *width,double *height,
1988
                   double *xoff,double *yoff)
1989
12.4k
{
1990
12.4k
  int
1991
12.4k
    n,
1992
12.4k
    parsed;
1993
1994
12.4k
  const char
1995
12.4k
    *start=str;
1996
1997
12.4k
  char
1998
12.4k
    *end;
1999
2000
12.4k
  n=MagickStrToD(start,&end,width);
2001
12.4k
  if (n == 0)
2002
4.57k
    return n;
2003
7.85k
  start=end;
2004
7.85k
  if (*start == '%')
2005
678
    start++;
2006
7.85k
  if ((*start != 'x') && (*start != 'X'))
2007
1.59k
    return n;
2008
6.25k
  start++;
2009
6.25k
  parsed = MagickStrToD(start,&end,height);
2010
6.25k
  if (parsed == 0)
2011
4.06k
    return n;
2012
2.19k
  n += parsed;
2013
2.19k
  start=end;
2014
2.19k
  if (xoff != (double *) NULL)
2015
0
    {
2016
0
      if ((*start != '+') && (*start != '-'))
2017
0
        return n;
2018
0
      parsed = MagickStrToD(start,&end,xoff);
2019
0
      if (parsed == 0)
2020
0
        return n;
2021
0
      n += parsed;
2022
0
      if (*(start -1) == '-')
2023
0
        *xoff=-*xoff;
2024
0
      start=end;
2025
0
    }
2026
2.19k
  if (yoff != (double *) NULL)
2027
0
    {
2028
0
      if ((*start != '+') && (*start != '-'))
2029
0
        return n;
2030
0
      parsed = MagickStrToD(start,&end,yoff);
2031
0
      if (parsed == 0)
2032
0
        return n;
2033
0
      n += parsed;
2034
0
      if (*(start -1) == '-')
2035
0
        *yoff=-*yoff;
2036
0
      start=end;
2037
0
    }
2038
2039
2.19k
  return (n);
2040
2.19k
}
2041

2042
/*
2043
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2044
%                                                                             %
2045
%                                                                             %
2046
%                                                                             %
2047
+   G e t M a g i c k G e o m e t r y                                         %
2048
%                                                                             %
2049
%                                                                             %
2050
%                                                                             %
2051
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2052
%
2053
%  GetMagickGeometry() is similar to GetGeometry() except that existing
2054
%  'width', and 'height' input values are modified by the geometry
2055
%  influenced by the meta characters:  %, @, !, <, and >, as well as
2056
%  +x, and +y offsets.  The geometry string has the form:
2057
%
2058
%      <width>x<height>{+-}<x>{+-}<y>{%}{@} {!}{<}{>}
2059
%
2060
%  For example, the string "640x480>" is a valid geometry string.
2061
%
2062
%  The interpretation of the extra geometry string parameters are as
2063
%  follows:
2064
%    %: (PercentValue) The geometry width and height parameters are
2065
%       interpreted as a percentage of the supplied width and height
2066
%       parameters.
2067
%    @: (AreaValue) The geometry parameter represents the desired total
2068
%       area (e.g. "307520@") or an area equivalent to a specified
2069
%       width x height (e.g. "640x480@"), of the final image.
2070
%    !: (AspectValue) Force the width and height values to be absolute
2071
%       values.  The original image aspect ratio is not maintained.
2072
%    <: (LessValue) Update the provided width and height parameters if
2073
%       its dimensions are less than the geometry specification.
2074
%    >: (GreaterValue) Update the provided width and height parameters
2075
%       if its dimensions are greater than the geometry specification.
2076
%    ^: (MinimumValue) Width and height are increased as required to
2077
%       preserve aspect ratio while ensuring that width and height are
2078
%       no less than specified.
2079
%
2080
%  Any supplied offset parameters are used to adjust the image width,
2081
%  height, and x/y offset values as required to center the scaled image
2082
%  into the region specified by the supplied width and height.
2083
%
2084
%  If only the width is specified, the width assumes the value and the
2085
%  height is chosen to maintain the aspect ratio of the image. Similarly,
2086
%  if only the height is specified (e.g., -geometry x256), the width is
2087
%  chosen to maintain the aspect ratio.
2088
%
2089
%  The format of the GetMagickGeometry method is:
2090
%
2091
%      int GetMagickGeometry(const char *geometry,long *x,long *y,
2092
%        unsigned long *width,unsigned long *height)
2093
%
2094
%  A description of each parameter follows:
2095
%
2096
%    o flags:  Method GetMagickGeometry returns a bitmask that indicates
2097
%      which of the twelve values (XValue, YValue, WidthValue, HeightValue,
2098
%      XNegative, YNegative, PercentValue, AspectValue, LessValue,
2099
%      GreaterValue, AreaValue, MinimumValue) were located in the geometry
2100
%      string.
2101
%
2102
%    o image_geometry:  Specifies a character string representing the geometry
2103
%      specification.
2104
%
2105
%    o x,y:  A pointer to an integer.  The x and y offset as determined by
2106
%      the geometry specification is returned here.
2107
%
2108
%    o width,height:  A pointer to an unsigned integer.  The width and height
2109
%      as determined by the geometry specification is returned here.
2110
%
2111
%
2112
*/
2113
MagickExport int GetMagickGeometry(const char *geometry,long *x,long *y,
2114
                                   unsigned long *width,unsigned long *height)
2115
33.7k
{
2116
33.7k
  int
2117
33.7k
    flags;
2118
2119
33.7k
  long
2120
33.7k
    count;
2121
2122
33.7k
  unsigned long
2123
33.7k
    former_height,
2124
33.7k
    former_width;
2125
2126
  /*
2127
    Ensure the image geometry is valid.
2128
  */
2129
33.7k
  assert(x != (long *) NULL);
2130
33.7k
  assert(y != (long *) NULL);
2131
33.7k
  assert(width != (unsigned long *) NULL);
2132
33.7k
  assert(height != (unsigned long *) NULL);
2133
33.7k
  if ((geometry == (char *) NULL) || (*geometry == '\0'))
2134
0
    return(NoValue);
2135
  /*
2136
    Parse geometry using GetGeometry.
2137
  */
2138
33.7k
  former_width=(*width);
2139
33.7k
  former_height=(*height);
2140
33.7k
  flags=GetGeometry(geometry,x,y,width,height);
2141
2142
33.7k
  if ((former_width == 0UL) || (former_height == 0UL))
2143
0
    return(flags);
2144
2145
#if 0
2146
  fprintf(stderr,"WidthValue=%u, HeightValue=%u width=%lu, height=%lu\n",
2147
          flags & WidthValue ? 1 : 0,
2148
          flags & HeightValue ? 1 : 0,
2149
          *width,*height);
2150
#endif
2151
2152
33.7k
  if (flags & AreaValue) /* @  */
2153
0
    {
2154
0
      double
2155
0
        scale_factor,
2156
0
        original_area,
2157
0
        target_area;
2158
2159
0
      MagickBool
2160
0
        resize;
2161
2162
      /*
2163
        Geometry is an area in pixels.
2164
      */
2165
0
      target_area=0.0;
2166
0
      if (flags & WidthValue)
2167
0
        target_area=(double) (*width);
2168
0
      if (flags & HeightValue)
2169
0
        target_area *= (double) (*height);
2170
2171
0
      if (target_area > 0.25)
2172
0
        {
2173
0
          original_area=(double) former_width*former_height;
2174
0
          resize=MagickFalse;
2175
0
          if (flags & GreaterValue)
2176
0
            {
2177
              /* Resize if image area greater than target */
2178
0
              if (original_area > target_area)
2179
0
                resize=MagickTrue;
2180
0
            }
2181
0
          else if (flags & LessValue)
2182
0
            {
2183
              /* Resize if image area less than target */
2184
0
              if (original_area < target_area)
2185
0
                resize=MagickTrue;
2186
0
            }
2187
0
          else
2188
0
            {
2189
              /* Always resize */
2190
0
              resize=MagickTrue;
2191
0
            }
2192
2193
0
          if (resize)
2194
0
            {
2195
0
              scale_factor=1.0/sqrt(original_area/target_area);
2196
0
              *width=(unsigned long) floor(former_width*scale_factor+0.25);
2197
0
              *height=(unsigned long) floor(former_height*scale_factor+0.25);
2198
0
            }
2199
0
          else
2200
0
            {
2201
0
              *width=former_width;
2202
0
              *height=former_height;
2203
0
            }
2204
0
        }
2205
0
    }
2206
33.7k
  else
2207
33.7k
    {
2208
      /*
2209
        Deal with width or height being missing from geometry.  Supply
2210
        missing value required to preserve current image aspect ratio.
2211
      */
2212
33.7k
      if (((flags & WidthValue) && !(flags & HeightValue)))
2213
3.95k
        *height=(unsigned long) floor(((double) former_height/former_width)*
2214
3.95k
                                      (*width)+0.5);
2215
29.7k
      else if ((!(flags & WidthValue) &&  (flags & HeightValue)))
2216
0
        *width=(unsigned long) floor(((double) former_width/former_height)*
2217
0
                                     (*height)+0.5);
2218
#if 0
2219
      fprintf(stderr,"Geometry Bounds: %lux%lu\n",*width,*height);
2220
#endif
2221
33.7k
      if (flags & PercentValue)
2222
0
        {
2223
0
          double
2224
0
            x_scale,
2225
0
            y_scale;
2226
2227
          /*
2228
            Geometry is a percentage of the image size.
2229
          */
2230
0
          x_scale=(*width);
2231
0
          y_scale=(*height);
2232
0
          count=GetMagickDimension(geometry,&x_scale,&y_scale,NULL,NULL);
2233
0
          if (count == 1)
2234
0
            y_scale=x_scale;
2235
0
          *width=(unsigned long) floor((x_scale*former_width/100.0)+0.5);
2236
0
          *height=(unsigned long) floor((y_scale*former_height/100.0)+0.5);
2237
0
          former_width=(*width);
2238
0
          former_height=(*height);
2239
0
        }
2240
33.7k
      if (!(flags & AspectValue) && /* ! */
2241
12.1k
          ((*width != former_width) || (*height != former_height)))
2242
10.9k
        {
2243
10.9k
          double
2244
10.9k
            scale_factor;
2245
2246
          /*
2247
            Respect aspect ratio of the image but assure that it is no
2248
            larger than specified.
2249
          */
2250
10.9k
          if ((former_width == 0) || (former_height == 0))
2251
0
            {
2252
0
              scale_factor=1.0;
2253
0
            }
2254
10.9k
          else
2255
10.9k
            {
2256
10.9k
              double
2257
10.9k
                scale_height,
2258
10.9k
                scale_width;
2259
2260
10.9k
              scale_height=(double) *height/former_height;
2261
10.9k
              scale_width=(double) *width/former_width;
2262
2263
10.9k
              scale_factor=scale_width;
2264
10.9k
              if ((flags & MinimumValue) != 0)
2265
0
                {
2266
                  /* Width and height are minimum values */
2267
0
                  if (scale_width < scale_height)
2268
0
                    scale_factor=scale_height;
2269
0
                }
2270
10.9k
              else
2271
10.9k
                {
2272
                  /* Width and height are maximum values */
2273
10.9k
                  if (scale_width > scale_height)
2274
2.81k
                    scale_factor=scale_height;
2275
10.9k
                }
2276
10.9k
            }
2277
10.9k
          *width=(unsigned long) floor(scale_factor*former_width+0.5);
2278
10.9k
          *height=(unsigned long) floor(scale_factor*former_height+0.5);
2279
2280
          /* Width and height can not be zero! */
2281
10.9k
          *width=Max(*width,1);
2282
10.9k
          *height=Max(*height,1);
2283
10.9k
        }
2284
33.7k
      if (flags & GreaterValue) /* > */
2285
2.20k
        {
2286
2.20k
          if (former_width < *width)
2287
846
            *width=former_width;
2288
2.20k
          if (former_height < *height)
2289
829
            *height=former_height;
2290
2.20k
        }
2291
33.7k
      if (flags & LessValue) /* < */
2292
0
        {
2293
0
          if (former_width > *width)
2294
0
            *width=former_width;
2295
0
          if (former_height > *height)
2296
0
            *height=former_height;
2297
0
        }
2298
33.7k
    }
2299
2300
33.7k
  return(flags);
2301
33.7k
}
2302

2303
/*
2304
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2305
%                                                                             %
2306
%                                                                             %
2307
%                                                                             %
2308
%  G e t P a g e G e o m e t r y                                              %
2309
%                                                                             %
2310
%                                                                             %
2311
%                                                                             %
2312
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2313
%
2314
%  GetPageGeometry() returns a new geometry string, with any embedded page
2315
%  mneumonic in the original geometry string replaced with the equivalent
2316
%  size in picas. For example, the geometry string "A4+36+36" is translated
2317
%  to "595x842+36+36" in the returned value.
2318
%
2319
%  The format of the GetPageGeometry method is:
2320
%
2321
%      char *GetPageGeometry(const char *page_geometry)
2322
%
2323
%  A description of each parameter follows.
2324
%
2325
%   o  page_geometry:  The geometry string to translate.
2326
%
2327
%
2328
*/
2329
MagickExport char *GetPageGeometry(const char *page_geometry)
2330
58.5k
{
2331
58.5k
#undef PAGE_SIZE
2332
3.98M
#define PAGE_SIZE(name, geometry) { name, sizeof(name)-1, geometry }
2333
58.5k
  static const struct
2334
58.5k
  {
2335
58.5k
    char
2336
58.5k
    name[12];
2337
2338
58.5k
    unsigned char
2339
58.5k
    name_length;
2340
2341
58.5k
    char
2342
58.5k
    geometry[10];
2343
58.5k
  }
2344
58.5k
    PageSizes[] =
2345
58.5k
    {
2346
58.5k
      PAGE_SIZE("4x6",  "288x432"),
2347
58.5k
      PAGE_SIZE("5x7",  "360x504"),
2348
58.5k
      PAGE_SIZE("7x9",  "504x648"),
2349
58.5k
      PAGE_SIZE("8x10", "576x720"),
2350
58.5k
      PAGE_SIZE("9x11",  "648x792"),
2351
58.5k
      PAGE_SIZE("9x12",  "648x864"),
2352
58.5k
      PAGE_SIZE("10x13",  "720x936"),
2353
58.5k
      PAGE_SIZE("10x14",  "720x1008"),
2354
58.5k
      PAGE_SIZE("11x17",  "792x1224"),
2355
58.5k
      PAGE_SIZE("A0",  "2384x3370"),
2356
58.5k
      PAGE_SIZE("A1",  "1684x2384"),
2357
58.5k
      PAGE_SIZE("A10", "73x105"),
2358
58.5k
      PAGE_SIZE("A2",  "1191x1684"),
2359
58.5k
      PAGE_SIZE("A3",  "842x1191"),
2360
58.5k
      PAGE_SIZE("A4",  "595x842"),
2361
58.5k
      PAGE_SIZE("A4SMALL", "595x842"),
2362
58.5k
      PAGE_SIZE("A5",  "420x595"),
2363
58.5k
      PAGE_SIZE("A6",  "297x420"),
2364
58.5k
      PAGE_SIZE("A7",  "210x297"),
2365
58.5k
      PAGE_SIZE("A8",  "148x210"),
2366
58.5k
      PAGE_SIZE("A9",  "105x148"),
2367
58.5k
      PAGE_SIZE("ARCHA", "648x864"),
2368
58.5k
      PAGE_SIZE("ARCHB", "864x1296"),
2369
58.5k
      PAGE_SIZE("ARCHC", "1296x1728"),
2370
58.5k
      PAGE_SIZE("ARCHD", "1728x2592"),
2371
58.5k
      PAGE_SIZE("ARCHE", "2592x3456"),
2372
58.5k
      PAGE_SIZE("B0",  "2920x4127"),
2373
58.5k
      PAGE_SIZE("B1",  "2064x2920"),
2374
58.5k
      PAGE_SIZE("B10", "91x127"),
2375
58.5k
      PAGE_SIZE("B2",  "1460x2064"),
2376
58.5k
      PAGE_SIZE("B3",  "1032x1460"),
2377
58.5k
      PAGE_SIZE("B4",  "729x1032"),
2378
58.5k
      PAGE_SIZE("B5",  "516x729"),
2379
58.5k
      PAGE_SIZE("B6",  "363x516"),
2380
58.5k
      PAGE_SIZE("B7",  "258x363"),
2381
58.5k
      PAGE_SIZE("B8",  "181x258"),
2382
58.5k
      PAGE_SIZE("B9",  "127x181"),
2383
58.5k
      PAGE_SIZE("C0",  "2599x3676"),
2384
58.5k
      PAGE_SIZE("C1",  "1837x2599"),
2385
58.5k
      PAGE_SIZE("C2",  "1298x1837"),
2386
58.5k
      PAGE_SIZE("C3",  "918x1296"),
2387
58.5k
      PAGE_SIZE("C4",  "649x918"),
2388
58.5k
      PAGE_SIZE("C5",  "459x649"),
2389
58.5k
      PAGE_SIZE("C6",  "323x459"),
2390
58.5k
      PAGE_SIZE("C7",  "230x323"),
2391
58.5k
      PAGE_SIZE("EXECUTIVE", "540x720"),
2392
58.5k
      PAGE_SIZE("FLSA", "612x936"),
2393
58.5k
      PAGE_SIZE("FLSE", "612x936"),
2394
58.5k
      PAGE_SIZE("FOLIO",  "612x936"),
2395
58.5k
      PAGE_SIZE("HALFLETTER", "396x612"),
2396
58.5k
      PAGE_SIZE("ISOB0", "2835x4008"),
2397
58.5k
      PAGE_SIZE("ISOB1", "2004x2835"),
2398
58.5k
      PAGE_SIZE("ISOB10", "88x125"),
2399
58.5k
      PAGE_SIZE("ISOB2", "1417x2004"),
2400
58.5k
      PAGE_SIZE("ISOB3", "1001x1417"),
2401
58.5k
      PAGE_SIZE("ISOB4", "709x1001"),
2402
58.5k
      PAGE_SIZE("ISOB5", "499x709"),
2403
58.5k
      PAGE_SIZE("ISOB6", "354x499"),
2404
58.5k
      PAGE_SIZE("ISOB7", "249x354"),
2405
58.5k
      PAGE_SIZE("ISOB8", "176x249"),
2406
58.5k
      PAGE_SIZE("ISOB9", "125x176"),
2407
58.5k
      PAGE_SIZE("LEDGER",  "1224x792"),
2408
58.5k
      PAGE_SIZE("LEGAL",  "612x1008"),
2409
58.5k
      PAGE_SIZE("LETTER", "612x792"),
2410
58.5k
      PAGE_SIZE("LETTERSMALL",  "612x792"),
2411
58.5k
      PAGE_SIZE("QUARTO",  "610x780"),
2412
58.5k
      PAGE_SIZE("STATEMENT",  "396x612"),
2413
58.5k
      PAGE_SIZE("TABLOID",  "792x1224")
2414
58.5k
    };
2415
2416
58.5k
  char
2417
58.5k
    page[MaxTextExtent];
2418
2419
58.5k
  register size_t
2420
58.5k
    i;
2421
2422
58.5k
  assert(page_geometry != (char *) NULL);
2423
58.5k
  strlcpy(page,page_geometry,MaxTextExtent);
2424
3.27M
  for (i=0; i < ArraySize(PageSizes); i++)
2425
3.23M
    if (LocaleNCompare(PageSizes[i].name,page_geometry,
2426
3.23M
                       PageSizes[i].name_length) == 0)
2427
15.1k
      {
2428
15.1k
        int
2429
15.1k
          flags;
2430
2431
15.1k
        RectangleInfo
2432
15.1k
          geometry;
2433
2434
        /*
2435
          Replace mneumonic with the equivalent size in dots-per-inch.
2436
        */
2437
15.1k
        MagickFormatString(page,sizeof(page),"%s%.80s", PageSizes[i].geometry,
2438
15.1k
                           page_geometry+PageSizes[i].name_length);
2439
15.1k
        flags=GetGeometry(page,&geometry.x,&geometry.y,&geometry.width,
2440
15.1k
                          &geometry.height);
2441
15.1k
        if (!(flags & GreaterValue))
2442
14.5k
          (void) strlcat(page,">",sizeof(page));
2443
15.1k
        break;
2444
15.1k
      }
2445
58.5k
  return (AcquireString(page));
2446
58.5k
}
2447

2448
/*
2449
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2450
%                                                                             %
2451
%                                                                             %
2452
%                                                                             %
2453
%   G e t P a t h C o m p o n e n t                                           %
2454
%                                                                             %
2455
%                                                                             %
2456
%                                                                             %
2457
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2458
%
2459
%  Method GetPathComponent returns the parent directory name, filename,
2460
%  basename, or extension of a file path.  File paths are in the form:
2461
%
2462
%     magick:base.ext[subimage]
2463
%
2464
%  Similar to
2465
%
2466
%      jpg:bar
2467
%      jpg:foo.bar
2468
%      pdf:foo.pdf[2-3]
2469
%      foo.pdf[2-3]
2470
%      C:\path\foo.bar
2471
%      /path/foo.bar
2472
%      pdf:C:\path\foo.pdf[2-3]
2473
%
2474
%  Note that Windows drive letters may be part of paths on Windows systems
2475
%  and such paths include a colon.  Path components in real file paths may
2476
%  include a colon and the file might not exist yet (or ever) so testing
2477
%  for it is not reliable.  This means that determination of the "magick"
2478
%  part is ambiguous and not reliable.
2479
%
2480
%  The format of the GetPathComponent function is:
2481
%
2482
%      GetPathComponent(const char *path,PathType type,char *component)
2483
%
2484
%  A description of each parameter follows:
2485
%
2486
%    o path: Specifies a pointer to a character array that contains the
2487
%      file path.
2488
%
2489
%    o type: Specififies which file path component to return (RootPath,
2490
%              HeadPath, TailPath, BasePath, ExtensionPath, MagickPath,
2491
%              SubImagePath, or FullPath).
2492
%
2493
%    o component: The selected file path component is returned here.
2494
%
2495
*/
2496
static inline unsigned int IsFrame(const char *point)
2497
0
{
2498
0
  char
2499
0
    *p;
2500
2501
0
  long
2502
0
    long_val;
2503
2504
0
  long_val = strtol(point,&p,10);
2505
0
  (void) long_val;
2506
0
  return(p != point);
2507
0
}
2508
2509
MagickExport void GetPathComponent(const char *path,PathType type,
2510
  char *component)
2511
67.1k
{
2512
67.1k
  register char
2513
67.1k
    *p;
2514
2515
67.1k
  char
2516
67.1k
    magick[MaxTextExtent],
2517
67.1k
    subimage[MaxTextExtent];
2518
2519
  /*
2520
    Get basename of client.
2521
  */
2522
67.1k
  assert(path != (const char *) NULL);
2523
67.1k
  assert(component != (const char *) NULL);
2524
67.1k
  if (strlcpy(component,path,MaxTextExtent) >= MaxTextExtent)
2525
0
    MagickFatalError2(ResourceLimitFatalError,"Path buffer overflow",
2526
67.1k
                      path);
2527
67.1k
  if (*path == '\0')
2528
2.23k
    return;
2529
64.9k
  subimage[0]=magick[0]='\0';
2530
2531
  /*
2532
    Remove magic and subimage spec. from the path to make
2533
    it easier to extract filename parts.
2534
  */
2535
932k
  for (p=component; (*p != '\0') && (*p != ':'); p++)
2536
867k
    ;
2537
64.9k
  if (*p == ':')
2538
0
    {
2539
0
      (void) strncpy(magick,component,(size_t)(p-component)+1);
2540
0
      magick[p-component+1]='\0';
2541
0
      if (IsMagickConflict(magick))
2542
0
        {
2543
0
          magick[0]='\0';
2544
0
        }
2545
0
      else
2546
0
        {
2547
0
          register char
2548
0
            *q;
2549
2550
          /*
2551
            Safe-copy the remaining component part on top of the magic part.
2552
          */
2553
0
          magick[p-component]='\0';
2554
0
          p++;
2555
0
          q=component;
2556
0
          while ((*q++=*p++))
2557
0
            ;
2558
0
        }
2559
0
    }
2560
2561
64.9k
  p=component+strlen(component);
2562
64.9k
  if ((p > component) && (*--p == ']'))
2563
0
    {
2564
      /* Look for a '[' matching the ']' */
2565
0
      p--;
2566
0
      while ((p > component) &&
2567
0
             (*p != '[') &&
2568
0
             (strchr("0123456789xX,-+ ", (int)(unsigned char)*p) != 0) )
2569
0
        p--;
2570
2571
      /* Copy to subimage and remove from component */
2572
0
      if ((p > component) && (*p == '[') && IsFrame(p+1))
2573
0
        {
2574
0
          (void) strlcpy(subimage, p,sizeof(subimage));
2575
0
          *p='\0';
2576
0
        }
2577
0
    }
2578
2579
  /* first locate the spot were the filename begins */
2580
655k
  for (p=component+strlen(component); p > component; p--)
2581
655k
    if (IsBasenameSeparator(*p)) /* Is directory delimiter like '/' or '\\' */
2582
64.6k
      break;
2583
2584
64.9k
  switch (type)
2585
64.9k
  {
2586
0
    case MagickPath:
2587
0
    {
2588
      /* this only includes the magick override prefix (if any) */
2589
0
      (void) strlcpy(component,magick,MaxTextExtent);
2590
0
      break;
2591
0
    }
2592
0
    case SubImagePath:
2593
0
    {
2594
      /* this returns only the subimage specification, including
2595
         bracketing '[]', (if any) */
2596
0
      (void) strlcpy(component,subimage,MaxTextExtent);
2597
0
      break;
2598
0
    }
2599
0
    case FullPath:
2600
0
    {
2601
      /* this returns the full path except magic and sub-image spec. */
2602
0
      break;
2603
0
    }
2604
64.1k
    case RootPath:
2605
64.1k
    {
2606
      /* this returns the path including the file part with no extension */
2607
898k
      for (p=component+strlen(component); p > component; p--)
2608
834k
        if (*p == '.')
2609
0
          break;
2610
64.1k
      if (*p == '.')
2611
0
        *p='\0';
2612
64.1k
      break;
2613
0
    }
2614
252
    case HeadPath:
2615
252
    {
2616
      /* this returns the path only with no trailing separator */
2617
252
      *p='\0';
2618
252
      break;
2619
0
    }
2620
252
    case TailPath:
2621
252
    {
2622
      /* this returns the filename and extension only */
2623
252
      if (IsBasenameSeparator(*p))
2624
252
        {
2625
252
          char
2626
252
            scratch[MaxTextExtent];
2627
2628
252
          (void) strlcpy(scratch,p+1,MaxTextExtent);
2629
252
          (void) strlcpy(component,scratch,MaxTextExtent);
2630
252
        }
2631
252
      break;
2632
0
    }
2633
252
    case BasePath:
2634
252
    {
2635
      /* this returns just the filename with no extension */
2636
252
      if (IsBasenameSeparator(*p))
2637
0
        {
2638
0
          char
2639
0
            scratch[MaxTextExtent];
2640
2641
0
          (void) strlcpy(scratch,p+1,MaxTextExtent);
2642
0
          (void) strlcpy(component,scratch,MaxTextExtent);
2643
0
        }
2644
4.44k
      for (p=component+strlen(component); p > component; p--)
2645
4.19k
        if (*p == '.')
2646
0
          {
2647
0
            *p='\0';
2648
0
            break;
2649
0
          }
2650
252
      break;
2651
0
    }
2652
0
    case ExtensionPath:
2653
0
    {
2654
      /* this returns the file extension only */
2655
0
      if (IsBasenameSeparator(*p))
2656
0
        {
2657
0
          char
2658
0
            scratch[MaxTextExtent];
2659
2660
0
          (void) strlcpy(scratch,p+1,MaxTextExtent);
2661
0
          (void) strlcpy(component,scratch,MaxTextExtent);
2662
0
        }
2663
0
      for (p=component+strlen(component); p > component; p--)
2664
0
        if (*p == '.')
2665
0
          break;
2666
0
      *component='\0';
2667
0
      if (*p == '.')
2668
0
        {
2669
0
          char
2670
0
            scratch[MaxTextExtent];
2671
2672
0
          (void) strlcpy(scratch,p+1,MaxTextExtent);
2673
0
          (void) strlcpy(component,scratch,MaxTextExtent);
2674
0
        }
2675
0
      break;
2676
0
    }
2677
64.9k
  }
2678
64.9k
}
2679

2680
/*
2681
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2682
%                                                                             %
2683
%                                                                             %
2684
%                                                                             %
2685
+   G e t T o k e n                                                           %
2686
%                                                                             %
2687
%                                                                             %
2688
%                                                                             %
2689
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2690
%
2691
%  Method GetToken gets a token from the token stream.  A token is defined
2692
%  as sequence of characters delimited by whitespace (e.g. clip-path), a
2693
%  sequence delimited with quotes (.e.g "Quote me"), or a sequence enclosed
2694
%  in parenthesis (e.g. rgb(0,0,0)).  The output to token is constrained to
2695
%  not overflow a buffer of size MaxTextExtent so it should be allocated with
2696
%  that size.
2697
%
2698
%  The format of the GetToken method is:
2699
%
2700
%      void GetToken(const char *start,char **end,char *token)
2701
%
2702
%  A description of each parameter follows:
2703
%
2704
%    o start: the start of the token sequence.
2705
%
2706
%    o end: point to the end of the token sequence (may be NULL).
2707
%
2708
%    o token: copy the token to this buffer.
2709
%
2710
%
2711
*/
2712
MagickExport void GetToken(const char *start,char **end,char *token)
2713
0
{
2714
0
  (void) MagickGetToken(start,end,token, MaxTextExtent);
2715
0
}
2716

2717
/*
2718
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2719
%                                                                             %
2720
%                                                                             %
2721
%                                                                             %
2722
%   G l o b E x p r e s s i o n                                               %
2723
%                                                                             %
2724
%                                                                             %
2725
%                                                                             %
2726
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2727
%
2728
%  Method GlobExpression returns True if the expression matches the pattern.
2729
%  The pattern specification syntax is roughly similar to that supported by
2730
%  POSIX.2 glob().
2731
%
2732
%  Please note that there is a conflict between glob patterns and subimage
2733
%  specifications.  For example, video.mpg[50] or video.mpg[50-75] might
2734
%  refer to video.mpg (page 51, or pages 51-76) or there might be a file
2735
%  named 'video.mpg[50]'.  The IsSubimage() function is used to quickly test
2736
%  if the specification may be a subimage specification.  If the pattern is
2737
%  ultimately determined to be a subimage specification, then globbing is
2738
%  not performed.
2739
%
2740
%
2741
%  The format of the GlobExpression function is:
2742
%
2743
%      int GlobExpression(const char *expression,const char *pattern)
2744
%
2745
%  A description of each parameter follows:
2746
%
2747
%    o expression: Specifies a pointer to a text string containing a file name.
2748
%
2749
%    o pattern: Specifies a pointer to a text string containing a pattern.
2750
%            Patterns supported are roughly equivalent to those supported by
2751
%            POSIX.2 glob().
2752
%
2753
%
2754
*/
2755
MagickExport int GlobExpression(const char *expression,const char *pattern)
2756
0
{
2757
0
  unsigned int
2758
0
    done;
2759
2760
  /*
2761
    Return on empty pattern or '*'.
2762
  */
2763
0
  if (pattern == (char *) NULL)
2764
0
    return(True);
2765
0
  if (strlen(pattern) == 0)
2766
0
    return(True);
2767
0
  if (LocaleCompare(pattern,"*") == 0)
2768
0
    return(True);
2769
  /*
2770
    Evaluate glob expression.
2771
  */
2772
0
  done=False;
2773
0
  while ((*pattern != '\0') && !done)
2774
0
  {
2775
0
    if (*expression == '\0')
2776
0
      if ((*pattern != '{') && (*pattern != '*'))
2777
0
        break;
2778
0
    switch (*pattern)
2779
0
    {
2780
0
      case '\\':
2781
0
      {
2782
0
        pattern++;
2783
0
        if (*pattern != '\0')
2784
0
          pattern++;
2785
0
        break;
2786
0
      }
2787
0
      case '*':
2788
0
      {
2789
0
        int
2790
0
          status;
2791
2792
0
        pattern++;
2793
0
        status=False;
2794
0
        while ((*expression != '\0') && !status)
2795
0
          status=GlobExpression((char *) expression++,pattern);
2796
0
        if (status)
2797
0
          {
2798
0
            while (*expression != '\0')
2799
0
              expression++;
2800
0
            while (*pattern != '\0')
2801
0
              pattern++;
2802
0
          }
2803
0
        break;
2804
0
      }
2805
0
      case '[':
2806
0
      {
2807
0
        char
2808
0
          c;
2809
2810
0
        pattern++;
2811
0
        for ( ; ; )
2812
0
        {
2813
0
          if ((*pattern == '\0') || (*pattern == ']'))
2814
0
            {
2815
0
              done=True;
2816
0
              break;
2817
0
            }
2818
0
          if (*pattern == '\\')
2819
0
            {
2820
0
              pattern++;
2821
0
              if (*pattern == '\0')
2822
0
                {
2823
0
                  done=True;
2824
0
                  break;
2825
0
                }
2826
0
             }
2827
0
          if (*(pattern+1) == '-')
2828
0
            {
2829
0
              c=(*pattern);
2830
0
              pattern+=2;
2831
0
              if (*pattern == ']')
2832
0
                {
2833
0
                  done=True;
2834
0
                  break;
2835
0
                }
2836
0
              if (*pattern == '\\')
2837
0
                {
2838
0
                  pattern++;
2839
0
                  if (*pattern == '\0')
2840
0
                    {
2841
0
                      done=True;
2842
0
                      break;
2843
0
                    }
2844
0
                }
2845
0
              if ((*expression < c) || (*expression > *pattern))
2846
0
                {
2847
0
                  pattern++;
2848
0
                  continue;
2849
0
                }
2850
0
            }
2851
0
          else
2852
0
            if (*pattern != *expression)
2853
0
              {
2854
0
                pattern++;
2855
0
                continue;
2856
0
              }
2857
0
          pattern++;
2858
0
          while ((*pattern != ']') && (*pattern != '\0'))
2859
0
          {
2860
0
            if ((*pattern == '\\') && (*(pattern+1) != '\0'))
2861
0
              pattern++;
2862
0
            pattern++;
2863
0
          }
2864
0
          if (*pattern != '\0')
2865
0
            {
2866
0
              pattern++;
2867
0
              expression++;
2868
0
            }
2869
0
          break;
2870
0
        }
2871
0
        break;
2872
0
      }
2873
0
      case '?':
2874
0
      {
2875
0
        pattern++;
2876
0
        expression++;
2877
0
        break;
2878
0
      }
2879
0
      case '{':
2880
0
      {
2881
0
        int
2882
0
          match;
2883
2884
0
        register const char
2885
0
          *p;
2886
2887
0
        pattern++;
2888
0
        while ((*pattern != '}') && (*pattern != '\0'))
2889
0
        {
2890
0
          p=expression;
2891
0
          match=True;
2892
0
          while ((*p != '\0') && (*pattern != '\0') &&
2893
0
                 (*pattern != ',') && (*pattern != '}') && match)
2894
0
          {
2895
0
            if (*pattern == '\\')
2896
0
              pattern++;
2897
0
            match=(*pattern == *p);
2898
0
            p++;
2899
0
            pattern++;
2900
0
          }
2901
0
          if (*pattern == '\0')
2902
0
            {
2903
0
              match=False;
2904
0
              done=True;
2905
0
              break;
2906
0
            }
2907
0
          else
2908
0
            if (match)
2909
0
              {
2910
0
                expression=p;
2911
0
                while ((*pattern != '}') && (*pattern != '\0'))
2912
0
                {
2913
0
                  pattern++;
2914
0
                  if (*pattern == '\\')
2915
0
                    {
2916
0
                      pattern++;
2917
0
                      if (*pattern == '}')
2918
0
                        pattern++;
2919
0
                    }
2920
0
                }
2921
0
              }
2922
0
            else
2923
0
              {
2924
0
                while ((*pattern != '}') && (*pattern != ',') &&
2925
0
                       (*pattern != '\0'))
2926
0
                {
2927
0
                  pattern++;
2928
0
                  if (*pattern == '\\')
2929
0
                    {
2930
0
                      pattern++;
2931
0
                      if ((*pattern == '}') || (*pattern == ','))
2932
0
                        pattern++;
2933
0
                    }
2934
0
                }
2935
0
              }
2936
0
          if (*pattern != '\0')
2937
0
            pattern++;
2938
0
        }
2939
0
        break;
2940
0
      }
2941
0
      default:
2942
0
      {
2943
0
        if (*expression != *pattern)
2944
0
          done=True;
2945
0
        else
2946
0
          {
2947
0
            expression++;
2948
0
            pattern++;
2949
0
          }
2950
0
      }
2951
0
    }
2952
0
  }
2953
0
  while ((*pattern != '\0') && (*pattern == '*'))
2954
0
    pattern++;
2955
0
  return((*expression == '\0') && (*pattern == '\0'));
2956
0
}
2957

2958
/*
2959
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2960
%                                                                             %
2961
%                                                                             %
2962
%                                                                             %
2963
%  I s A c c e s s i b l e                                                    %
2964
%                                                                             %
2965
%                                                                             %
2966
%                                                                             %
2967
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2968
%
2969
%  IsAccessible() returns MagickTrue if the file as defined by path exists
2970
%  and is readable by the user.
2971
%
2972
%  The format of the IsAccessible method is:
2973
%
2974
%      MagickBool IsAccessible(const char *path)
2975
%
2976
%  A description of each parameter follows.
2977
%
2978
%    o status:  Method IsAccessible returns MagickTrue if the file as defined by
2979
%      path exists and is readable by the user, otherwise MagickFalse is returned.
2980
%
2981
%    o path:  A pointer to an array of characters containing the path.
2982
%
2983
%
2984
*/
2985
MagickExport MagickBool IsAccessible(const char *path)
2986
19.9k
{
2987
19.9k
  if ((path == (const char *) NULL) || (*path == '\0'))
2988
3.01k
    return(MagickFalse);
2989
2990
16.9k
  if ((access(path,R_OK)) != 0)
2991
10.7k
    {
2992
10.7k
      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
2993
10.7k
        "Tried: %.1024s [%.1024s]",path,strerror(errno));
2994
10.7k
      return(MagickFalse);
2995
10.7k
    }
2996
6.24k
  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
2997
6.24k
                        "Found: %.1024s",path);
2998
6.24k
  return (MagickTrue);
2999
16.9k
}
3000

3001
/*
3002
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3003
%                                                                             %
3004
%                                                                             %
3005
%                                                                             %
3006
%  I s A c c e s s i b l e N o L o g g i n g                                  %
3007
%                                                                             %
3008
%                                                                             %
3009
%                                                                             %
3010
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3011
%
3012
%  IsAccessibleNoLogging() returns MagickTrue if the file as defined by path
3013
%  exists and is accessible by the user. This version is used internally to
3014
%  avoid using the error logging of the normal version.
3015
%
3016
%  The format of the IsAccessibleNoLogging method is:
3017
%
3018
%      MagickBool IsAccessibleNoLogging(const char *path)
3019
%
3020
%  A description of each parameter follows.
3021
%
3022
%    o status:  Method IsAccessibleNoLogging returns MagickTrue if the file as
3023
%      defined by path exists and is a regular file, otherwise Magick False is
3024
%      returned.
3025
%
3026
%    o path:  A pointer to an array of characters containing the path.
3027
%
3028
%
3029
*/
3030
MagickExport MagickBool IsAccessibleNoLogging(const char *path)
3031
1.61M
{
3032
1.61M
  if ((path == (const char *) NULL) || (*path == '\0'))
3033
5
    return(MagickFalse);
3034
3035
1.61M
  if ((access(path,R_OK)) != 0)
3036
1.61M
    return(MagickFalse);
3037
298
  return (MagickTrue);
3038
1.61M
}
3039

3040
/*
3041
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3042
%                                                                             %
3043
%                                                                             %
3044
%                                                                             %
3045
%  I s A c c e s s i b l e A n d N o t E m p t y                              %
3046
%                                                                             %
3047
%                                                                             %
3048
%                                                                             %
3049
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3050
%
3051
%  IsAccessibleAndNotEmpty() returns MagickTrue if the file as defined by path
3052
%  exists, is a regular file, and contains at least one byte of data.
3053
%
3054
%  The format of the IsAccessibleAndNotEmpty method is:
3055
%
3056
%      MagickBool IsAccessibleAndNotEmpty(const char *path)
3057
%
3058
%  A description of each parameter follows.
3059
%
3060
%    o status:  Method IsAccessibleAndNotEmpty returns MagickTrue if the file as
3061
%      defined by path exists, is a regular file, and contains content,
3062
%      otherwise MagickFalse is returned.
3063
%
3064
%    o path:  A pointer to an array of characters containing the path.
3065
%
3066
%
3067
*/
3068
MagickExport MagickBool IsAccessibleAndNotEmpty(const char *path)
3069
5.79k
{
3070
5.79k
  int
3071
5.79k
    status;
3072
3073
5.79k
  MagickStatStruct_t
3074
5.79k
    file_info;
3075
3076
5.79k
  if ((path == (const char *) NULL) || (*path == '\0'))
3077
1
    return(MagickFalse);
3078
5.79k
  status=MagickStat(path,&file_info);
3079
3080
5.79k
  if ((status == 0) && S_ISREG(file_info.st_mode) && (file_info.st_size > 0))
3081
5.77k
    return (MagickTrue);
3082
3083
22
  return (MagickFalse);
3084
5.79k
}
3085

3086
/*
3087
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3088
%                                                                             %
3089
%                                                                             %
3090
%                                                                             %
3091
+  I s D i r e c t o r y                                                      %
3092
%                                                                             %
3093
%                                                                             %
3094
%                                                                             %
3095
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3096
%
3097
%  IsDirectory() returns -1 if the path does not exist, 0 if the
3098
%  path represents a file, and 1 if the path represents a directory.
3099
%
3100
%  The format of the IsDirectory method is:
3101
%
3102
%      int IsDirectory(const char *path)
3103
%
3104
%  A description of each parameter follows.
3105
%
3106
%   o  status:  Method IsDirectory returns -1 if the path does not exist,
3107
%      0 if the path represents a file, and 1 if the path represents
3108
%      a directory.
3109
%
3110
%   o  path:  Path to file or directory.
3111
%
3112
%
3113
*/
3114
static int IsDirectory(const char *path)
3115
0
{
3116
0
  MagickStatStruct_t
3117
0
    file_info;
3118
3119
0
  if ((path == (const char *) NULL) || (*path == '\0'))
3120
0
    return(False);
3121
3122
0
  if ((MagickStat(path,&file_info)) == 0)
3123
0
    {
3124
0
      if (S_ISREG(file_info.st_mode))
3125
0
        return 0;
3126
0
      if (S_ISDIR(file_info.st_mode))
3127
0
        return 1;
3128
0
    }
3129
0
  return -1;
3130
0
}
3131

3132
/*
3133
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3134
%                                                                             %
3135
%                                                                             %
3136
%                                                                             %
3137
+     I s G e o m e t r y                                                     %
3138
%                                                                             %
3139
%                                                                             %
3140
%                                                                             %
3141
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3142
%
3143
%  Method IsGeometry returns MagickTrue if the geometry specification is valid
3144
%  as determined by GetGeometry.
3145
%
3146
%  The format of the IsGeometry method is:
3147
%
3148
%      MagickBool IsGeometry(const char *geometry)
3149
%
3150
%  A description of each parameter follows:
3151
%
3152
%    o status: Method IsGeometry returns MagickTrue if the geometry specification
3153
%      is valid otherwise MagickFalse is returned.
3154
%
3155
%    o geometry: This string is the geometry specification.
3156
%
3157
%
3158
*/
3159
MagickExport MagickBool IsGeometry(const char *geometry)
3160
0
{
3161
0
  long
3162
0
    x,
3163
0
    y;
3164
3165
0
  unsigned int
3166
0
    flags;
3167
3168
0
  unsigned long
3169
0
    height,
3170
0
    width;
3171
3172
0
  if (geometry == (const char *) NULL)
3173
0
    return(False);
3174
0
  flags=GetGeometry(geometry,&x,&y,&width,&height);
3175
0
  return(flags != NoValue);
3176
0
}
3177

3178
/*
3179
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3180
%                                                                             %
3181
%                                                                             %
3182
+     I s G l o b                                                             %
3183
%                                                                             %
3184
%                                                                             %
3185
%                                                                             %
3186
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3187
%
3188
%  IsGlob() returns MagickTrue if the path specification contains a globbing
3189
%  pattern as supported by GlobExpression().  Glob patterns supported are
3190
%  roughly equivalent to those supported by POSIX.2 glob().
3191
%
3192
%  The format of the IsGlob method is:
3193
%
3194
%      MagickBool IsGlob(const char *path)
3195
%
3196
%  A description of each parameter follows:
3197
%
3198
%    o status: Returns MagickTrue if the path specification contains
3199
%      a globbing patten.
3200
%
3201
%    o path: The path.
3202
%
3203
%
3204
*/
3205
MagickExport MagickBool IsGlob(const char *path)
3206
24
{
3207
24
  register const char
3208
24
    *p;
3209
3210
24
  MagickBool
3211
24
    status = MagickFalse;
3212
3213
24
  for (p = path; *p != '\0'; p++)
3214
0
    {
3215
0
      switch (*p)
3216
0
        {
3217
0
        case '*':
3218
0
        case '?':
3219
0
        case '{':
3220
0
        case '}':
3221
0
        case '[':
3222
0
        case ']':
3223
0
          {
3224
0
            status = MagickTrue;
3225
0
            break;
3226
0
          }
3227
0
        }
3228
0
    }
3229
3230
24
  return status ;
3231
24
}
3232

3233
/*
3234
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3235
%                                                                             %
3236
%                                                                             %
3237
%                                                                             %
3238
%  I s W r i t a b l e                                                        %
3239
%                                                                             %
3240
%                                                                             %
3241
%                                                                             %
3242
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3243
%
3244
%  IsWritable() returns True if the file as defined by path exists
3245
%  and is writeable by the user.
3246
%
3247
%  The format of the IsWriteable method is:
3248
%
3249
%      MagickBool IsWriteable(const char *path)
3250
%
3251
%  A description of each parameter follows.
3252
%
3253
%    o status:  Method IsWriteable returns MagickTrue if the file as defined
3254
%      by path exists and is writeable by the user, otherwise MagickFalse is
3255
%      returned.
3256
%
3257
%    o path:  A pointer to an array of characters containing the path.
3258
%
3259
%
3260
*/
3261
MagickExport MagickBool IsWriteable(const char *path)
3262
0
{
3263
0
  if ((path == (const char *) NULL) || (*path == '\0'))
3264
0
    return(MagickFalse);
3265
3266
0
  if ((access(path,W_OK)) != 0)
3267
0
    {
3268
0
      return(MagickFalse);
3269
0
    }
3270
0
  return (MagickTrue);
3271
0
}
3272

3273
/*
3274
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3275
%                                                                             %
3276
%                                                                             %
3277
%                                                                             %
3278
%   L i s t F i l e s                                                         %
3279
%                                                                             %
3280
%                                                                             %
3281
%                                                                             %
3282
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3283
%
3284
%  Method ListFiles reads the directory specified and returns a list
3285
%  of filenames contained in the directory sorted in ascending alphabetic
3286
%  order.
3287
%
3288
%  The format of the ListFiles function is:
3289
%
3290
%      char **ListFiles(const char *directory,const char *pattern,
3291
%        long *number_entries)
3292
%
3293
%  A description of each parameter follows:
3294
%
3295
%    o filelist: Method ListFiles returns a list of filenames contained
3296
%      in the directory.  If the directory specified cannot be read or it is
3297
%      a file a NULL list is returned.
3298
%
3299
%    o directory: Specifies a pointer to a text string containing a directory
3300
%      name.
3301
%
3302
%    o pattern: Specifies a pointer to a text string containing a pattern.
3303
%
3304
%    o number_entries:  This integer returns the number of filenames in the
3305
%      list.
3306
%
3307
%
3308
*/
3309
3310
#if defined(__cplusplus) || defined(c_plusplus)
3311
extern "C" {
3312
#endif
3313
3314
static int FileCompare(const void *x,const void *y)
3315
0
{
3316
0
  register char
3317
0
    **p,
3318
0
    **q;
3319
3320
0
  p=(char **) x;
3321
0
  q=(char **) y;
3322
0
  return(LocaleCompare(*p,*q));
3323
0
}
3324
3325
#if defined(__cplusplus) || defined(c_plusplus)
3326
}
3327
#endif
3328
3329
MagickExport char **ListFiles(const char *directory,const char *pattern,
3330
  long *number_entries)
3331
0
{
3332
0
  char
3333
0
    **filelist,
3334
0
    filename[MaxTextExtent];
3335
3336
0
  DIR
3337
0
    *current_directory;
3338
3339
0
  int
3340
0
    status;
3341
3342
0
  struct dirent
3343
0
    *entry;
3344
3345
0
  unsigned int
3346
0
    max_entries;
3347
3348
  /*
3349
    Open directory.
3350
  */
3351
0
  assert(directory != (const char *) NULL);
3352
0
  assert(pattern != (char *) NULL);
3353
0
  assert(number_entries != (long *) NULL);
3354
0
  *number_entries=0;
3355
0
  status=chdir(directory);
3356
0
  if (status != 0)
3357
0
    return((char **) NULL);
3358
0
  if (getcwd(filename,MaxTextExtent-1) == NULL)
3359
0
    MagickFatalError(ConfigureFatalError,UnableToGetCurrentDirectory,
3360
0
                     NULL);
3361
0
  current_directory=opendir(filename);
3362
0
  if (current_directory == (DIR *) NULL)
3363
0
    return((char **) NULL);
3364
0
  if (chdir(filename) != 0)
3365
0
    {
3366
0
      (void) closedir(current_directory);
3367
0
      return((char **) NULL);
3368
0
    }
3369
  /*
3370
    Allocate filelist.
3371
  */
3372
0
  max_entries=2048U;
3373
0
  filelist=MagickAllocateArray(char **,max_entries,sizeof(char *));
3374
0
  if (filelist == (char **) NULL)
3375
0
    {
3376
0
      (void) closedir(current_directory);
3377
0
      return((char **) NULL);
3378
0
    }
3379
  /*
3380
    Save the current and change to the new directory.
3381
  */
3382
0
  entry=readdir(current_directory);
3383
0
  while (entry != (struct dirent *) NULL)
3384
0
  {
3385
0
    if (*entry->d_name == '.')
3386
0
      {
3387
0
        entry=readdir(current_directory);
3388
0
        continue;
3389
0
      }
3390
0
    if ((IsDirectory(entry->d_name) > 0) ||
3391
0
        GlobExpression(entry->d_name,pattern))
3392
0
      {
3393
0
        if (*number_entries >= (int) max_entries)
3394
0
          {
3395
            /*
3396
              Extend the file list.
3397
            */
3398
0
            max_entries<<=1;
3399
0
            MagickReallocMemory(char **,filelist,max_entries*sizeof(char *));
3400
0
            if (filelist == (char **) NULL)
3401
0
              {
3402
0
                (void) closedir(current_directory);
3403
                /*
3404
                  We simply bail here since our memory reallocator has
3405
                  just leaked lots of memory and returning does not
3406
                  solve the problem.
3407
                */
3408
0
                MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
3409
0
                                  UnableToAllocateString);
3410
0
              }
3411
0
          }
3412
0
        {
3413
0
          size_t
3414
0
            entry_length;
3415
3416
0
          entry_length=strlen(entry->d_name)+1;
3417
0
          if (IsDirectory(entry->d_name) > 0)
3418
0
            entry_length+=strlen(DirectorySeparator);
3419
3420
0
          filelist[*number_entries]=MagickAllocateMemory(char *,entry_length);
3421
0
          if (filelist[*number_entries] == (char *) NULL)
3422
0
            {
3423
0
              break;
3424
0
            }
3425
0
          (void) strlcpy(filelist[*number_entries],entry->d_name,entry_length);
3426
0
          if (IsDirectory(entry->d_name) > 0)
3427
0
            (void) strlcat(filelist[*number_entries],DirectorySeparator,entry_length);
3428
0
        }
3429
0
        (*number_entries)++;
3430
0
      }
3431
0
    entry=readdir(current_directory);
3432
0
  }
3433
0
  (void) closedir(current_directory);
3434
  /*
3435
    Sort filelist in ascending order.
3436
  */
3437
0
  qsort((void *) filelist,*number_entries,sizeof(filelist[0]),FileCompare);
3438
0
  return(filelist);
3439
0
}
3440

3441
/*
3442
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3443
%                                                                             %
3444
%                                                                             %
3445
%                                                                             %
3446
%   L o c a l e C o m p a r e                                                 %
3447
%                                                                             %
3448
%                                                                             %
3449
%                                                                             %
3450
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3451
%
3452
%  Method LocaleCompare performs a case-insensitive comparison of two strings
3453
%  byte-by-byte, according to the ordering of the current locale encoding.
3454
%  LocaleCompare returns an integer greater than, equal to, or less than 0,
3455
%  if the string pointed to by p is greater than, equal to, or less than the
3456
%  string pointed to by q respectively.  The sign of a non-zero return value
3457
%  is determined by the sign of the difference between the values of the first
3458
%  pair of bytes that differ in the strings being compared.
3459
%
3460
%  The format of the LocaleCompare method is:
3461
%
3462
%      int LocaleCompare(const char *p,const char *q)
3463
%
3464
%  A description of each parameter follows:
3465
%
3466
%    o p: A pointer to a character string.
3467
%
3468
%    o q: A pointer to a character string to compare to p.
3469
%
3470
%
3471
*/
3472
MagickExport int LocaleCompare(const char *p,const char *q)
3473
241M
{
3474
241M
  int
3475
241M
    result=0;
3476
3477
241M
  register size_t
3478
241M
    i;
3479
3480
241M
  if (p == (char *) NULL)
3481
112
    result=-1;
3482
241M
  else if (q == (char *) NULL)
3483
95.7k
    result=1;
3484
241M
  else
3485
365M
    for (i=0; ; i++)
3486
606M
      {
3487
606M
        if (((result=
3488
606M
              AsciiMap[(unsigned int) ((unsigned char *) p)[i] & 0xff] -
3489
606M
              AsciiMap[(unsigned int) ((unsigned char *) q)[i] & 0xff]) != 0)
3490
397M
            || (p[i] == 0) || (q[i] == 0))
3491
241M
          break;
3492
606M
      }
3493
241M
  return result;
3494
241M
}
3495

3496
/*
3497
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3498
%                                                                             %
3499
%                                                                             %
3500
%                                                                             %
3501
%   L o c a l e L o w e r                                                     %
3502
%                                                                             %
3503
%                                                                             %
3504
%                                                                             %
3505
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3506
%
3507
%  Method LocaleLower transforms all of the characters in the supplied
3508
%  null-terminated string, changing all uppercase letters to lowercase.
3509
%
3510
%  The format of the LocaleLower method is:
3511
%
3512
%      void LocaleLower(char *string)
3513
%
3514
%  A description of each parameter follows:
3515
%
3516
%    o string: A pointer to the string to convert to lower-case Locale.
3517
%
3518
%
3519
*/
3520
MagickExport void LocaleLower(char *string)
3521
6.74k
{
3522
6.74k
  register char
3523
6.74k
    *q;
3524
3525
6.74k
  assert(string != (char *) NULL);
3526
97.1k
  for (q=string; *q != '\0'; q++)
3527
90.4k
    *q=(char) tolower((int) *q);
3528
6.74k
}
3529

3530
/*
3531
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3532
%                                                                             %
3533
%                                                                             %
3534
%                                                                             %
3535
%   L o c a l e N C o m p a r e                                               %
3536
%                                                                             %
3537
%                                                                             %
3538
%                                                                             %
3539
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3540
%
3541
%  Method LocaleNCompare performs a case-insensitive comparison of two
3542
%  strings byte-by-byte, according to the ordering of the current locale
3543
%  encoding. LocaleNCompare returns an integer greater than, equal to, or
3544
%  less than 0, if the string pointed to by p is greater than, equal to, or
3545
%  less than the string pointed to by q respectively.  The sign of a non-zero
3546
%  return value is determined by the sign of the difference between the
3547
%  values of the first pair of bytes that differ in the strings being
3548
%  compared.  The LocaleNCompare method makes the same comparison as
3549
%  LocaleCompare but looks at a maximum of n bytes.  Bytes following a
3550
%  null byte are not compared.
3551
%
3552
%  The format of the LocaleNCompare method is:
3553
%
3554
%      int LocaleNCompare(const char *p,const char *q,const size_t n)
3555
%
3556
%  A description of each parameter follows:
3557
%
3558
%    o p: A pointer to a character string.
3559
%
3560
%    o q: A pointer to a character string to compare to p.
3561
%
3562
%    o length: The number of characters to compare in strings p & q.
3563
%
3564
%
3565
*/
3566
MagickExport int LocaleNCompare(const char *p,const char *q,const size_t length)
3567
690M
{
3568
690M
  int
3569
690M
    result=0;
3570
3571
690M
  register size_t
3572
690M
    i;
3573
3574
690M
  if (p == (char *) NULL)
3575
0
    result = -1;
3576
690M
  else if (q == (char *) NULL)
3577
0
    result = 1;
3578
690M
  else
3579
762M
    for (i=0; i < length; i++)
3580
761M
      {
3581
761M
        if (((result=
3582
761M
              AsciiMap[(unsigned int) ((unsigned char *) p)[i] & 0xff] -
3583
761M
              AsciiMap[(unsigned int) ((unsigned char *) q)[i] & 0xff]) != 0)
3584
76.5M
            || (p[i] == 0) || (q[i] == 0))
3585
688M
          break;
3586
761M
      }
3587
690M
  return result;
3588
690M
}
3589

3590
/*
3591
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3592
%                                                                             %
3593
%                                                                             %
3594
%                                                                             %
3595
%   L o c a l e U p p e r                                                     %
3596
%                                                                             %
3597
%                                                                             %
3598
%                                                                             %
3599
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3600
%
3601
%  Method LocaleUpper transforms all of the characters in the supplied
3602
%  null-terminated string, changing all lowercase letters to uppercase.
3603
%
3604
%  The format of the LocaleUpper method is:
3605
%
3606
%      void LocaleUpper(char *string)
3607
%
3608
%  A description of each parameter follows:
3609
%
3610
%    o string: A pointer to the string to convert to upper-case Locale.
3611
%
3612
%
3613
*/
3614
MagickExport void LocaleUpper(char *string)
3615
2.22M
{
3616
2.22M
  register char
3617
2.22M
    *q;
3618
3619
2.22M
  assert(string != (char *) NULL);
3620
10.6M
  for (q=string; *q != '\0'; q++)
3621
8.40M
    *q=(char) toupper((int) *q);
3622
2.22M
}
3623

3624
MagickExport MagickPassFail MagickAtoFChk(const char *str, double *value)
3625
3.76M
{
3626
3.76M
  MagickPassFail status = MagickPass;
3627
3.76M
  char *estr=0;
3628
3.76M
  *value=strtod(str,&estr);
3629
3.76M
  if (str == estr)
3630
6.73k
    {
3631
6.73k
      *value=0.0;
3632
6.73k
      status=MagickFail;
3633
6.73k
    }
3634
3.75M
#if defined(INFINITY)
3635
3.75M
  else if ((*value == +INFINITY) || (*value == -INFINITY))
3636
739
    {
3637
739
      *value=0.0;
3638
739
      status=MagickFail;
3639
739
      errno=ERANGE;
3640
739
    }
3641
3.75M
#endif
3642
3.75M
  else if (isnan(*value))
3643
208
    {
3644
208
      *value=0.0;
3645
208
      status=MagickFail;
3646
208
      errno=ERANGE;
3647
208
    }
3648
3.76M
  return status;
3649
3.76M
}
3650

3651
MagickExport MagickPassFail MagickAtoIChk(const char *str, int *value)
3652
0
{
3653
0
  MagickPassFail status = MagickPass;
3654
0
  char *estr=0;
3655
0
  long lvalue;
3656
0
  lvalue=strtol(str,&estr, 10);
3657
0
  if (str == estr)
3658
0
    {
3659
0
      lvalue=0;
3660
0
      status=MagickFail;
3661
0
      errno=EINVAL;
3662
0
    }
3663
0
  else if ((int) lvalue != lvalue)
3664
0
    {
3665
0
      lvalue=0;
3666
0
      status=MagickFail;
3667
0
      errno=ERANGE;
3668
0
    }
3669
0
  *value=(int) lvalue;
3670
0
  return status;
3671
0
}
3672

3673
MagickExport MagickPassFail MagickAtoUIChk(const char *str, unsigned int *value)
3674
110k
{
3675
110k
  MagickPassFail status = MagickPass;
3676
110k
  char *estr=0;
3677
110k
  long lvalue;
3678
110k
  lvalue=strtol(str,&estr, 10);
3679
110k
  if (str == estr)
3680
49
    {
3681
49
      lvalue=0U;
3682
49
      status=MagickFail;
3683
49
      errno=EINVAL;
3684
49
    }
3685
110k
  else if ((long) ((unsigned int) lvalue) != lvalue)
3686
149
    {
3687
149
      lvalue=0U;
3688
149
      status=MagickFail;
3689
149
      errno=ERANGE;
3690
149
    }
3691
110k
  *value=(unsigned int) lvalue;
3692
110k
  return status;
3693
110k
}
3694

3695
MagickExport MagickPassFail MagickAtoLChk(const char *str, long *value)
3696
0
{
3697
0
  char *estr=0;
3698
0
  *value=strtol(str,&estr, 10);
3699
0
  if (str == estr)
3700
0
    *value=0L;
3701
0
  return (str == estr ? MagickFail : MagickPass);
3702
0
}
3703

3704
MagickExport MagickPassFail MagickAtoULChk(const char *str, unsigned long *value)
3705
2.92k
{
3706
2.92k
  MagickPassFail status = MagickPass;
3707
2.92k
  char *estr=0;
3708
2.92k
  long lvalue;
3709
2.92k
  lvalue=strtol(str,&estr, 10);
3710
2.92k
  if (str == estr)
3711
25
    {
3712
25
      lvalue=0L;
3713
25
      status=MagickFail;
3714
25
      errno=EINVAL;
3715
25
    }
3716
2.89k
  else if ((long) ((unsigned long) lvalue) != lvalue)
3717
0
    {
3718
0
      lvalue=0L;
3719
0
      status=MagickFail;
3720
0
      errno=ERANGE;
3721
0
    }
3722
2.92k
  *value=(unsigned long) lvalue;
3723
2.92k
  return status;
3724
2.92k
}
3725

3726
/*
3727
  Access to the 'long long' type is assured by C'99
3728
*/
3729
MagickExport MagickPassFail MagickAtoULLChk(const char *str, unsigned long long *value)
3730
0
{
3731
0
  MagickPassFail status = MagickPass;
3732
0
  char *estr=0;
3733
0
  long long lvalue;
3734
0
  lvalue=strtoll(str,&estr, 10);
3735
0
  if (str == estr)
3736
0
    {
3737
0
      lvalue=0L;
3738
0
      status=MagickFail;
3739
0
      errno=EINVAL;
3740
0
    }
3741
0
  else if ((long long) ((unsigned long long) lvalue) != lvalue)
3742
0
    {
3743
0
      lvalue=0LL;
3744
0
      status=MagickFail;
3745
0
      errno=ERANGE;
3746
0
    }
3747
0
  *value=(unsigned long long) lvalue;
3748
0
  return status;
3749
0
}
3750

3751
/*
3752
  Convert a double to a long, with clipping.
3753
  Someday a warning or an error may be produced here.
3754
*/
3755
MagickExport long MagickDoubleToLong(const double dval/*, ExceptionInfo *exception*/)
3756
33.0M
{
3757
33.0M
  long lval;
3758
3759
33.0M
  do
3760
33.0M
    {
3761
33.0M
#if defined(INFINITY)
3762
33.0M
      if (dval == +INFINITY)
3763
0
        {
3764
0
          lval=LONG_MAX;
3765
0
          break;
3766
0
        }
3767
33.0M
      if (dval == -INFINITY)
3768
0
        {
3769
0
          lval=LONG_MIN;
3770
0
          break;
3771
0
        }
3772
33.0M
#endif
3773
33.0M
      if (isnan(dval))
3774
0
        {
3775
0
          lval=0;
3776
0
          break;
3777
0
        }
3778
33.0M
      if (floor(dval) > ((double) LONG_MAX - 1))
3779
0
        {
3780
0
          lval=LONG_MAX;
3781
0
          break;
3782
0
        }
3783
33.0M
      if (ceil(dval) < ((double) LONG_MIN + 1))
3784
0
        {
3785
0
          lval=LONG_MIN;
3786
0
          break;
3787
0
        }
3788
33.0M
      lval=(long) dval;
3789
33.0M
    } while (0);
3790
3791
33.0M
  return lval;
3792
33.0M
}
3793

3794
/*
3795
  Convert a double to an int, with clipping.
3796
  Someday a warning or an error may be produced here.
3797
*/
3798
MagickExport int MagickDoubleToInt(const double dval/*, ExceptionInfo *exception*/)
3799
0
{
3800
0
  int lval;
3801
3802
0
  do
3803
0
    {
3804
0
#if defined(INFINITY)
3805
0
      if (dval == +INFINITY)
3806
0
        {
3807
0
          lval=INT_MAX;
3808
0
          break;
3809
0
        }
3810
0
      if (dval == -INFINITY)
3811
0
        {
3812
0
          lval=INT_MIN;
3813
0
          break;
3814
0
        }
3815
0
#endif
3816
0
      if (isnan(dval))
3817
0
        {
3818
0
          lval=0;
3819
0
          break;
3820
0
        }
3821
0
      if (floor(dval) > ((double) INT_MAX - 1))
3822
0
        {
3823
0
          lval=INT_MAX;
3824
0
          break;
3825
0
        }
3826
0
      if (ceil(dval) < ((double) INT_MIN + 1))
3827
0
        {
3828
0
          lval=INT_MIN;
3829
0
          break;
3830
0
        }
3831
0
      lval=(int) dval;
3832
0
    } while (0);
3833
3834
0
  return lval;
3835
0
}
3836

3837
/*
3838
  Convert a double to an unsigned long, with clipping.
3839
  Someday a warning or an error may be produced here.
3840
*/
3841
MagickExport unsigned long MagickDoubleToULong(const double dval/*, ExceptionInfo *exception*/)
3842
0
{
3843
0
  unsigned long lval;
3844
3845
0
  do
3846
0
    {
3847
0
#if defined(INFINITY)
3848
0
      if (dval == +INFINITY)
3849
0
        {
3850
0
          lval=ULONG_MAX;
3851
0
          break;
3852
0
        }
3853
0
      if (dval == -INFINITY)
3854
0
        {
3855
0
          lval=0;
3856
0
          break;
3857
0
        }
3858
0
#endif
3859
0
      if (isnan(dval))
3860
0
        {
3861
0
          lval=0;
3862
0
          break;
3863
0
        }
3864
0
      if (floor(dval) > ((double) ULONG_MAX - 1))
3865
0
        {
3866
0
          lval=ULONG_MAX;
3867
0
          break;
3868
0
        }
3869
0
      if (ceil(dval) < 0.0)
3870
0
        {
3871
0
          lval=0;
3872
0
          break;
3873
0
        }
3874
0
      lval=(unsigned long) dval;
3875
0
    } while (0);
3876
3877
0
  return lval;
3878
0
}
3879

3880
/*
3881
  Convert a double to an unsigned int, with clipping.
3882
  Someday a warning or an error may be produced here.
3883
*/
3884
MagickExport unsigned int MagickDoubleToUInt(const double dval/*, ExceptionInfo *exception*/)
3885
150
{
3886
150
  unsigned int lval;
3887
3888
150
  do
3889
150
    {
3890
150
#if defined(INFINITY)
3891
150
      if (dval == +INFINITY)
3892
0
        {
3893
0
          lval=UINT_MAX;
3894
0
          break;
3895
0
        }
3896
150
      if (dval == -INFINITY)
3897
0
        {
3898
0
          lval=0;
3899
0
          break;
3900
0
        }
3901
150
#endif
3902
150
      if (isnan(dval))
3903
0
        {
3904
0
          lval=0;
3905
0
          break;
3906
0
        }
3907
150
      if (floor(dval) > ((double) UINT_MAX - 1))
3908
25
        {
3909
25
          lval=UINT_MAX;
3910
25
          break;
3911
25
        }
3912
125
      if (ceil(dval) < 0.0)
3913
0
        {
3914
0
          lval=0;
3915
0
          break;
3916
0
        }
3917
125
      lval=(unsigned int) dval;
3918
125
    } while (0);
3919
3920
150
  return lval;
3921
150
}
3922

3923
/*
3924
  Convert a double to a short, with clipping.
3925
  Someday a warning or an error may be produced here.
3926
*/
3927
MagickExport short int MagickDoubleToShort(const double dval/*, ExceptionInfo *exception*/)
3928
0
{
3929
0
  short int lval;
3930
3931
0
  do
3932
0
    {
3933
0
#if defined(INFINITY)
3934
0
      if (dval == +INFINITY)
3935
0
        {
3936
0
          lval=SHRT_MAX;
3937
0
          break;
3938
0
        }
3939
0
      if (dval == -INFINITY)
3940
0
        {
3941
0
          lval=SHRT_MIN;
3942
0
          break;
3943
0
        }
3944
0
#endif
3945
0
      if (isnan(dval))
3946
0
        {
3947
0
          lval=0;
3948
0
          break;
3949
0
        }
3950
0
      if (floor(dval) > ((double) SHRT_MAX - 1))
3951
0
        {
3952
0
          lval=SHRT_MAX;
3953
0
          break;
3954
0
        }
3955
0
      if (ceil(dval) < ((double) SHRT_MIN + 1))
3956
0
        {
3957
0
          lval=SHRT_MIN;
3958
0
          break;
3959
0
        }
3960
0
      lval=(short int) dval;
3961
0
    } while (0);
3962
3963
0
  return lval;
3964
0
}
3965

3966
/*
3967
  Convert a double to an unsigned short, with clipping.
3968
  Someday a warning or an error may be produced here.
3969
*/
3970
MagickExport unsigned short int MagickDoubleToUShort(const double dval/*, ExceptionInfo *exception*/)
3971
0
{
3972
0
  unsigned short int lval;
3973
3974
0
  do
3975
0
    {
3976
0
#if defined(INFINITY)
3977
0
      if (dval == +INFINITY)
3978
0
        {
3979
0
          lval=USHRT_MAX;
3980
0
          break;
3981
0
        }
3982
0
      if (dval == -INFINITY)
3983
0
        {
3984
0
          lval=0;
3985
0
          break;
3986
0
        }
3987
0
#endif
3988
0
      if (isnan(dval))
3989
0
        {
3990
0
          lval=0;
3991
0
          break;
3992
0
        }
3993
0
      if (floor(dval) > ((double) USHRT_MAX - 1))
3994
0
        {
3995
0
          lval=USHRT_MAX;
3996
0
          break;
3997
0
        }
3998
0
      if (ceil(dval) < 0.0)
3999
0
        {
4000
0
          lval=0;
4001
0
          break;
4002
0
        }
4003
0
      lval=(unsigned short int) dval;
4004
0
    } while (0);
4005
4006
0
  return lval;
4007
0
}
4008

4009
/*
4010
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4011
%                                                                             %
4012
%                                                                             %
4013
%                                                                             %
4014
%  M a g i c k F m i n                                                        %
4015
%                                                                             %
4016
%                                                                             %
4017
%                                                                             %
4018
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4019
%
4020
%  Method MagickFmin emulates C'99 fmin(), which returns the minimum of two
4021
%  double values.  This is implemented as a function rather than a macro.
4022
%
4023
%  The format of the MagickFmin method is:
4024
%
4025
%      double MagickFmin(const double x, const double y)
4026
%
4027
%  A description of each parameter follows.
4028
%
4029
%   o  x: first input value
4030
%
4031
%   o  y: second input value
4032
%
4033
%   o  returns: minimum of values x or y
4034
%
4035
%
4036
*/
4037
double MagickFmin(const double x, const double y)
4038
0
{
4039
0
  return Min(x,y);
4040
0
}
4041

4042
/*
4043
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4044
%                                                                             %
4045
%                                                                             %
4046
%                                                                             %
4047
%  M a g i c k F m a x                                                        %
4048
%                                                                             %
4049
%                                                                             %
4050
%                                                                             %
4051
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4052
%
4053
%  Method MagickFmax emulates C'99 fmax(), which returns the maximum of two
4054
%  double values.  This is implemented as a function rather than a macro.
4055
%
4056
%  The format of the MagickFmax method is:
4057
%
4058
%      double MagickFmax(const double x, const double y)
4059
%
4060
%  A description of each parameter follows.
4061
%
4062
%   o  x: first input value
4063
%
4064
%   o  y: second input value
4065
%
4066
%   o  returns: maximum of values x or y
4067
%
4068
%
4069
*/
4070
double MagickFmax(const double x, const double y)
4071
0
{
4072
0
  return Max(x,y);
4073
0
}
4074

4075
/*
4076
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4077
%                                                                             %
4078
%                                                                             %
4079
%                                                                             %
4080
%  M a g i c k F o r m a t S t r i n g                                        %
4081
%                                                                             %
4082
%                                                                             %
4083
%                                                                             %
4084
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4085
%
4086
%  Method MagickFormatString prints formatted output of a variable
4087
%  argument list buffer, limiting its output to a specified buffer size.
4088
%  The formatted size (as would be returned by strlen()) is returned.
4089
%
4090
%  The format of the MagickFormatString method is:
4091
%
4092
%      size_t MagickFormatString(char *string,const size_t length,
4093
%                                const char *format,...)
4094
%
4095
%  A description of each parameter follows.
4096
%
4097
%   o  string:  Method FormatString returns the formatted string in this
4098
%      character buffer. Buffer must be at least MaxTextExtent characters
4099
%      in size.
4100
%
4101
%   o  length:  Maximum number of characters to write into buffer, not
4102
%      including a terminating null byte.  The result is always terminated
4103
%      with a null byte.
4104
%
4105
%   o  format:  A string describing the format to use to write the remaining
4106
%      arguments.
4107
%
4108
%
4109
*/
4110
MagickExport size_t MagickFormatStringList(char *string,
4111
                                           const size_t length,
4112
                                           const char *format,
4113
                                           va_list operands)
4114
384M
{
4115
384M
  size_t
4116
384M
    fls = 0;
4117
4118
384M
  int
4119
384M
    fli;
4120
4121
384M
  if (length > 0)
4122
384M
    {
4123
384M
      fli=vsnprintf(string,length,format,operands);
4124
384M
      if (fli > 0)
4125
384M
        {
4126
384M
          if ((size_t) fli >= length)
4127
2
            fls=length-1;
4128
384M
          else
4129
384M
            fls=(size_t) fli;
4130
384M
        }
4131
384M
    }
4132
384M
  return fls;
4133
384M
}
4134
MagickExport size_t MagickFormatString(char *string,
4135
                                       const size_t length,
4136
                                       const char *format,...)
4137
370M
{
4138
370M
  va_list
4139
370M
    operands;
4140
4141
370M
  size_t
4142
370M
    formatted_len;
4143
4144
#if 0
4145
  assert(length > sizeof(char *)); /* Catch code update errors */
4146
#endif
4147
370M
  va_start(operands,format);
4148
370M
  formatted_len=MagickFormatStringList(string, length, format, operands);
4149
370M
  va_end(operands);
4150
370M
  return formatted_len;
4151
370M
}
4152

4153
/*
4154
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4155
%                                                                             %
4156
%                                                                             %
4157
%                                                                             %
4158
+   M a g i c k G e t T o k e n                                               %
4159
%                                                                             %
4160
%                                                                             %
4161
%                                                                             %
4162
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4163
%
4164
%  Method MagickGetToken gets a token from the token stream given a
4165
%  NUL-terminated buffer.  A token is defined as sequence of characters
4166
%  delimited by whitespace (e.g. clip-path), a sequence delimited with
4167
%  quotes (.e.g "Quote me"), or a sequence enclosed in parenthesis
4168
%  (e.g. rgb(0,0,0)).
4169
%
4170
%  The format of the MagickGetToken method is:
4171
%
4172
%      size_t MagickGetToken(const char *start,char **end,char *token,
4173
%                            const size_t max_token_length)
4174
%
4175
%  A description of each parameter follows:
4176
%
4177
%    o start: the start of the token sequence in a NUL-terminated buffer.
4178
%
4179
%    o end: points to the end of the scanned token sequence (may be NULL).
4180
%
4181
%    o token: copy the token to this buffer.
4182
%
4183
%    o max_token_length: maximum token length which may be returned.
4184
%     If the token exceeds the maximum token size,
4185
%     then the token will be truncated, but the parser will still
4186
%     update the end pointer (constrained by the terminating NUL
4187
%     character) as if the truncation did not occur. This allows
4188
%     using the end pointer as start when scanning a next token.
4189
%
4190
%    o returns: The size of the token returned.
4191
%
4192
%      This function used to "Report the size of the consumed token,
4193
%      not including a terminating null character.  If this is
4194
%      larger or equal to the buffer size then truncation has
4195
%      occurred". The old behavior is not useful given that
4196
%      the difference between 'end' and 'start' may be used to
4197
%      determine how many characters were consumed.
4198
%
4199
*/
4200
MagickExport size_t MagickGetToken(const char *start,char **end,char *token,
4201
                                   const size_t max_token_length)
4202
10.2M
{
4203
10.2M
  register const char
4204
10.2M
    *p;
4205
4206
10.2M
  register size_t
4207
10.2M
    i;
4208
4209
10.2M
  register size_t
4210
10.2M
    length = max_token_length - 1;
4211
4212
10.2M
  double
4213
10.2M
    double_val;
4214
4215
10.2M
  assert(start != (const char *) NULL);
4216
10.2M
  assert(token != (char *) NULL);
4217
4218
10.2M
  i=0;
4219
10.2M
  token[i]='\0';
4220
10.2M
  p=start;
4221
4222
10.2M
  if (*p != '\0')
4223
10.0M
    {
4224
18.0M
      while (isspace((int)(unsigned char) (*p)) && (*p != '\0'))
4225
8.02M
        p++;
4226
10.0M
      switch (*p)
4227
10.0M
        {
4228
7.37k
        case '"':
4229
360k
        case '\'':
4230
421k
        case '{':
4231
421k
          {
4232
421k
            register char
4233
421k
              escape;
4234
4235
421k
            escape=(*p);
4236
421k
            if (escape == '{')
4237
61.2k
              escape='}';
4238
137M
            for (p++; *p != '\0'; p++)
4239
137M
              {
4240
137M
                if ((*p == '\\') && ((*(p+1) == escape) || (*(p+1) == '\\')))
4241
5.72k
                  p++;
4242
137M
                else
4243
137M
                  if (*p == escape)
4244
399k
                    {
4245
399k
                      p++;
4246
399k
                      break;
4247
399k
                    }
4248
137M
                if (i < length)
4249
137M
                  token[i++]=(*p);
4250
137M
              }
4251
421k
            break;
4252
360k
          }
4253
9.59M
        default:
4254
9.59M
          {
4255
9.59M
            char
4256
9.59M
              *q;
4257
4258
9.59M
            double_val=strtod(p,&q);
4259
9.59M
            (void) double_val;
4260
9.59M
            if (p != q)
4261
5.17M
              {
4262
22.5M
                for ( ; p < q; p++)
4263
17.3M
                  if (i < length)
4264
17.2M
                    token[i++]=(*p);
4265
5.17M
                if (*p == '%')
4266
141k
                  if (i < length)
4267
141k
                    {
4268
141k
                      token[i++]=(*p);
4269
141k
                      p++;
4270
141k
                    }
4271
5.17M
                break;
4272
5.17M
              }
4273
4.41M
            if ((*p != '\0') && !isalpha((int) *p) &&
4274
1.56M
                (*p != *DirectorySeparator) &&
4275
1.56M
                (*p != '#') && (*p != '<'))
4276
1.27M
              {
4277
1.27M
                if (i < length)
4278
1.27M
                  {
4279
1.27M
                    token[i++]=(*p);
4280
1.27M
                    p++;
4281
1.27M
                  }
4282
1.27M
                break;
4283
1.27M
              }
4284
39.9M
            for ( ; *p != '\0'; p++)
4285
39.8M
              {
4286
39.8M
                if ((isspace((int)(unsigned char) *p) ||
4287
36.7M
                     (*p == '=')) && (*(p-1) != '\\'))
4288
3.04M
                  break;
4289
36.7M
                if (i < length)
4290
36.6M
                  token[i++]=(*p);
4291
36.7M
                if (*p == '(')
4292
17.5k
                  {
4293
1.77M
                    for (p++; *p != '\0'; p++)
4294
1.77M
                      {
4295
1.77M
                        if (i < length)
4296
1.76M
                          token[i++]=(*p);
4297
1.77M
                        if ((*p == ')') && (*(p-1) != '\\'))
4298
14.4k
                          break;
4299
1.77M
                      }
4300
17.5k
                  }
4301
36.7M
                if (*p == '\0')
4302
3.05k
                  break;
4303
36.7M
              }
4304
3.14M
            break;
4305
4.41M
          }
4306
10.0M
        }
4307
10.0M
    }
4308
10.2M
  token[i]='\0';
4309
10.2M
  {
4310
10.2M
    char
4311
10.2M
      *r;
4312
4313
    /*
4314
      Parse token in form "url(#%s)"
4315
    */
4316
10.2M
    if ((LocaleNCompare(token,"url(#",5) == 0) &&
4317
13.0k
        ((r = strrchr(token,')')) != NULL))
4318
12.0k
      {
4319
12.0k
        *r='\0';
4320
12.0k
        (void) memmove(token,token+5,r-token-4);
4321
12.0k
      }
4322
10.2M
  }
4323
10.2M
  if (end != (char **) NULL)
4324
9.65M
    *end=(char *)p;
4325
10.2M
  return (i); /* Was (p-start+1) to report consumed text */
4326
10.2M
}
4327

4328
/*
4329
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4330
%                                                                             %
4331
%                                                                             %
4332
%                                                                             %
4333
%   M a g i c k R a n d R e e n t r a n t                                     %
4334
%                                                                             %
4335
%                                                                             %
4336
%                                                                             %
4337
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4338
%
4339
%  Method MagickRandReentrant() is a reentrant version of the standard
4340
%  rand() function but which allows the user to pass a pointer to the
4341
%  'seed'.  Values returned are in the range of 0 - RAND_MAX.
4342
%
4343
%  This function is deprecated, and scheduled for eventual removal.
4344
%
4345
%  The format of the MagickRandReentrant method is:
4346
%
4347
%      int MagickRandReentrant(unsigned int *seed)
4348
%
4349
%  A description of each parameter follows:
4350
%
4351
%    o seed: The random sequence seed value.  Initialized by the user
4352
%            once (e.g. with output from MagickRandNewSeed()) and then
4353
%            passed via pointer thereafter.  If seed is NULL then
4354
%            this function behaves identically to rand(), using the
4355
%            global seed value set via srand().
4356
%
4357
*/
4358
MagickExport int MagickRandReentrant(unsigned int *seed)
4359
0
{
4360
0
  ARG_NOT_USED(seed);
4361
4362
0
  return (int) ((double) RAND_MAX*MagickRandomReal()+0.5);
4363
0
}
4364

4365
/*
4366
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4367
%                                                                             %
4368
%                                                                             %
4369
%                                                                             %
4370
%   M a g i c k R a n d N e w S e e d                                         %
4371
%                                                                             %
4372
%                                                                             %
4373
%                                                                             %
4374
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4375
%
4376
%  Method MagickRandNewSeed() returns a semi-random initial seed value for
4377
%  use with MagickRandReentrant() or rand().
4378
%
4379
%  This function is deprecated, and scheduled for eventual removal.
4380
%
4381
%  The format of the MagickRandNewSeed method is:
4382
%
4383
%      unsigned int MagickRandNewSeed(void)
4384
%
4385
*/
4386
MagickExport unsigned int MagickRandNewSeed(void)
4387
0
{
4388
0
  return (unsigned int) MagickRandomInteger();
4389
0
}
4390

4391
/*
4392
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4393
%                                                                             %
4394
%                                                                             %
4395
%                                                                             %
4396
%   M a g i c k S i z e S t r T o I n t 6 4                                   %
4397
%                                                                             %
4398
%                                                                             %
4399
%                                                                             %
4400
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4401
%
4402
%  MagickSizeStrToInt64() converts a numeric string expressed using a scaling
4403
%  suffix (e.g. "100K" is 100 kilo) to a 64-bit integer type.  Even though
4404
%  this function returns a signed type, it is intended to be used to obtain
4405
%  positive size values so a negative return value indicates an error.
4406
%  Specifically, -1 is returned if there is known to be an conversion error.
4407
%
4408
%  Binary Prefixes: http://en.wikipedia.org/wiki/Binary_prefix
4409
%
4410
%  SI Prefixes: http://en.wikipedia.org/wiki/SI_prefix
4411
%
4412
%  The format of the MagickSizeStrToInt64 method is:
4413
%
4414
%      magick_int64_t MagickSizeStrToInt64(const char *str,
4415
%                                          const unsigned int kilo)
4416
%
4417
%  A description of each parameter follows:
4418
%
4419
%    o str: Input string to convert
4420
%
4421
%    o kilo: The unit of "kilo".  Should be either 1000 (SI units)
4422
%            or 1024 (Binary units).
4423
%
4424
*/
4425
MagickExport magick_int64_t MagickSizeStrToInt64(const char *str,
4426
                                                 const unsigned int kilo)
4427
0
{
4428
0
  char
4429
0
    *end;
4430
4431
0
  magick_int64_t
4432
0
    result;
4433
4434
0
  MagickPassFail
4435
0
    status;
4436
4437
0
  result=-1;
4438
0
  end=(char *) NULL;
4439
0
  if ((status=MagickStrToInt64(str,&end,&result)) == MagickPass)
4440
0
    {
4441
0
      int
4442
0
        c,
4443
0
        mult;
4444
4445
0
      c='\0';
4446
0
      if (end != (char *) NULL)
4447
0
        c=*end;
4448
0
      mult=0;
4449
4450
0
      switch (tolower(c))
4451
0
        {
4452
0
        default: break;
4453
0
        case 'k': mult=1; break; /* kilo, 10^3 */
4454
0
        case 'm': mult=2; break; /* mega, 10^6 */
4455
0
        case 'g': mult=3; break; /* giga, 10^9 */
4456
0
        case 't': mult=4; break; /* tera, 10^12 */
4457
0
        case 'p': mult=5; break; /* peta, 10^15 */
4458
0
        case 'e': mult=6; break; /* exa,  10^18 */
4459
0
        }
4460
4461
0
      while (mult-- > 0)
4462
0
        result *= kilo;
4463
0
    }
4464
4465
0
  return result;
4466
0
}
4467

4468
/*
4469
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4470
%                                                                             %
4471
%                                                                             %
4472
%                                                                             %
4473
%   M a g i c k S p a w n V P                                                 %
4474
%                                                                             %
4475
%                                                                             %
4476
%                                                                             %
4477
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4478
%
4479
%  MagickSpawnVP() executes an external command with arguments provided by
4480
%  an argument vector.  The return status of the executed command is returned
4481
%  if it is executed, or -1 is returned if the command could not be executed.
4482
%  Executed commands will normally return zero if they execute without error.
4483
%
4484
%  The format of the MagickSpawnVP method is:
4485
%
4486
%      int MagickSpawnVP(const char *file, char *const argv[])
4487
%
4488
%  A description of each parameter follows:
4489
%
4490
%    o file:  Name of the command to execute.
4491
%
4492
%    o argv:  Argument vector. First argument in the vector should be
4493
%             the name of the command.  The argument vector is terminated
4494
%             via a NULL pointer.
4495
%
4496
*/
4497
MagickExport int
4498
MagickSpawnVP(const unsigned int verbose,const char *file, char *const argv[])
4499
0
{
4500
0
  int
4501
0
    status;
4502
4503
0
  char
4504
0
    message[MaxTextExtent];
4505
4506
4507
0
  status = -1;
4508
0
  message[0]='\0';
4509
0
  errno=0;
4510
4511
0
  assert(file != (const char *) NULL);
4512
4513
0
  if (strlen(file) == 0)
4514
0
    return -1;
4515
4516
0
  {
4517
    /*
4518
      Verify that we are allowed to run this program.
4519
    */
4520
0
    ExceptionInfo
4521
0
      exception;
4522
4523
0
    GetExceptionInfo(&exception);
4524
0
    if (MagickConfirmAccess(FileExecuteConfirmAccessMode,argv[0],&exception)
4525
0
        == MagickFail)
4526
0
      {
4527
0
        errno=EPERM;
4528
0
        DestroyExceptionInfo(&exception);
4529
0
        return -1;
4530
0
      }
4531
0
  }
4532
4533
#if defined(HAVE_SPAWNVP)
4534
  {
4535
    /* int spawnvp(int mode, const char *path, const char * const *argv); */
4536
#if defined(__MINGW64_VERSION_MAJOR)
4537
    /* MinGW-w64 prototype is lacking */
4538
    status = spawnvp(_P_WAIT, file, (char * const *) argv);
4539
#else
4540
    status = spawnvp(_P_WAIT, file, (const char * const *) argv);
4541
#endif
4542
  }
4543
#else
4544
0
  {
4545
0
    pid_t
4546
0
      child_pid;
4547
4548
0
    child_pid = fork( );
4549
0
    if ( (pid_t)-1 == child_pid)
4550
0
      {
4551
        /* Failed to fork, errno contains reason */
4552
0
        status = -1;
4553
0
        MagickFormatString(message,sizeof(message),"fork failed: %.1024s", strerror(errno));
4554
0
      }
4555
0
    else if ( 0 == child_pid )
4556
0
      {
4557
        /* We are the child process, exec program with arguments. */
4558
0
        status = execvp(file, argv);
4559
4560
        /* If we get here, then execvp must have failed. */
4561
0
        (void) fprintf(stderr, "execvp failed, errno = %d (%s)\n",errno,strerror(errno));
4562
4563
        /* If there is an execvp error, then call _exit() */
4564
0
        _exit(1);
4565
0
      }
4566
0
    else
4567
0
      {
4568
        /* We are the parent process, wait for child. */
4569
0
        pid_t waitpid_status;
4570
0
        int child_status = 0;
4571
0
        waitpid_status = waitpid(child_pid, &child_status, 0);
4572
0
        if ( (pid_t)-1 == waitpid_status )
4573
0
          {
4574
            /* Waitpid error */
4575
0
            status = -1;
4576
0
            MagickFormatString(message, sizeof(message), "waitpid failed: %.1024s", strerror(errno));
4577
0
          }
4578
0
        else if ( waitpid_status == child_pid )
4579
0
          {
4580
            /* Status is available for child process */
4581
0
            if ( WIFEXITED( child_status ) )
4582
0
              {
4583
0
                status =  WEXITSTATUS( child_status );
4584
0
              }
4585
0
            else if ( WIFSIGNALED( child_status ) )
4586
0
              {
4587
0
                int sig_num = WTERMSIG( child_status );
4588
0
                status = -1;
4589
0
                MagickFormatString(message, sizeof(message), "child process quit due to signal %d", sig_num);
4590
0
              }
4591
0
          }
4592
0
      }
4593
0
  }
4594
0
#endif
4595
4596
  /*
4597
    Provide a verbose/dignostic message in a form which is easy for
4598
    the user to understand.
4599
  */
4600
0
  if (verbose || (status != 0))
4601
0
    {
4602
0
      const char
4603
0
        *message_p = (const char *) NULL;
4604
4605
0
      char
4606
0
        *command;
4607
4608
0
      unsigned int
4609
0
        i;
4610
4611
0
      command = AllocateString((const char*) NULL);
4612
0
      for (i = 0; argv[i] != (const char*) NULL; i++)
4613
0
        {
4614
0
          char
4615
0
            buffer[MaxTextExtent];
4616
4617
0
          MagickFormatString(buffer,sizeof(buffer),"\"%.1024s\"", argv[i]);
4618
4619
0
          if (0 != i)
4620
0
            (void) ConcatenateString(&command," ");
4621
4622
0
          (void) ConcatenateString(&command,buffer);
4623
0
        }
4624
0
      if (message[0] != '\0')
4625
0
        message_p = message;
4626
0
      MagickError2(DelegateError,command,message_p);
4627
0
      MagickFreeMemory(command);
4628
0
    }
4629
4630
0
  return status;
4631
0
}
4632

4633
/*
4634
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4635
%                                                                             %
4636
%                                                                             %
4637
%                                                                             %
4638
%   M a g i c k S t r i p S t r i n g                                        %
4639
%                                                                             %
4640
%                                                                             %
4641
%                                                                             %
4642
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4643
%
4644
%  Method MagickStripString strips any whitespace or quotes from the
4645
%  beginning and end of a string of characters.  The final string length
4646
%  is returned.
4647
%
4648
%  The format of the _MagickStripString method is:
4649
%
4650
%      size_t _MagickStripString(char *message)
4651
%
4652
%  A description of each parameter follows:
4653
%
4654
%    o message: Specifies an array of characters.
4655
%
4656
%
4657
*/
4658
MagickExport size_t MagickStripString(char *message)
4659
6.37M
{
4660
6.37M
  register char
4661
6.37M
    *p,
4662
6.37M
    *q;
4663
4664
6.37M
  assert(message != (char *) NULL);
4665
6.37M
  if (*message == '\0')
4666
674k
    return 0;
4667
5.70M
  if (strlen(message) == 1)
4668
57.1k
    return 1;
4669
5.64M
  p=message;
4670
5.64M
  while (isspace((int)(unsigned char) (*p)))
4671
1.91M
    p++;
4672
5.64M
  if ((*p == '\'') || (*p == '"'))
4673
4.98k
    p++;
4674
5.64M
  q=message+strlen(message)-1;
4675
5.66M
  while (isspace((int)(unsigned char) (*q)) && (q > p))
4676
14.3k
    q--;
4677
5.64M
  if (q > p)
4678
5.63M
    if ((*q == '\'') || (*q == '"'))
4679
1.77M
      q--;
4680
5.64M
  (void) memmove(message,p,q-p+1);
4681
5.64M
  message[q-p+1]='\0';
4682
5.64M
  return (size_t) (q-p+1);
4683
5.70M
}
4684

4685
/*
4686
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4687
%                                                                             %
4688
%                                                                             %
4689
%                                                                             %
4690
%   M a g i c k S t r i p S p a c e s F r o m S t r i n g                     %
4691
%                                                                             %
4692
%                                                                             %
4693
%                                                                             %
4694
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4695
%
4696
%  MagickStripSpacesFromString() compacts a NULL-terminated string in-place
4697
%  by removing white space (space and tab) characters) from a string.
4698
%
4699
%  The format of the MagickStripSpacesFromString method is:
4700
%
4701
%      size_t MagickStripSpacesFromString(char *string)
4702
%
4703
%  A description of each parameter follows:
4704
%
4705
%    o string: String buffer to compact.
4706
%
4707
%    o returns: New string length
4708
%
4709
*/
4710
MagickExport size_t
4711
MagickStripSpacesFromString(char *string)
4712
0
{
4713
0
  register char
4714
0
    *w;
4715
4716
0
  register const char
4717
0
    *r;
4718
4719
0
  for (w=string, r=string; *r != '\0'; )
4720
0
    {
4721
0
      if ((*r == ' ') || (*r == '\t'))
4722
0
        {
4723
0
          r++;
4724
0
          continue;
4725
0
        }
4726
0
      if (r != w)
4727
0
        *w = *r;
4728
0
      r++;
4729
0
      w++;
4730
0
    }
4731
0
  *w='\0';
4732
0
  return (size_t) (w - string);
4733
0
}
4734

4735
/*
4736
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4737
%                                                                             %
4738
%                                                                             %
4739
%                                                                             %
4740
%   M a g i c k S t r T o I n t 6 4                                           %
4741
%                                                                             %
4742
%                                                                             %
4743
%                                                                             %
4744
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4745
%
4746
%  MagickStrToInt64() converts a string to a 64-bit integer type.  MagickPass
4747
%  is returned if the conversion succeeds, and MagickFail is returned if
4748
%  the conversion fails.
4749
%
4750
%  The format of the MagickStrToInt64 method is:
4751
%
4752
%      MagickPassFail MagickStrToInt64(const char *start,char **end,
4753
%                                      magick_int64_t *value)
4754
%
4755
%  A description of each parameter follows:
4756
%
4757
%    o start: Start of string
4758
%
4759
%    o end: Pointer to update with address where parsing stopped.
4760
%
4761
%    o value: Pointer to value to update
4762
%
4763
*/
4764
static MagickPassFail MagickStrToInt64(const char *start,char **end,
4765
                                       magick_int64_t *value)
4766
0
{
4767
0
  magick_int64_t
4768
0
    result;
4769
4770
0
  errno=0;
4771
0
  result=MagickStrToL64(start,end,10);
4772
0
  if (errno == 0)
4773
0
    *value=result;
4774
4775
0
  return (errno == 0);
4776
0
}
4777

4778
/*
4779
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4780
%                                                                             %
4781
%                                                                             %
4782
%                                                                             %
4783
%   M a g i c k C r e a t e D i r e c t o r y P a t h                         %
4784
%                                                                             %
4785
%                                                                             %
4786
%                                                                             %
4787
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4788
%
4789
%  MagickCreateDirectoryPath() creates the specified directory path, creating
4790
%  parent directories as required.  MagickPass is returned on success, and
4791
%  MagickFail is returned if there is a failure, with error information set
4792
%  in the user-provided ExceptionInfo structure.
4793
%
4794
%  The format of the MagickCreateDirectoryPath method is:
4795
%
4796
%      MagickPassFail MagickCreateDirectoryPath(const char *dir,
4797
%                                               ExceptionInfo *exception)
4798
%
4799
%  A description of each parameter follows:
4800
%
4801
%    o dir: Path to create.
4802
%
4803
%    o exception: Return any errors or warnings in this structure.
4804
%
4805
*/
4806
MagickExport MagickPassFail MagickCreateDirectoryPath(const char *dir,
4807
                                                      ExceptionInfo *exception)
4808
0
{
4809
0
  char
4810
0
    path[MaxTextExtent];
4811
4812
0
  size_t
4813
0
    dir_len;
4814
4815
0
  int
4816
0
    status = MagickPass;
4817
4818
0
  const char
4819
0
    *end,
4820
0
    *p;
4821
4822
0
  unsigned int
4823
0
    directory_mode;
4824
4825
0
#if !defined(MSWINDOWS)
4826
4827
0
#  if defined(S_IRWXU)
4828
0
  directory_mode = S_IRWXU;
4829
#  else
4830
  directory_mode = 0777;
4831
#  endif /* if defined(S_IRWXU) */
4832
4833
0
#  if defined(S_IRGRP)
4834
0
  directory_mode |= S_IRGRP;
4835
0
#  endif /* if defined(S_IRGRP) */
4836
0
#  if defined(S_IXGRP)
4837
0
  directory_mode |= S_IXGRP;
4838
0
#  endif /*if defined(S_IXGRP) */
4839
0
#  if defined(S_IROTH)
4840
0
  directory_mode |= S_IROTH;
4841
0
#  endif /* if defined(S_IROTH) */
4842
0
#  if defined(S_IXOTH)
4843
0
  directory_mode |= S_IXOTH;
4844
0
#  endif /* if defined(S_IXOTH) */
4845
4846
#else
4847
4848
  (void) directory_mode;
4849
4850
#endif /* if !defined(MSWINDOWS) */
4851
4852
0
  dir_len = strlen(dir);
4853
0
  end = dir + dir_len;
4854
4855
  /*
4856
    Walk back to find part of path which already exists.
4857
  */
4858
0
  for (p = end; p > dir ; p--)
4859
0
    {
4860
0
      if ((p == end) || (DirectorySeparator[0] == *p))
4861
0
        {
4862
0
          (void) strlcpy(path,dir,p-dir+1);
4863
0
          if (IsAccessibleNoLogging(path))
4864
0
            break;
4865
0
        }
4866
0
    }
4867
4868
0
  if (p != end)
4869
0
    {
4870
      /*
4871
        Create part of path which does not already exist.
4872
      */
4873
0
      for ( p++; p <= end ; p++)
4874
0
        {
4875
0
          if ((*p == '\0') || (DirectorySeparator[0] == *p))
4876
0
            {
4877
0
              (void) strlcpy(path,dir,p-dir+1);
4878
0
              if (-1 == mkdir(path,directory_mode))
4879
0
                {
4880
0
                  if (EEXIST != errno)
4881
0
                    {
4882
                      /*
4883
                        Throw exception.
4884
                      */
4885
0
                      ThrowException2(exception,FileOpenError,dir,strerror(errno));
4886
0
                      status = MagickFail;
4887
0
                      break;
4888
0
                    }
4889
0
                }
4890
0
              errno = 0;
4891
0
            }
4892
0
        }
4893
0
    }
4894
0
  return status;
4895
0
}
4896

4897
/*
4898
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4899
%                                                                             %
4900
%                                                                             %
4901
%                                                                             %
4902
%   M a g i c k S c e n e F i l e N a m e                                     %
4903
%                                                                             %
4904
%                                                                             %
4905
%                                                                             %
4906
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4907
%
4908
%  MagickSceneFileName() uses a filename template and scene number
4909
%  in order to produce a unique filename for the scene.  If force is
4910
%  MagickFalse, then a substitution is only performed if the template
4911
%  contains a valid substitution specification.  If force is MagickTrue,
4912
%  then the additional scene template is applied so that the generated
4913
%  filename is assured to be distinguished by the scene number.
4914
%
4915
%  The format of the MagickSceneFileName method is:
4916
%
4917
%      MagickBool MagickSceneFileName(char *filename, const char* template,
4918
%                                     unsigned long scene)
4919
%
4920
%  A description of each parameter follows:
4921
%
4922
%    o filename: Buffer to update with generated filename.  Buffer must
4923
%                be at least MaxTextExtent bytes long.
4924
%
4925
%    o filename_template: Filename generation template (e.g. "image%02d.miff").
4926
%
4927
%    o scene_template: Template for scene part which is appended to
4928
%                template if template does not contain a scene format
4929
%                specification  (e.g. ".%lu" or "[%lu]").
4930
%
4931
%    o force:    If there is no embedded template in filename, then apply
4932
%                the scene template.
4933
%
4934
%    o scene:    Scene number.
4935
%
4936
*/
4937
MagickExport MagickBool MagickSceneFileName(char *filename,
4938
                                            const char* filename_template,
4939
                                            const char* scene_template,
4940
                                            const MagickBool force,
4941
                                            unsigned long scene)
4942
0
{
4943
0
  const char
4944
0
    *p;
4945
4946
0
  MagickBool
4947
0
    status;
4948
4949
0
  status = MagickFalse;
4950
0
  (void) strlcpy(filename,filename_template,MaxTextExtent);
4951
0
  p=strchr(filename_template,'%');
4952
0
  if ((p != (char *) NULL) && ((strchr(p+1,'%') == (char *) NULL)))
4953
0
    {
4954
0
      for ( p=p+1; *p ; p++)
4955
0
        {
4956
0
          register const int c = *p;
4957
0
          if ('d' == c)
4958
0
            {
4959
0
              MagickFormatString(filename,MaxTextExtent,filename_template,scene);
4960
0
              break;
4961
0
            }
4962
0
          if (!isdigit(c))
4963
0
            {
4964
0
              status = MagickFalse;
4965
0
              break;
4966
0
            }
4967
0
        }
4968
0
    }
4969
4970
0
  if ((force) && (LocaleCompare(filename,filename_template) == 0))
4971
0
    {
4972
0
      char format[MaxTextExtent];
4973
0
      (void) strlcpy(format,"%.1024s",sizeof(format));
4974
0
      (void) strlcat(format,scene_template,sizeof(format));
4975
0
      MagickFormatString(filename,MaxTextExtent,format,filename_template,scene);
4976
0
    }
4977
0
  if (LocaleCompare(filename,filename_template) != 0)
4978
0
    status = MagickTrue;
4979
4980
0
  return status;
4981
0
}
4982

4983
/*
4984
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4985
%                                                                             %
4986
%                                                                             %
4987
%                                                                             %
4988
%  M a g i c k S t r l C a t                                                  %
4989
%                                                                             %
4990
%                                                                             %
4991
%                                                                             %
4992
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4993
%
4994
%  Method MagickStrlCat appends the NULL-terminated string src to the end
4995
%  of dst.  It will append at most size - strlen(dst) - 1 bytes, NULL-
4996
%  terminating the result. If size is zero, then the result is not NULL
4997
%  terminated. The total length of the string which would have been created
4998
%  given sufficient buffer size (may be longer than size) is returned.  This
4999
%  function substitutes for strlcat() which is available under FreeBSD,
5000
%  Apple's OS-X, and Solaris 8.
5001
%
5002
%  Buffer overflow can be checked as  follows:
5003
%
5004
%    if (MagickStrlCat(dst, src, dstsize) >= dstsize)
5005
%      return -1;
5006
%
5007
%  The format of the MagickStrlCat method is:
5008
%
5009
%      size_t MagickStrlCat(char *dst, const char *src, size_t size)
5010
%
5011
%  A description of each parameter follows.
5012
%
5013
%   o  dst:  Destination string.
5014
%
5015
%   o  src:  Source string.
5016
%
5017
%   o  size: Maximum string length, including the terminating null.
5018
%
5019
*/
5020
MagickExport size_t MagickStrlCat(char *dst, const char *src, const size_t size)
5021
18.5M
{
5022
18.5M
  size_t
5023
18.5M
    length;
5024
5025
18.5M
  const char
5026
18.5M
    *q;
5027
5028
18.5M
  assert(dst != NULL);
5029
18.5M
  assert(src != (const char *) NULL);
5030
18.5M
  assert(size >= 1);
5031
5032
18.5M
  length=strlen(dst);
5033
5034
  /*
5035
    Copy remaining characters from src while constraining length to
5036
    size - 1.
5037
  */
5038
18.5M
  q = src;
5039
18.5M
  if (size >= 1)
5040
18.5M
    {
5041
18.5M
      char
5042
18.5M
        *p;
5043
5044
#if defined(MAGICK_STRL_CHECK)
5045
      (void) memset(dst+length,0,size-length);
5046
#endif /* if defined(MAGICK_STRL_CHECK) */
5047
5048
18.5M
      for ( p = dst + length ;
5049
68.9M
            (*q != 0) && (length < size - 1) ;
5050
50.4M
            length++, p++, q++ )
5051
50.4M
        *p = *q;
5052
5053
18.5M
      dst[length]='\0';
5054
18.5M
    }
5055
5056
  /*
5057
    Add remaining length of src to length.
5058
  */
5059
18.5M
  while (*q++)
5060
23.8k
    length++;
5061
5062
18.5M
  return length;
5063
18.5M
}
5064

5065
/*
5066
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5067
%                                                                             %
5068
%                                                                             %
5069
%                                                                             %
5070
%  M a g i c k S t r l C p y                                                  %
5071
%                                                                             %
5072
%                                                                             %
5073
%                                                                             %
5074
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5075
%
5076
%  Method MagickStrlCpy copies up to size - 1 characters from the NULL-
5077
%  terminated string src to dst, NULL-terminating the result. If size is
5078
%  zero, then the result is not NULL terminated.  The total length of the
5079
%  string which would have been created given sufficient buffer size (may
5080
%  be longer than size) is returned. This function is similar to strlcpy()
5081
%  which is available under FreeBSD, Apple's OS-X, and Solaris 8 except
5082
%  that it is assured to work with overlapping objects.  FreeBSD does not
5083
%  document if strlcpy() handles overlapping objects, but Solaris strlcpy()
5084
%  does not.
5085
%
5086
%  Buffer overflow can be checked as  follows:
5087
%
5088
%    if (MagickStrlCpy(dst, src, dstsize) >= dstsize)
5089
%      return -1;
5090
%
5091
%  The format of the MagickStrlCpy method is:
5092
%
5093
%      size_t MagickStrlCpy(char *dst, const char *src, size_t size)
5094
%
5095
%  A description of each parameter follows.
5096
%
5097
%   o  dst:  Destination string.
5098
%
5099
%   o  src:  Source string.
5100
%
5101
%   o  size: Maximum string length, including the terminating null.
5102
%
5103
*/
5104
MagickExport size_t MagickStrlCpy(char *dst, const char *src, const size_t size)
5105
246M
{
5106
246M
  size_t
5107
246M
    length;
5108
5109
246M
  const char
5110
246M
    *q;
5111
5112
246M
  assert(dst != NULL);
5113
246M
  assert(src != (const char *) NULL);
5114
246M
  assert(size >= 1);
5115
  /* assert(((dst+size) <= src) || (dst >= (src+size))); */
5116
5117
#if defined(MAGICK_STRL_CHECK)
5118
  (void) memset(dst,0,size);
5119
#endif /* if defined(MAGICK_STRL_CHECK) */
5120
5121
  /*
5122
    Copy src to dst within bounds of size-1.
5123
  */
5124
246M
  length=0;
5125
246M
  q=src;
5126
246M
  if (size >= 1)
5127
246M
    {
5128
246M
      char
5129
246M
        *p;
5130
5131
246M
      for ( p=dst ;
5132
2.42G
            (*q != 0) && (length < size-1) ;
5133
2.18G
            length++, p++, q++ )
5134
2.18G
        *p = *q;
5135
5136
246M
      dst[length]='\0';
5137
246M
    }
5138
5139
  /*
5140
    Add remaining length of src to length.
5141
  */
5142
274M
  while (*q++)
5143
27.6M
    length++;
5144
5145
246M
  return length;
5146
246M
}
5147

5148
/*
5149
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5150
%                                                                             %
5151
%                                                                             %
5152
%                                                                             %
5153
%  M a g i c k S t r l C p y T r u n c                                        %
5154
%                                                                             %
5155
%                                                                             %
5156
%                                                                             %
5157
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5158
%
5159
%  Method MagickStrlCpyTrunc copies up to size - 1 characters from the NULL-
5160
%  terminated string src to dst, NULL-terminating the result.  If size is
5161
%  zero, then the result is not NULL terminated.  The number of bytes copied
5162
%  (not including the terminating NULL) is returned.  This function is a
5163
%  useful alternative to using MagickStrlCpy() when the actual size copied
5164
%  is more useful than knowledge that truncation occurred.
5165
%
5166
%  The format of the MagickStrlCat method is:
5167
%
5168
%      size_t MagickStrlCpyTrunc(char *dst, const char *src, size_t size)
5169
%
5170
%  A description of each parameter follows.
5171
%
5172
%   o  dst:  Destination string.
5173
%
5174
%   o  src:  Source string.
5175
%
5176
%   o  size: Maximum string length, including the terminating null.
5177
%
5178
*/
5179
MagickExport size_t MagickStrlCpyTrunc(char *dst, const char *src, const size_t size)
5180
0
{
5181
0
  size_t
5182
0
    length;
5183
5184
0
  const char
5185
0
    *q;
5186
5187
0
  assert(dst != NULL);
5188
0
  assert(src != (const char *) NULL);
5189
0
  assert(size >= 1);
5190
5191
  /*
5192
    Copy src to dst within bounds of size-1.
5193
  */
5194
0
  length=0;
5195
0
  if (size >= 1)
5196
0
    {
5197
0
      char
5198
0
        *p;
5199
5200
0
      for ( p=dst, q=src;
5201
0
            (*q != 0) && (length < size-1) ;
5202
0
            length++, p++, q++ )
5203
0
        *p = *q;
5204
5205
0
      dst[length]='\0';
5206
0
    }
5207
5208
0
  return length;
5209
0
}
5210

5211
/*
5212
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5213
%                                                                             %
5214
%                                                                             %
5215
%                                                                             %
5216
%  M u l t i l i n e C e n s u s                                              %
5217
%                                                                             %
5218
%                                                                             %
5219
%                                                                             %
5220
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5221
%
5222
%  Method MultilineCensus returns the number of lines within a label.  A line
5223
%  is represented by a \n character.
5224
%
5225
%  The format of the MultilineCenus method is:
5226
%
5227
%      unsigned long MultilineCensus(const char *label)
5228
%
5229
%  A description of each parameter follows.
5230
%
5231
%   o  label:  This character string is the label.
5232
%
5233
%
5234
*/
5235
MagickExport unsigned long MultilineCensus(const char *label)
5236
1.62k
{
5237
1.62k
  long
5238
1.62k
    number_lines;
5239
5240
  /*
5241
    Determine the number of lines within this label.
5242
  */
5243
1.62k
  if (label == (char *) NULL)
5244
0
    return(0);
5245
27.5k
  for (number_lines=1; *label != '\0'; label++)
5246
25.9k
    if (*label == '\n')
5247
3.24k
      number_lines++;
5248
1.62k
  return(number_lines);
5249
1.62k
}
5250

5251
/*
5252
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5253
%                                                                             %
5254
%                                                                             %
5255
%                                                                             %
5256
%   S e t C l i e n t F i l e n a m e                                         %
5257
%                                                                             %
5258
%                                                                             %
5259
%                                                                             %
5260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5261
%
5262
%  Method SetClientFilename sets the client filename if the name is specified.
5263
%  Otherwise the current client filename is returned. On a UNIX system the
5264
%  client name and filename are often the same since file extensions are not
5265
%  very important, but on windows the distinction is very important.
5266
%
5267
%  The format of the SetClientFilename method is:
5268
%
5269
%      char *SetClientFilname(const char *name)
5270
%
5271
%  A description of each parameter follows:
5272
%
5273
%    o client_name: Method SetClientFilename returns the current client name.
5274
%
5275
%    o status: Specifies the new client name.
5276
%
5277
%
5278
*/
5279
MagickExport const char *GetClientFilename(void)
5280
252
{
5281
252
  return(SetClientFilename((char *) NULL));
5282
252
}
5283
5284
MagickExport const char *SetClientFilename(const char *name)
5285
504
{
5286
504
  static char
5287
504
    client_filename[256] = "";
5288
5289
504
  if ((name != (char *) NULL) && (*name != '\0'))
5290
252
    {
5291
252
      (void) strlcpy(client_filename,name,sizeof(client_filename));
5292
252
      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
5293
252
        "Client Filename was set to: %s",client_filename);
5294
252
    }
5295
504
  return(client_filename);
5296
504
}
5297

5298
/*
5299
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5300
%                                                                             %
5301
%                                                                             %
5302
%                                                                             %
5303
%   S e t C l i e n t N a m e                                                 %
5304
%                                                                             %
5305
%                                                                             %
5306
%                                                                             %
5307
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5308
%
5309
%  Method SetClientName sets the client name if the name is specified.
5310
%  Otherwise the current client name is returned.  The default value
5311
%  returned if a value was never set is "Magick".
5312
%
5313
%  The format of the SetClientName method is:
5314
%
5315
%      char *SetClientName(const char *name)
5316
%
5317
%  A description of each parameter follows:
5318
%
5319
%    o client_name: Method SetClientName returns the current client name.
5320
%
5321
%    o status: Specifies the new client name.
5322
%
5323
%
5324
*/
5325
MagickExport const char *GetClientName(void)
5326
26.0k
{
5327
26.0k
  return SetClientName((char *) NULL);
5328
26.0k
}
5329
5330
MagickExport const char *SetClientName(const char *name)
5331
495k
{
5332
495k
  static char
5333
495k
    client_name[256] = "";
5334
5335
495k
  if ((name != (char *) NULL) && (*name != '\0'))
5336
252
    {
5337
252
      (void) strlcpy(client_name,name,sizeof(client_name));
5338
252
      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
5339
252
        "Client Name was set to: %s",client_name);
5340
252
    }
5341
495k
  return (client_name[0] == '\0' ? "Magick" : client_name);
5342
495k
}
5343

5344
/*
5345
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5346
%                                                                             %
5347
%                                                                             %
5348
%                                                                             %
5349
%   S e t C l i e n t P a t h                                                 %
5350
%                                                                             %
5351
%                                                                             %
5352
%                                                                             %
5353
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5354
%
5355
%  Method SetClientPath sets the client path if the name is specified.
5356
%  Otherwise the current client path is returned. A zero-length string
5357
%  is returned if the client path has never been set.
5358
%
5359
%  The format of the SetClientPath method is:
5360
%
5361
%      char *SetClientPath(const char *path)
5362
%
5363
%  A description of each parameter follows:
5364
%
5365
%    o client_path: Method SetClientPath returns the current client path.
5366
%
5367
%    o status: Specifies the new client path.
5368
%
5369
%
5370
*/
5371
MagickExport const char *GetClientPath(void)
5372
252
{
5373
252
  return(SetClientPath((char *) NULL));
5374
252
}
5375
5376
MagickExport const char *SetClientPath(const char *path)
5377
1.09k
{
5378
1.09k
  static char
5379
1.09k
    client_path[MaxTextExtent] = "";
5380
5381
1.09k
  if ((path != (char *) NULL) && (*path != '\0'))
5382
252
    {
5383
252
      (void) strlcpy(client_path,path,sizeof(client_path));
5384
252
      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
5385
252
        "Client Path was set to: %s",path);
5386
252
    }
5387
1.09k
  return(client_path);
5388
1.09k
}
5389

5390
/*
5391
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5392
%                                                                             %
5393
%                                                                             %
5394
%                                                                             %
5395
%   S e t G e o m e t r y                                                     %
5396
%                                                                             %
5397
%                                                                             %
5398
%                                                                             %
5399
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5400
%
5401
%  SetGeometry sets a geometry to its default values.
5402
%
5403
%  The format of the SetGeometry method is:
5404
%
5405
%      SetGeometry(const Image *image,RectangleInfo *geometry)
5406
%
5407
%  A description of each parameter follows:
5408
%
5409
%    o image: The image.
5410
%
5411
%    o geometry: The geometry.
5412
%
5413
%
5414
*/
5415
MagickExport void SetGeometry(const Image *image,RectangleInfo *geometry)
5416
58.0k
{
5417
58.0k
  assert(image != (Image *) NULL);
5418
58.0k
  assert(geometry != (RectangleInfo *) NULL);
5419
58.0k
  (void) memset(geometry,0,sizeof(RectangleInfo));
5420
58.0k
  geometry->width=image->columns;
5421
58.0k
  geometry->height=image->rows;
5422
58.0k
}
5423

5424
/*
5425
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5426
%                                                                             %
5427
%                                                                             %
5428
%                                                                             %
5429
%  S t r i n g T o A r g v                                                    %
5430
%                                                                             %
5431
%                                                                             %
5432
%                                                                             %
5433
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5434
%
5435
%  Method StringToArgv converts a text string into command line arguments.
5436
%
5437
%  The format of the StringToArgv method is:
5438
%
5439
%      char **StringToArgv(const char *text,int *argc)
5440
%
5441
%  A description of each parameter follows:
5442
%
5443
%    o argv:  Method StringToArgv returns the string list unless an error
5444
%      occurs, otherwise NULL.
5445
%
5446
%    o text:  Specifies the string to segment into a list.
5447
%
5448
%    o argc:  This integer pointer returns the number of arguments in the
5449
%      list.
5450
%
5451
%
5452
*/
5453
MagickExport char **StringToArgv(const char *text,int *argc)
5454
0
{
5455
0
  char
5456
0
    **argv;
5457
5458
0
  register char
5459
0
    *p,
5460
0
    *q;
5461
5462
0
  register long
5463
0
    i;
5464
5465
0
  *argc=0;
5466
0
  if (text == (char *) NULL)
5467
0
    return((char **) NULL);
5468
  /*
5469
    Determine the number of arguments.
5470
  */
5471
0
  for (p=(char *) text; *p != '\0'; )
5472
0
  {
5473
0
    while (isspace((int)(unsigned char) (*p)))
5474
0
      p++;
5475
0
    (*argc)++;
5476
0
    if (*p == '"')
5477
0
      for (p++; (*p != '"') && (*p != '\0'); p++);
5478
0
    if (*p == '\'')
5479
0
      for (p++; (*p != '\'') && (*p != '\0'); p++);
5480
0
    while (!isspace((int)(unsigned char) (*p)) && (*p != '\0'))
5481
0
      p++;
5482
0
  }
5483
0
  (*argc)++;
5484
0
  argv=MagickAllocateMemory(char **,MagickArraySize((size_t) *argc+1,sizeof(char *)));
5485
0
  if (argv == (char **) NULL)
5486
0
    {
5487
0
      MagickError3(ResourceLimitError,MemoryAllocationFailed,
5488
0
        UnableToConvertStringToTokens);
5489
0
      return((char **) NULL);
5490
0
    }
5491
  /*
5492
    Convert string to an ASCII list.
5493
  */
5494
0
  argv[0]=AllocateString("magick");
5495
0
  p=(char *) text;
5496
0
  for (i=1; i < *argc; i++)
5497
0
  {
5498
0
    while (isspace((int)(unsigned char) (*p)))
5499
0
      p++;
5500
0
    q=p;
5501
0
    if (*q == '"')
5502
0
      {
5503
0
        p++;
5504
0
        for (q++; (*q != '"') && (*q != '\0'); q++);
5505
0
      }
5506
0
    else
5507
0
      if (*q == '\'')
5508
0
        {
5509
0
          for (q++; (*q != '\'') && (*q != '\0'); q++);
5510
0
          q++;
5511
0
        }
5512
0
      else
5513
0
        while (!isspace((int)(unsigned char) (*q)) && (*q != '\0'))
5514
0
          q++;
5515
0
    argv[i]=MagickAllocateMemory(char *,(size_t) (q-p+MaxTextExtent));
5516
0
    if (argv[i] == (char *) NULL)
5517
0
      {
5518
0
        int
5519
0
          j;
5520
5521
0
        MagickError3(ResourceLimitError,MemoryAllocationFailed,
5522
0
          UnableToConvertStringToTokens);
5523
5524
        /*
5525
          Deallocate allocated data and return.
5526
        */
5527
0
        for (j=0; j<i; j++)
5528
0
          MagickFreeMemory(argv[j]);
5529
0
        MagickFreeMemory(argv);
5530
0
        return((char **) NULL);
5531
0
      }
5532
0
    (void) strlcpy(argv[i],p,q-p+1);
5533
0
    p=q;
5534
0
    while (!isspace((int)(unsigned char) (*p)) && (*p != '\0'))
5535
0
      p++;
5536
0
  }
5537
0
  argv[i]=(char *) NULL;
5538
0
  return(argv);
5539
0
}
5540

5541
/*
5542
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5543
%                                                                             %
5544
%                                                                             %
5545
%                                                                             %
5546
%  S t r i n g T o D o u b l e                                                %
5547
%                                                                             %
5548
%                                                                             %
5549
%                                                                             %
5550
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5551
%
5552
%  Method StringToDouble() converts a text string to a double.  If the string
5553
%  contains a percent sign (e.g. 50%) that percentage of the interval is
5554
%  returned.
5555
%
5556
%  The format of the StringToDouble method is:
5557
%
5558
%      double StringToDouble(const char *text,const double interval)
5559
%
5560
%  A description of each parameter follows:
5561
%
5562
%    o value:  Method StringToDouble returns the converted value.
5563
%
5564
%    o text:  Specifies the string to segment into a list.
5565
%
5566
%    o interval:  Specifies the interval; used for obtaining a percentage.
5567
%
5568
%
5569
*/
5570
MagickExport double StringToDouble(const char *text,const double interval)
5571
0
{
5572
0
  char
5573
0
    *q;
5574
5575
0
  double
5576
0
    value;
5577
5578
0
  if (MagickStrToD(text,&q,&value) == 0)
5579
0
    return 0.0;
5580
0
  if (strchr(q,'%') != (char *) NULL)
5581
0
    value*=interval/100.0;
5582
0
  return(value);
5583
0
}
5584

5585
/*
5586
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5587
%                                                                             %
5588
%                                                                             %
5589
%                                                                             %
5590
%  S t r i n g T o L i s t                                                    %
5591
%                                                                             %
5592
%                                                                             %
5593
%                                                                             %
5594
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5595
%
5596
%  Method StringToList converts a text string into a list by segmenting the
5597
%  text string at each carriage return discovered.  The list is converted to
5598
%  HEX characters if any control characters are discovered within the text
5599
%  string.
5600
%
5601
%  The format of the StringToList method is:
5602
%
5603
%      char **StringToList(const char *text)
5604
%
5605
%  A description of each parameter follows:
5606
%
5607
%    o list:  Method StringToList returns the string list unless an error
5608
%      occurs, otherwise NULL.
5609
%
5610
%    o text:  Specifies the string to segment into a list.
5611
%
5612
%
5613
*/
5614
MagickExport char **StringToList(const char *text)
5615
0
{
5616
0
  char
5617
0
    **textlist;
5618
5619
0
  register char
5620
0
    *q;
5621
5622
0
  register const char
5623
0
    *p;
5624
5625
0
  register size_t
5626
0
    i;
5627
5628
0
  size_t
5629
0
    lines;
5630
5631
0
  if (text == (char *) NULL)
5632
0
    return((char **) NULL);
5633
0
  for (p=text; *p != '\0'; p++)
5634
0
    if (((unsigned char) *p < 32) && !isspace((int)(unsigned char) (*p)))
5635
0
      break;
5636
0
  if (*p == '\0')
5637
0
    {
5638
      /*
5639
        Convert string to an ASCII list.
5640
      */
5641
0
      lines=1;
5642
0
      for (p=text; *p != '\0'; p++)
5643
0
        if (*p == '\n')
5644
0
          lines++;
5645
0
      textlist=MagickAllocateMemory(char **,(lines+1)*sizeof(char *));
5646
0
      if (textlist == (char **) NULL)
5647
0
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
5648
0
                          UnableToConvertText);
5649
0
      p=text;
5650
0
      for (i=0; i < lines; i++)
5651
0
        {
5652
0
          for (q=(char *) p; *q != '\0'; q++)
5653
0
            if ((*q == '\r') || (*q == '\n'))
5654
0
              break;
5655
0
          textlist[i]=MagickAllocateMemory(char *,(size_t) (q-p+1));
5656
0
          if (textlist[i] == (char *) NULL)
5657
0
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
5658
0
                              UnableToConvertText);
5659
0
          (void) memcpy(textlist[i],p,q-p);
5660
0
          textlist[i][q-p]='\0';
5661
0
          if (*q == '\r')
5662
0
            q++;
5663
0
          p=q+1;
5664
0
        }
5665
0
    }
5666
0
  else
5667
0
    {
5668
0
      const size_t
5669
0
        chars_per_line = 0x14;
5670
5671
0
      char
5672
0
        hex_string[MaxTextExtent];
5673
5674
0
      register size_t
5675
0
        j;
5676
5677
      /*
5678
        Convert string to a HEX list.
5679
      */
5680
0
      lines=(strlen(text)/chars_per_line)+1;
5681
0
      textlist=MagickAllocateMemory(char **,(lines+1)*sizeof(char *));
5682
0
      if (textlist == (char **) NULL)
5683
0
        MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
5684
0
                          UnableToConvertText);
5685
0
      p=text;
5686
0
      for (i=0; i < lines; i++)
5687
0
        {
5688
          /* FIXME: Allocation here is excessively large */
5689
0
          const size_t textlist_size = 2*MaxTextExtent;
5690
0
          textlist[i]=MagickAllocateMemory(char *,textlist_size);
5691
0
          if (textlist[i] == (char *) NULL)
5692
0
            MagickFatalError3(ResourceLimitFatalError,MemoryAllocationFailed,
5693
0
                              UnableToConvertText);
5694
0
          MagickFormatString(textlist[i],textlist_size/2,"0x%08" MAGICK_SIZE_T_F "x: ",
5695
0
                             (MAGICK_SIZE_T) chars_per_line*i);
5696
0
          q=textlist[i]+strlen(textlist[i]);
5697
0
          for (j=1; j <= Min(strlen(p),chars_per_line); j++)
5698
0
            {
5699
0
              MagickFormatString(hex_string,sizeof(hex_string),"%02x",*(p+j));
5700
0
              (void) strlcpy(q,hex_string,MaxTextExtent);
5701
0
              q+=2;
5702
0
              if ((j % 0x04) == 0)
5703
0
                *q++=' ';
5704
0
            }
5705
0
          for (; j <= chars_per_line; j++)
5706
0
            {
5707
0
              *q++=' ';
5708
0
              *q++=' ';
5709
0
              if ((j % 0x04) == 0)
5710
0
                *q++=' ';
5711
0
            }
5712
0
          *q++=' ';
5713
0
          for (j=1; j <= Min(strlen(p),chars_per_line); j++)
5714
0
            {
5715
0
              if (isprint((int)(unsigned char)(*p)))
5716
0
                *q++=(*p);
5717
0
              else
5718
0
                *q++='-';
5719
0
              p++;
5720
0
            }
5721
0
          *q='\0';
5722
0
        }
5723
0
    }
5724
0
  textlist[i]=(char *) NULL;
5725
0
  return(textlist);
5726
0
}
5727

5728
/*
5729
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5730
%                                                                             %
5731
%                                                                             %
5732
%                                                                             %
5733
+   S u b s t i t u t e S t r i n g                                           %
5734
%                                                                             %
5735
%                                                                             %
5736
%                                                                             %
5737
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5738
%
5739
%  SubstituteString() performs string substitution on a buffer, replacing
5740
%  the buffer with the substituted version. Buffer must be allocated from
5741
%  the heap since it may be reallocated (as required). MagickTrue is returned
5742
%  if a replacement was made.
5743
%
5744
%  The format of the SubstituteString method is:
5745
%
5746
%      MagickBool SubstituteString(char **buffer,const char* search,
5747
%        const char *replace)
5748
%
5749
%  A description of each parameter follows:
5750
%
5751
%    o buffer: The buffer to perform replacements on. Replaced with new
5752
%      allocation if a replacement is made.
5753
%
5754
%    o search: String to search for.
5755
%
5756
%    o replace: Replacement string.
5757
%
5758
*/
5759
MagickExport MagickBool
5760
SubstituteString(char **buffer,const char *search,const char *replace)
5761
0
{
5762
0
  register char
5763
0
    *p=*buffer;
5764
5765
0
  register size_t
5766
0
    i;
5767
5768
0
  size_t
5769
0
    search_len=0,
5770
0
    replace_len=0;
5771
5772
0
  MagickBool
5773
0
    replaced=MagickFalse;
5774
5775
0
  search_len=strlen(search);
5776
0
  p=*buffer;
5777
0
  for (i=0; p[i] != '\0'; i++)
5778
0
    {
5779
0
      if ((p[i] == search[0]) && (strncmp(&p[i],search,search_len) == 0))
5780
0
        {
5781
0
          if (0 == replace_len)
5782
0
            {
5783
0
              replace_len=strlen(replace);
5784
0
              if (replace_len == 0)
5785
0
                break;
5786
0
            }
5787
0
          if (replace_len > search_len)
5788
0
            {
5789
0
              size_t
5790
0
                allocation_len;
5791
5792
0
              allocation_len=strlen(p)+(replace_len-search_len)+1;
5793
0
              MagickRoundUpStringLength(allocation_len);
5794
0
              MagickReallocMemory(char *,p,allocation_len);
5795
0
              *buffer=p;
5796
0
              if (p == (char *) NULL)
5797
0
                MagickFatalError3(ResourceLimitFatalError,
5798
0
                                  MemoryAllocationFailed,
5799
0
                                  UnableToAllocateString);
5800
0
            }
5801
0
          if (search_len != replace_len)
5802
0
            (void) MagickCloneMemory(&p[i+replace_len],&p[i+search_len],
5803
0
                                     strlen(&p[i+search_len])+1);
5804
0
          (void) MagickCloneMemory(&p[i],replace,replace_len);
5805
0
          i += (replace_len-1);
5806
0
          replaced=MagickTrue;
5807
0
        }
5808
0
    }
5809
0
  return replaced;
5810
0
}
5811

5812
/*
5813
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5814
%                                                                             %
5815
%                                                                             %
5816
%                                                                             %
5817
%   S y s t e m C o m m a n d                                                 %
5818
%                                                                             %
5819
%                                                                             %
5820
%                                                                             %
5821
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5822
%
5823
%  Method SystemCommand executes the specified command and waits until it
5824
%  terminates.  The returned value is the exit status of the command.
5825
%
5826
%  The format of the SystemCommand method is:
5827
%
5828
%      int SystemCommand(const unsigned int verbose,const char *command)
5829
%
5830
%  A description of each parameter follows:
5831
%
5832
%    o status: Method SystemCommand returns False if the command is
5833
%      executed successfully.
5834
%
5835
%    o verbose: An unsigned integer other than 0 prints the executed
5836
%      command before it is invoked.
5837
%
5838
%    o command: This string is the command to execute.
5839
%
5840
%
5841
*/
5842
MagickExport int SystemCommand(const unsigned int verbose,const char *command)
5843
0
{
5844
0
  int
5845
0
    status;
5846
5847
0
#if defined(POSIX)
5848
0
  char
5849
0
    message[MaxTextExtent];
5850
0
#endif /* POSIX */
5851
5852
0
  const char
5853
0
    *message_p = (const char *) NULL;
5854
5855
0
  {
5856
    /*
5857
      Verify that we are allowed to run this program.
5858
    */
5859
0
    ExceptionInfo
5860
0
      exception;
5861
5862
0
    char
5863
0
      *end,
5864
0
      program[MaxTextExtent];
5865
5866
0
    GetExceptionInfo(&exception);
5867
0
    end=(char *) NULL;
5868
0
    program[0]='\0';
5869
0
    MagickGetToken(command,&end,program,MaxTextExtent);
5870
0
    if (MagickConfirmAccess(FileExecuteConfirmAccessMode,program,&exception)
5871
0
        == MagickFail)
5872
0
      {
5873
0
        errno=EPERM;
5874
0
        DestroyExceptionInfo(&exception);
5875
0
        return -1;
5876
0
      }
5877
0
  }
5878
5879
0
  errno=0;
5880
0
#if defined(POSIX)
5881
0
  status=system(command);
5882
0
  if (status == 1)
5883
0
    {
5884
0
      (void) strlcpy(message,strerror(status),sizeof(message));
5885
0
      message_p=message;
5886
0
    }
5887
0
  else if (WIFSIGNALED(status))
5888
0
    {
5889
0
      MagickFormatString(message,sizeof(message),"terminated due to signal %d",
5890
0
                         WTERMSIG(status));
5891
0
      message[sizeof(message)-1]='\0';
5892
0
      message_p=message;
5893
0
    }
5894
#elif defined(MSWINDOWS)
5895
  status=NTSystemComman(command);
5896
  if (!status)
5897
    message_p=strerror(status);
5898
#else
5899
#  error Do not know how to run system commands.
5900
#endif
5901
0
  if (verbose || (status != 0))
5902
0
    MagickError2(DelegateError,command,message_p);
5903
0
  return(status);
5904
0
}
5905

5906
/*
5907
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5908
%                                                                             %
5909
%                                                                             %
5910
%                                                                             %
5911
%   T o k e n i z e r                                                         %
5912
%                                                                             %
5913
%                                                                             %
5914
%                                                                             %
5915
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5916
%
5917
%  Method Tokenizer is a generalized, finite state token parser.  It extracts
5918
%  tokens one at a time from a string of characters.  The characters used for
5919
%  white space, for break characters, and for quotes can be specified.  Also,
5920
%  characters in the string can be preceded by a specifiable escape character
5921
%  which removes any special meaning the character may have.
5922
%
5923
%  Here is some terminology:
5924
%
5925
%    o token: A single unit of information in the form of a group of
5926
%      characters.
5927
%
5928
%    o white space: Space that gets ignored (except within quotes or when
5929
%      escaped), like blanks and tabs. in addition, white space terminates a
5930
%      non-quoted token.
5931
%
5932
%    o break set: One or more characters that separates non-quoted tokens.
5933
%      Commas are a common break character. The usage of break characters to
5934
%      signal the end of a token is the same as that of white space, except
5935
%      multiple break characters with nothing or only white space between
5936
%      generate a null token for each two break characters together.
5937
%
5938
%      For example, if blank is set to be the white space and comma is set to
5939
%      be the break character, the line
5940
%
5941
%        A, B, C ,  , DEF
5942
%
5943
%        ... consists of 5 tokens:
5944
%
5945
%        1)  "A"
5946
%        2)  "B"
5947
%        3)  "C"
5948
%        4)  "" (the null string)
5949
%        5)  "DEF"
5950
%
5951
%    o Quote character: A character that, when surrounding a group of other
5952
%      characters, causes the group of characters to be treated as a single
5953
%      token, no matter how many white spaces or break characters exist in
5954
%      the group. Also, a token always terminates after the closing quote.
5955
%      For example, if ' is the quote character, blank is white space, and
5956
%      comma is the break character, the following string
5957
%
5958
%        A, ' B, CD'EF GHI
5959
%
5960
%        ... consists of 4 tokens:
5961
%
5962
%        1)  "A"
5963
%        2)  " B, CD" (note the blanks & comma)
5964
%        3)  "EF"
5965
%        4)  "GHI"
5966
%
5967
%      The quote characters themselves do not appear in the resultant
5968
%      tokens.  The double quotes are delimiters i use here for
5969
%      documentation purposes only.
5970
%
5971
%    o Escape character: A character which itself is ignored but which
5972
%      causes the next character to be used as is.  ^ and \ are often used
5973
%      as escape characters. An escape in the last position of the string
5974
%      gets treated as a "normal" (i.e., non-quote, non-white, non-break,
5975
%      and non-escape) character. For example, assume white space, break
5976
%      character, and quote are the same as in the above examples, and
5977
%      further, assume that ^ is the escape character. Then, in the string
5978
%
5979
%        ABC, ' DEF ^' GH' I ^ J K^ L ^
5980
%
5981
%        ... there are 7 tokens:
5982
%
5983
%        1)  "ABC"
5984
%        2)  " DEF ' GH"
5985
%        3)  "I"
5986
%        4)  " "     (a lone blank)
5987
%        5)  "J"
5988
%        6)  "K L"
5989
%        7)  "^"     (passed as is at end of line)
5990
%
5991
%  The format of the Tokenizer method is:
5992
%
5993
%      int Tokenizer(TokenInfo *token_info,unsigned flag,char *token,
5994
%        size_t max_token_length,char *line,char *white,char *break_set,
5995
%        char *quote,char escape,char *breaker,int *next,char *quoted)
5996
%
5997
%  A description of each parameter follows:
5998
%
5999
%    o flag: right now, only the low order 3 bits are used.
6000
%
6001
%        1 => convert non-quoted tokens to upper case
6002
%        2 => convert non-quoted tokens to lower case
6003
%        0 => do not convert non-quoted tokens
6004
%
6005
%    o token: a character string containing the returned next token
6006
%
6007
%    o max_token_length: the maximum size of "token".  Characters beyond
6008
%      "max_token_length" are truncated.
6009
%
6010
%    o string: the string to be parsed.
6011
%
6012
%    o white: a string of the valid white spaces.  example:
6013
%
6014
%        char whitesp[]={" \t"};
6015
%
6016
%      blank and tab will be valid white space.
6017
%
6018
%    o break: a string of the valid break characters. example:
6019
%
6020
%        char breakch[]={";,"};
6021
%
6022
%      semicolon and comma will be valid break characters.
6023
%
6024
%    o quote: a string of the valid quote characters. An example would be
6025
%
6026
%        char whitesp[]={"'\"");
6027
%
6028
%      (this causes single and double quotes to be valid) Note that a
6029
%      token starting with one of these characters needs the same quote
6030
%      character to terminate it.
6031
%
6032
%      for example:
6033
%
6034
%        "ABC '
6035
%
6036
%      is unterminated, but
6037
%
6038
%        "DEF" and 'GHI'
6039
%
6040
%      are properly terminated.  Note that different quote characters
6041
%      can appear on the same line; only for a given token do the quote
6042
%      characters have to be the same.
6043
%
6044
%    o escape: the escape character (NOT a string ... only one
6045
%      allowed). Use zero if none is desired.
6046
%
6047
%    o breaker: the break character used to terminate the current
6048
%      token.  If the token was quoted, this will be the quote used.  If
6049
%      the token is the last one on the line, this will be zero.
6050
%
6051
%    o next: this variable points to the first character of the
6052
%      next token.  it gets reset by "tokenizer" as it steps through the
6053
%      string.  Set it to 0 upon initialization, and leave it alone
6054
%      after that.  You can change it if you want to jump around in the
6055
%      string or re-parse from the beginning, but be careful.
6056
%
6057
%    o quoted: set to True if the token was quoted and False
6058
%      if not.  You may need this information (for example:  in C, a
6059
%      string with quotes around it is a character string, while one
6060
%      without is an identifier).
6061
%
6062
%    o result: 0 if we haven't reached EOS (end of string), and 1
6063
%      if we have.
6064
%
6065
*/
6066
6067
101M
#define IN_WHITE 0
6068
123M
#define IN_TOKEN 1
6069
212M
#define IN_QUOTE 2
6070
21.9M
#define IN_OZONE 3
6071
6072
static long sindex(char c,char *string) MAGICK_FUNC_PURE;
6073
6074
static long sindex(char c,char *string)
6075
377M
{
6076
377M
  register char
6077
377M
    *p;
6078
6079
554M
  for (p=string; *p; p++)
6080
203M
    if (c == (*p))
6081
26.1M
      return(p-string);
6082
351M
  return(-1);
6083
377M
}
6084
6085
static void StoreToken(TokenInfo *token_info,char *string,
6086
  size_t max_token_length,char c)
6087
121M
{
6088
121M
  register long
6089
121M
    i;
6090
6091
121M
  if ((token_info->offset < 0) ||
6092
121M
      ((size_t) token_info->offset >= (max_token_length-1)))
6093
0
    return;
6094
121M
  i=token_info->offset++;
6095
121M
  string[i]=c;
6096
121M
  if (token_info->state == IN_QUOTE)
6097
19.9M
    return;
6098
101M
  switch (token_info->flag & 0x03)
6099
101M
  {
6100
0
    case 1:
6101
0
    {
6102
0
      string[i]=toupper((int) c);
6103
0
      break;
6104
0
    }
6105
0
    case 2:
6106
0
    {
6107
0
      string[i]=tolower((int) c);
6108
0
      break;
6109
0
    }
6110
101M
    default:
6111
101M
      break;
6112
101M
  }
6113
101M
}
6114
6115
MagickExport int Tokenizer(TokenInfo *token_info,unsigned flag,char *token,
6116
  size_t max_token_length,char *line,char *white,char *break_set,char *quote,
6117
  char escape,char *breaker,int *next,char *quoted)
6118
94.8M
{
6119
94.8M
  char
6120
94.8M
    c;
6121
6122
94.8M
  register long
6123
94.8M
    i;
6124
6125
94.8M
  *breaker=False;
6126
94.8M
  *quoted=False;
6127
94.8M
  if (!line[*next])
6128
43.8M
    return(1);
6129
50.9M
  token_info->state=IN_WHITE;
6130
50.9M
  token_info->quote=False;
6131
50.9M
  token_info->flag=flag;
6132
172M
  for (token_info->offset=0; line[*next] != 0; (*next)++)
6133
143M
  {
6134
143M
    c=line[*next];
6135
143M
    i=sindex(c,break_set);
6136
143M
    if (i >= 0)
6137
25.9M
      {
6138
25.9M
        switch (token_info->state)
6139
25.9M
        {
6140
20.4M
          case IN_WHITE:
6141
21.7M
          case IN_TOKEN:
6142
21.7M
          case IN_OZONE:
6143
21.7M
          {
6144
21.7M
            (*next)++;
6145
21.7M
            *breaker=break_set[i];
6146
21.7M
            token[token_info->offset]=0;
6147
21.7M
            return(0);
6148
21.7M
          }
6149
4.19M
          case IN_QUOTE:
6150
4.19M
          {
6151
4.19M
            StoreToken(token_info,token,max_token_length,c);
6152
4.19M
            break;
6153
21.7M
          }
6154
25.9M
        }
6155
4.19M
        continue;
6156
25.9M
      }
6157
117M
    i=sindex(c,quote);
6158
117M
    if (i >= 0)
6159
201k
      {
6160
201k
        switch(token_info->state)
6161
201k
        {
6162
98.0k
          case IN_WHITE:
6163
98.0k
          {
6164
98.0k
            token_info->state=IN_QUOTE;
6165
98.0k
            token_info->quote=quote[i];
6166
98.0k
            *quoted=True;
6167
98.0k
            break;
6168
0
          }
6169
69.1k
          case IN_QUOTE:
6170
69.1k
          {
6171
69.1k
            if (quote[i] != token_info->quote)
6172
0
              StoreToken(token_info,token,max_token_length,c);
6173
69.1k
            else
6174
69.1k
              {
6175
69.1k
                token_info->state=IN_OZONE;
6176
69.1k
                token_info->quote=0;
6177
69.1k
              }
6178
69.1k
            break;
6179
0
          }
6180
27.0k
          case IN_TOKEN:
6181
33.9k
          case IN_OZONE:
6182
33.9k
          {
6183
33.9k
            *breaker=c;
6184
33.9k
            token[token_info->offset]=0;
6185
33.9k
            return(0);
6186
27.0k
          }
6187
201k
        }
6188
167k
        continue;
6189
201k
      }
6190
117M
    i=sindex(c,white);
6191
117M
    if (i >= 0)
6192
0
      {
6193
0
        switch(token_info->state)
6194
0
        {
6195
0
          case IN_WHITE:
6196
0
          case IN_OZONE:
6197
0
            break;
6198
0
          case IN_TOKEN:
6199
0
          {
6200
0
            token_info->state=IN_OZONE;
6201
0
            break;
6202
0
          }
6203
0
          case IN_QUOTE:
6204
0
          {
6205
0
            StoreToken(token_info,token,max_token_length,c);
6206
0
            break;
6207
0
          }
6208
0
        }
6209
0
        continue;
6210
0
      }
6211
117M
    if (c == escape)
6212
0
      {
6213
0
        if (line[(*next)+1] == 0)
6214
0
          {
6215
0
            *breaker=0;
6216
0
            StoreToken(token_info,token,max_token_length,c);
6217
0
            (*next)++;
6218
0
            token[token_info->offset]=0;
6219
0
            return(0);
6220
0
          }
6221
0
        switch(token_info->state)
6222
0
        {
6223
0
          case IN_WHITE:
6224
0
          {
6225
0
            (*next)--;
6226
0
            token_info->state=IN_TOKEN;
6227
0
            break;
6228
0
          }
6229
0
          case IN_TOKEN:
6230
0
          case IN_QUOTE:
6231
0
          {
6232
0
            (*next)++;
6233
0
            c=line[*next];
6234
0
            StoreToken(token_info,token,max_token_length,c);
6235
0
            break;
6236
0
          }
6237
0
          case IN_OZONE:
6238
0
          {
6239
0
            token[token_info->offset]=0;
6240
0
            return(0);
6241
0
          }
6242
0
        }
6243
0
        continue;
6244
0
      }
6245
117M
    switch(token_info->state)
6246
117M
    {
6247
30.3M
      case IN_WHITE:
6248
30.3M
        {
6249
30.3M
          token_info->state=IN_TOKEN;
6250
30.3M
          StoreToken(token_info,token,max_token_length,c);
6251
30.3M
          break;
6252
0
        }
6253
70.9M
      case IN_TOKEN:
6254
86.6M
      case IN_QUOTE:
6255
86.6M
      {
6256
86.6M
        StoreToken(token_info,token,max_token_length,c);
6257
86.6M
        break;
6258
70.9M
      }
6259
59.2k
      case IN_OZONE:
6260
59.2k
      {
6261
59.2k
        token[token_info->offset]=0;
6262
59.2k
        return(0);
6263
70.9M
      }
6264
117M
    }
6265
117M
  }
6266
29.1M
  token[token_info->offset]=0;
6267
29.1M
  return(0);
6268
50.9M
}
6269

6270
/*
6271
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6272
%                                                                             %
6273
%                                                                             %
6274
%                                                                             %
6275
%   T r a n s l a t e T e x t                                                 %
6276
%                                                                             %
6277
%                                                                             %
6278
%                                                                             %
6279
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6280
%
6281
%  Method TranslateText replaces any embedded formatting characters with
6282
%  the appropriate image attribute and returns the translated text.  See
6283
%  the documentation for TranslateTextEx() for the available translations.
6284
%
6285
%  The format of the TranslateText method is:
6286
%
6287
%      char *TranslateText(const ImageInfo *image_info,Image *image,
6288
%        const char *formatted_text)
6289
%
6290
%  A description of each parameter follows:
6291
%
6292
%    o translated_text:  Method TranslateText returns a new allocation
6293
%      containing the translated text string.  If the translated text
6294
%      string would be empty, a NULL pointer is returned instead.
6295
%
6296
%    o image_info: The imageInfo (may be NULL!).
6297
%
6298
%    o image: The image.
6299
%
6300
%    o formatted_text: The address of a character string containing the embedded
6301
%      formatting characters.
6302
%
6303
*/
6304
6305
MagickExport char *TranslateText(const ImageInfo *image_info,
6306
                                 Image *image,
6307
                                 const char *formatted_text)
6308
62
{
6309
62
  return TranslateTextEx(image_info,image,formatted_text,MagickStrlCpyTrunc);
6310
62
}
6311

6312
/*
6313
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6314
%                                                                             %
6315
%                                                                             %
6316
%                                                                             %
6317
%   T r a n s l a t e T e x t E x                                             %
6318
%                                                                             %
6319
%                                                                             %
6320
%                                                                             %
6321
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6322
%
6323
%  Method TranslateTextEx replaces any embedded formatting characters with
6324
%  the appropriate image attribute and returns the translated text, while
6325
%  applying a text transformation for each substitution via a user provided
6326
%  translation function.  The translation function should behave similar to
6327
%  strlcpy() but may translate text while it is copied.
6328
%
6329
%  The currently supported translations are:
6330
%
6331
%    %b   file size
6332
%    %c   comment
6333
%    %d   directory
6334
%    %e   filename extension
6335
%    %f   filename
6336
%    %g   page dimensions and offsets
6337
%    %h   height
6338
%    %i   input filename
6339
%    %k   number of unique colors
6340
%    %l   label
6341
%    %m   magick
6342
%    %n   number of scenes
6343
%    %o   output filename
6344
%    %p   page number
6345
%    %q   image bit depth
6346
%    %r   image type description
6347
%    %s   scene number
6348
%    %t   top of filename
6349
%    %u   first unique temporary filename
6350
%    %w   width
6351
%    %x   horizontal resolution
6352
%    %y   vertical resolution
6353
%    %z   second unique temporary filename
6354
%    %A   transparency supported
6355
%    %C   compression type
6356
%    %D   GIF disposal method
6357
%    %G   Original width and height
6358
%    %H   page height
6359
%    %M   original filename specification
6360
%    %O   page offset (x,y)
6361
%    %P   page dimensions (width,height)
6362
%    %Q   compression quality
6363
%    %T   time delay (in centi-seconds)
6364
%    %U   resolution units
6365
%    %W   page width
6366
%    %X   page horizontal offset (x)
6367
%    %Y   page vertical offset (y)
6368
%    %@   trim bounding box
6369
%    %[a] named attribute 'a'
6370
%    %#   signature
6371
%    \n   newline
6372
%    \r   carriage return
6373
%    %%   % (literal)
6374
%
6375
%  The format of the TranslateTextEx method is:
6376
%
6377
%      char *TranslateTextEx(const ImageInfo *image_info,Image *image,
6378
%        const char *formatted_text, MagickTextTranslate translate)
6379
%
6380
%  A description of each parameter follows:
6381
%
6382
%    o translated_text:  Method TranslateTextEx returns a new allocation
6383
%      containing the translated text string.  If the translated text
6384
%      string would be empty, a NULL pointer is returned instead.
6385
%
6386
%    o image_info: The imageInfo (may be NULL!).
6387
%
6388
%    o image: The image.
6389
%
6390
%    o formatted_text: The address of a character string containing the embedded
6391
%      formatting characters.
6392
%
6393
%    o translate: text translation callback function
6394
%
6395
*/
6396
MagickExport char *TranslateTextEx(const ImageInfo *image_info,
6397
                                   Image *image,
6398
                                   const char *formatted_text,
6399
                                   MagickTextTranslate translate)
6400
62
{
6401
62
  char
6402
62
    buffer[MaxTextExtent],
6403
62
    *text,
6404
62
    *translated_text;
6405
6406
62
  const ImageAttribute
6407
62
    *attribute;
6408
6409
62
  register char
6410
62
    *p,
6411
62
    *q;
6412
6413
62
  register long
6414
62
    i;
6415
6416
62
  size_t
6417
62
    length,
6418
62
    offset;
6419
6420
62
  assert(image != (Image *) NULL);
6421
62
  if ((formatted_text == (const char *) NULL) || (*formatted_text == '\0'))
6422
62
    return((char *) NULL);
6423
0
  text=(char *) formatted_text;
6424
  /*
6425
    Translate any embedded format characters.
6426
  */
6427
0
  length=strlen(text);
6428
0
  translated_text=MagickAllocateMemory(char *,length+MaxTextExtent);
6429
0
  if (translated_text == (char *) NULL)
6430
0
    return NULL;
6431
0
  (void) memcpy(translated_text,text,length);
6432
0
  translated_text[length]='\0';
6433
0
  length=length+MaxTextExtent;
6434
0
  p=text;
6435
0
  for (q=translated_text; *p != '\0'; p++)
6436
0
    {
6437
0
      *q='\0';
6438
0
      if ((size_t) (q-translated_text+MaxTextExtent) >= length)
6439
0
        {
6440
0
          length<<=1;
6441
0
          MagickReallocMemory(char *,translated_text,length);
6442
0
          if (translated_text == (char *) NULL)
6443
0
            break;
6444
0
          q=translated_text+strlen(translated_text);
6445
0
        }
6446
      /*
6447
        Process formatting characters in text.
6448
      */
6449
0
      if ((*p == '\\') && (*(p+1) == 'r'))
6450
0
        {
6451
0
          *q++='\r';
6452
0
          p++;
6453
0
          continue;
6454
0
        }
6455
0
      if ((*p == '\\') && (*(p+1) == 'n'))
6456
0
        {
6457
0
          *q++='\n';
6458
0
          p++;
6459
0
          continue;
6460
0
        }
6461
0
      if (*p != '%')
6462
0
        {
6463
0
          *q++=(*p);
6464
0
          continue;
6465
0
        }
6466
0
      p++;
6467
0
      switch (*p)
6468
0
        {
6469
0
        case 'b':
6470
0
          {
6471
            /* File size */
6472
0
            FormatSize(GetBlobSize(image),buffer);
6473
0
            q+=(translate)(q,buffer,MaxTextExtent);
6474
0
            break;
6475
0
          }
6476
0
        case 'c':
6477
0
          {
6478
            /* Comment */
6479
0
            attribute=GetImageAttribute(image,"comment");
6480
0
            if (attribute != (ImageAttribute *) NULL)
6481
0
              {
6482
                /* Comments may be larger than MaxTextExtent so make sure
6483
                   there is sufficient memory allocated. Make sure that
6484
                   there is at least MaxTextExtent left available after we
6485
                   have concatenated our part. */
6486
0
                offset=q-translated_text;
6487
0
                if ((size_t) (offset+attribute->length+1+MaxTextExtent) >= length)
6488
0
                  {
6489
0
                    length += (attribute->length+1+2*MaxTextExtent);
6490
0
                    MagickReallocMemory(char *,translated_text,length);
6491
0
                    if (translated_text == (char *) NULL)
6492
0
                      break;
6493
0
                    q=translated_text+offset;
6494
0
                  }
6495
0
                q+=(translate)(q,attribute->value,attribute->length+1+MaxTextExtent);
6496
0
              }
6497
0
            break;
6498
0
          }
6499
0
        case 'd':
6500
0
        case 'e':
6501
0
        case 'f':
6502
0
        case 't':
6503
0
          {
6504
            /*
6505
              Label segment is the base of the filename.
6506
            */
6507
0
            if (strlen(image->magick_filename) != 0)
6508
0
              {
6509
0
                (void) strlcpy(buffer,"",MaxTextExtent);
6510
0
                switch (*p)
6511
0
                  {
6512
0
                  case 'd':
6513
0
                    {
6514
                      /* Directory */
6515
0
                      GetPathComponent(image->magick_filename,HeadPath,buffer);
6516
0
                      break;
6517
0
                    }
6518
0
                  case 'e':
6519
0
                    {
6520
                      /* Filename extension */
6521
0
                      GetPathComponent(image->magick_filename,ExtensionPath,buffer);
6522
0
                      break;
6523
0
                    }
6524
0
                  case 'f':
6525
0
                    {
6526
                      /* Filename */
6527
0
                      GetPathComponent(image->magick_filename,TailPath,buffer);
6528
0
                      break;
6529
0
                    }
6530
0
                  case 't':
6531
0
                    {
6532
                      /* Top of filename */
6533
0
                      GetPathComponent(image->magick_filename,BasePath,buffer);
6534
0
                      break;
6535
0
                    }
6536
0
                  }
6537
0
                q+=(translate)(q,buffer,MaxTextExtent);
6538
0
              }
6539
0
            break;
6540
0
          }
6541
0
        case 'g':
6542
0
          {
6543
            /* page dimensions and offsets */
6544
0
            MagickFormatString(buffer,sizeof(buffer),"%lux%lu%+ld%+ld",
6545
0
                               image->page.width,image->page.height,
6546
0
                               image->page.x,image->page.y);
6547
0
            q+=(translate)(q,buffer,MaxTextExtent);
6548
0
            break;
6549
0
          }
6550
0
        case 'h':
6551
0
          {
6552
            /* Image height */
6553
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->rows);
6554
0
            q+=(translate)(q,buffer,MaxTextExtent);
6555
0
            break;
6556
0
          }
6557
0
        case 'i':
6558
0
          {
6559
            /* Input filename */
6560
0
            q+=(translate)(q,image->filename,MaxTextExtent);
6561
0
            break;
6562
0
          }
6563
0
        case 'k':
6564
0
          {
6565
            /* Number of unique colors */
6566
0
            if (GetPixelCachePresent(image))
6567
0
              {
6568
0
                MagickFormatString(buffer,sizeof(buffer),"%lu",
6569
0
                                   GetNumberColors(image,(FILE *) NULL,
6570
0
                                                   &image->exception));
6571
0
                q+=(translate)(q,buffer,MaxTextExtent);
6572
0
              }
6573
0
            else
6574
0
              {
6575
0
                *q++='%';
6576
0
                *q++=(*p);
6577
0
              }
6578
0
            break;
6579
0
          }
6580
0
        case 'l':
6581
0
          {
6582
            /* Label */
6583
0
            attribute=GetImageAttribute(image,"label");
6584
0
            if (attribute != (ImageAttribute *) NULL)
6585
0
              q+=(translate)(q,attribute->value,MaxTextExtent);
6586
0
            break;
6587
0
          }
6588
0
        case 'm':
6589
0
          {
6590
            /* File format "magick" */
6591
0
            q+=(translate)(q,image->magick,MaxTextExtent);
6592
0
            break;
6593
0
          }
6594
0
        case 'n':
6595
0
          {
6596
            /* Number of scenes */
6597
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",
6598
0
                               (unsigned long) GetImageListLength(image));
6599
0
            q+=(translate)(q,buffer,MaxTextExtent);
6600
0
            break;
6601
0
          }
6602
0
        case 'o':
6603
0
          {
6604
            /* Output filename */
6605
0
            if (image_info != (const ImageInfo *) NULL)
6606
0
              q+=(translate)(q,image_info->filename,MaxTextExtent);
6607
0
            break;
6608
0
          }
6609
0
        case 'p':
6610
0
          {
6611
            /* Page number */
6612
0
            register const Image
6613
0
              *frame;
6614
6615
0
            unsigned long
6616
0
              page;
6617
6618
0
            frame=image;
6619
0
            for (page=1; frame->previous != (Image *) NULL; page++)
6620
0
              frame=frame->previous;
6621
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",page);
6622
0
            q+=(translate)(q,buffer,MaxTextExtent);
6623
0
            break;
6624
0
          }
6625
0
        case 'q':
6626
0
          {
6627
            /* Quantum depth */
6628
0
            if (GetPixelCachePresent(image))
6629
0
              MagickFormatString(buffer,sizeof(buffer),"%lu",
6630
0
                                 GetImageDepth(image,&image->exception));
6631
0
            else
6632
0
              MagickFormatString(buffer,sizeof(buffer),"%u",image->depth);
6633
0
            q+=(translate)(q,buffer,MaxTextExtent);
6634
0
            break;
6635
0
          }
6636
0
        case 'r':
6637
0
          {
6638
            /* Image type */
6639
0
            q+=(translate)(q,ImageTypeToString(GetImageType(image,&image->exception)),
6640
0
                           MaxTextExtent);
6641
0
            break;
6642
0
          }
6643
0
        case 's':
6644
0
          {
6645
            /* Scene number */
6646
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->scene);
6647
0
            if (image_info != (const ImageInfo *) NULL)
6648
0
              if (image_info->subrange != 0)
6649
0
                MagickFormatString(buffer,sizeof(buffer),"%lu",image_info->subimage);
6650
0
            q+=(translate)(q,buffer,MaxTextExtent);
6651
0
            break;
6652
0
          }
6653
0
        case 'u':
6654
0
          {
6655
            /* Unique temporary filename */
6656
0
            if (image_info != (const ImageInfo *) NULL)
6657
0
              {
6658
0
                if (strlcpy(buffer,image_info->unique,MaxTextExtent) == 0)
6659
0
                  if (!AcquireTemporaryFileName(buffer))
6660
0
                    break;
6661
0
                q+=(translate)(q,buffer,MaxTextExtent);
6662
0
              }
6663
0
            break;
6664
0
          }
6665
0
        case 'w':
6666
0
          {
6667
            /* Image width */
6668
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->columns);
6669
0
            q+=(translate)(q,buffer,MaxTextExtent);
6670
0
            break;
6671
0
          }
6672
0
        case 'x':
6673
0
          {
6674
            /* Horizontal resolution (default to 72.0 DPI if impossibly small) */
6675
0
            MagickFormatString(buffer,sizeof(buffer),"%g",
6676
0
                               fabs(image->x_resolution) > MagickEpsilon ? image->x_resolution :
6677
0
                               (image->units == PixelsPerCentimeterResolution ? 72.0/2.54 : 72.0));
6678
0
            q+=(translate)(q,buffer,MaxTextExtent);
6679
0
            break;
6680
0
          }
6681
0
        case 'y':
6682
0
          {
6683
            /* Vertical resolution (default to 72.0 DPI if impossibly small) */
6684
0
            MagickFormatString(buffer,sizeof(buffer),"%g",
6685
0
                               fabs(image->y_resolution) > MagickEpsilon ? image->y_resolution :
6686
0
                               (image->units == PixelsPerCentimeterResolution ? 72.0/2.54 : 72.0));
6687
0
            q+=(translate)(q,buffer,MaxTextExtent);
6688
0
            break;
6689
0
          }
6690
0
        case 'z':
6691
0
          {
6692
            /* Second unique temporary filename */
6693
0
            if (image_info != (const ImageInfo *) NULL)
6694
0
              {
6695
0
                if (strlcpy(buffer,image_info->zero,MaxTextExtent) == 0)
6696
0
                  if (!AcquireTemporaryFileName(buffer))
6697
0
                    break;
6698
0
                q+=(translate)(q,buffer,MaxTextExtent);
6699
0
              }
6700
0
            break;
6701
0
          }
6702
0
        case 'A':
6703
0
          {
6704
            /* Transparency supported */
6705
0
            MagickFormatString(buffer,sizeof(buffer),"%s",image->matte? "true" : "false");
6706
0
            q+=(translate)(q,buffer,MaxTextExtent);
6707
0
            break;
6708
0
          }
6709
0
        case 'C':
6710
0
          {
6711
            /* Image compression type */
6712
0
            MagickFormatString(buffer,sizeof(buffer),"%s",CompressionTypeToString(image->compression));
6713
0
            q+=(translate)(q,buffer,MaxTextExtent);
6714
0
            break;
6715
0
          }
6716
0
        case 'D':
6717
0
          {
6718
            /* GIF disposal method */
6719
0
            MagickFormatString(buffer,sizeof(buffer),"%d",image->dispose);
6720
0
            q+=(translate)(q,buffer,MaxTextExtent);
6721
0
            break;
6722
0
          }
6723
0
        case 'G':
6724
0
          {
6725
            /* Original image width and height */
6726
0
            MagickFormatString(buffer,sizeof(buffer),"%lux%lu",
6727
0
                               image->magick_columns,image->magick_rows);
6728
0
            q+=(translate)(q,buffer,MaxTextExtent);
6729
0
            break;
6730
0
          }
6731
0
        case 'H':
6732
0
          {
6733
            /* page height */
6734
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->page.height);
6735
0
            q+=(translate)(q,buffer,MaxTextExtent);
6736
0
            break;
6737
0
          }
6738
0
        case 'M':
6739
0
          {
6740
            /* Original filename specification */
6741
0
            q+=(translate)(q,image->magick_filename,MaxTextExtent);
6742
0
            break;
6743
0
          }
6744
0
        case 'O':
6745
0
          {
6746
            /* page offset */
6747
0
            MagickFormatString(buffer,sizeof(buffer),"%+ld%+ld",
6748
0
                               image->page.x,image->page.y);
6749
0
            q+=(translate)(q,buffer,MaxTextExtent);
6750
0
            break;
6751
0
          }
6752
0
        case 'P':
6753
0
          {
6754
            /* page dimensions */
6755
0
            MagickFormatString(buffer,sizeof(buffer),"%lux%lu",
6756
0
                               image->page.width,image->page.height);
6757
0
            q+=(translate)(q,buffer,MaxTextExtent);
6758
0
            break;
6759
0
          }
6760
0
        case 'Q':
6761
0
          {
6762
            /* Compression quality */
6763
0
            attribute=GetImageAttribute(image,"JPEG-Quality");
6764
0
            if (attribute != (ImageAttribute *) NULL)
6765
0
              {
6766
0
                q+=(translate)(q,attribute->value,MaxTextExtent);
6767
0
                break;
6768
0
              }
6769
0
            if (image_info != (const ImageInfo *) NULL)
6770
0
              {
6771
0
                MagickFormatString(buffer,sizeof(buffer),"%lu",image_info->quality);
6772
0
                q+=(translate)(q,buffer,MaxTextExtent);
6773
0
                break;
6774
0
              }
6775
0
            MagickFormatString(buffer,sizeof(buffer),"%u",DefaultCompressionQuality);
6776
0
            q+=(translate)(q,buffer,MaxTextExtent);
6777
0
            break;
6778
0
          }
6779
0
        case 'T':
6780
0
          {
6781
            /* time delay (in centi-seconds) */
6782
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->delay);
6783
0
            q+=(translate)(q,buffer,MaxTextExtent);
6784
0
            break;
6785
0
          }
6786
0
        case 'U':
6787
0
          {
6788
            /* resolution units */
6789
0
            MagickFormatString(buffer,sizeof(buffer),"%s",ResolutionTypeToString(image->units));
6790
0
            q+=(translate)(q,buffer,MaxTextExtent);
6791
0
            break;
6792
0
          }
6793
0
        case 'W':
6794
0
          {
6795
            /* page width */
6796
0
            MagickFormatString(buffer,sizeof(buffer),"%lu",image->page.width);
6797
0
            q+=(translate)(q,buffer,MaxTextExtent);
6798
0
            break;
6799
0
          }
6800
0
        case 'X':
6801
0
          {
6802
            /* page x offset */
6803
0
            MagickFormatString(buffer,sizeof(buffer),"%+ld",image->page.x);
6804
0
            q+=(translate)(q,buffer,MaxTextExtent);
6805
0
            break;
6806
0
          }
6807
0
        case 'Y':
6808
0
          {
6809
            /* page y offset */
6810
0
            MagickFormatString(buffer,sizeof(buffer),"%+ld",image->page.y);
6811
0
            q+=(translate)(q,buffer,MaxTextExtent);
6812
0
            break;
6813
0
          }
6814
0
        case '@':
6815
0
          {
6816
            /* trim bounding box */
6817
0
            RectangleInfo bounds = GetImageBoundingBox(image,
6818
0
                                                       &image->exception);
6819
0
            MagickFormatString(buffer,sizeof(buffer),"%lux%lu%+ld%+ld",
6820
0
                               bounds.width,bounds.height,bounds.x,bounds.y);
6821
0
            q+=(translate)(q,buffer,MaxTextExtent);
6822
0
            break;
6823
0
          }
6824
0
        case '[':
6825
0
          {
6826
            /* Image attribute */
6827
0
            char
6828
0
              key[MaxTextExtent];
6829
6830
            /*
6831
              Extract attribute key string.
6832
6833
              FIXME: does not handle nested specification so that
6834
              '%[[MVG]]' results in '[MVG]'.
6835
            */
6836
0
            p++;
6837
0
            for (i=0; (i < MaxTextExtent-1) && (*p) && (*p != ']'); i++)
6838
0
              {
6839
0
                key[i]=(*p++);
6840
0
              }
6841
0
            if (']' != *p)
6842
0
              break;
6843
0
            key[i]='\0';
6844
6845
            /* Try to get the attribute from image */
6846
0
            attribute=GetImageAttribute(image,key);
6847
6848
            /* Try to get the attribute from image_info */
6849
0
            if (attribute == (const ImageAttribute *) NULL)
6850
0
              if (image_info != (const ImageInfo *) NULL)
6851
0
                attribute=GetImageInfoAttribute(image_info,image,key);
6852
6853
0
            if (attribute != (const ImageAttribute *) NULL)
6854
0
              {
6855
                /* Attributes may be larger than MaxTextExtent so make
6856
                   sure there is sufficient memory allocated. Make sure
6857
                   that there is at least MaxTextExtent left available
6858
                   after we have concatenated our part. */
6859
0
                offset=q-translated_text;
6860
0
                if ((size_t) (offset+attribute->length+1+MaxTextExtent) >= length)
6861
0
                  {
6862
0
                    length += (attribute->length+1+2*MaxTextExtent);
6863
0
                    MagickReallocMemory(char *,translated_text,length);
6864
0
                    if (translated_text == (char *) NULL)
6865
0
                      break;
6866
0
                    q=translated_text+offset;
6867
0
                  }
6868
0
                q+=(translate)(q,attribute->value,attribute->length+1+MaxTextExtent);
6869
0
              }
6870
0
            break;
6871
0
          }
6872
0
        case '#':
6873
0
          {
6874
            /* If 'ping' mode was used, then there may be no pixel cache! */
6875
0
            if (GetPixelCachePresent(image))
6876
0
              {
6877
0
                (void) SignatureImage(image);
6878
0
                attribute=GetImageAttribute(image,"signature");
6879
0
                if (attribute != (ImageAttribute *) NULL)
6880
0
                  q+=(translate)(q,attribute->value,MaxTextExtent);
6881
0
              }
6882
0
            else
6883
0
              {
6884
0
                *q++='%';
6885
0
                *q++=(*p);
6886
0
              }
6887
0
            break;
6888
0
          }
6889
0
        case '%':
6890
0
          {
6891
            /* Pass through literal % */
6892
0
            *q++=(*p);
6893
0
            break;
6894
0
          }
6895
0
        default:
6896
0
          {
6897
            /* Pass through unknown codes */
6898
0
            *q++='%';
6899
0
            *q++=(*p);
6900
0
            break;
6901
0
          }
6902
0
        }
6903
0
      if (*p == '\0')
6904
0
        break;
6905
0
    }
6906
0
  *q='\0';
6907
0
  if (text != (char *) formatted_text)
6908
0
    MagickFreeMemory(text);
6909
0
  return(translated_text);
6910
0
}