00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "magick/studio.h"
00043 #include "magick/property.h"
00044 #include "magick/blob.h"
00045 #include "magick/color.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/geometry.h"
00049 #include "magick/list.h"
00050 #include "magick/log.h"
00051 #include "magick/memory_.h"
00052 #include "magick/option.h"
00053 #include "magick/resource_.h"
00054 #include "magick/semaphore.h"
00055 #include "magick/signature-private.h"
00056 #include "magick/statistic.h"
00057 #include "magick/string_.h"
00058 #include "magick/token.h"
00059 #include "magick/utility.h"
00060 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
00061 #include <mach-o/dyld.h>
00062 #endif
00063
00064
00065
00066
00067 static const char
00068 Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00069
00070
00071
00072
00073 static int
00074 IsPathDirectory(const char *);
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
00100 {
00101 int
00102 file;
00103
00104 file=AcquireUniqueFileResource(path);
00105 if (file == -1)
00106 return(MagickFalse);
00107 file=close(file)-1;
00108 return(MagickTrue);
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 static inline size_t MagickMin(const size_t x,const size_t y)
00142 {
00143 if (x < y)
00144 return(x);
00145 return(y);
00146 }
00147
00148 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
00149 char *destination)
00150 {
00151 int
00152 destination_file,
00153 source_file;
00154
00155 size_t
00156 length,
00157 quantum;
00158
00159 ssize_t
00160 count;
00161
00162 struct stat
00163 attributes;
00164
00165 unsigned char
00166 *buffer;
00167
00168 assert(source != (const char *) NULL);
00169 assert(destination != (char *) NULL);
00170 #if defined(MAGICKCORE_HAVE_SYMLINK)
00171 (void) AcquireUniqueFilename(destination);
00172 (void) RelinquishUniqueFileResource(destination);
00173 if (*source == *DirectorySeparator)
00174 {
00175 if (symlink(source,destination) == 0)
00176 return(MagickTrue);
00177 }
00178 else
00179 {
00180 char
00181 path[MaxTextExtent];
00182
00183 *path='\0';
00184 if (getcwd(path,MaxTextExtent) == (char *) NULL)
00185 return(MagickFalse);
00186 (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00187 (void) ConcatenateMagickString(path,source,MaxTextExtent);
00188 if (symlink(path,destination) == 0)
00189 return(MagickTrue);
00190 }
00191 #endif
00192 destination_file=AcquireUniqueFileResource(destination);
00193 if (destination_file == -1)
00194 return(MagickFalse);
00195 source_file=open(source,O_RDONLY | O_BINARY);
00196 if (source_file == -1)
00197 {
00198 (void) close(destination_file);
00199 (void) RelinquishUniqueFileResource(destination);
00200 return(MagickFalse);
00201 }
00202 quantum=(size_t) MagickMaxBufferExtent;
00203 if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
00204 quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
00205 buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
00206 if (buffer == (unsigned char *) NULL)
00207 {
00208 (void) close(source_file);
00209 (void) close(destination_file);
00210 (void) RelinquishUniqueFileResource(destination);
00211 return(MagickFalse);
00212 }
00213 for (length=0; ; )
00214 {
00215 count=(ssize_t) read(source_file,buffer,quantum);
00216 if (count <= 0)
00217 break;
00218 length=(size_t) count;
00219 count=(ssize_t) write(destination_file,buffer,length);
00220 if ((size_t) count != length)
00221 {
00222 (void) close(destination_file);
00223 (void) close(source_file);
00224 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00225 (void) RelinquishUniqueFileResource(destination);
00226 return(MagickFalse);
00227 }
00228 }
00229 (void) close(destination_file);
00230 (void) close(source_file);
00231 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
00232 return(MagickTrue);
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 MagickExport void AppendImageFormat(const char *format,char *filename)
00263 {
00264 char
00265 root[MaxTextExtent];
00266
00267 assert(format != (char *) NULL);
00268 assert(filename != (char *) NULL);
00269 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00270 if ((*format == '\0') || (*filename == '\0'))
00271 return;
00272 if (LocaleCompare(filename,"-") == 0)
00273 {
00274 char
00275 message[MaxTextExtent];
00276
00277 (void) FormatMagickString(message,MaxTextExtent,"%s:%s",format,filename);
00278 (void) CopyMagickString(filename,message,MaxTextExtent);
00279 return;
00280 }
00281 GetPathComponent(filename,RootPath,root);
00282 (void) FormatMagickString(filename,MaxTextExtent,"%s.%s",root,format);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
00312 {
00313 int
00314 state;
00315
00316 register const char
00317 *p,
00318 *q;
00319
00320 register size_t
00321 i;
00322
00323 unsigned char
00324 *decode;
00325
00326 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00327 assert(source != (char *) NULL);
00328 assert(length != (size_t *) NULL);
00329 *length=0;
00330 decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
00331 3*sizeof(*decode));
00332 if (decode == (unsigned char *) NULL)
00333 return((unsigned char *) NULL);
00334 i=0;
00335 state=0;
00336 for (p=source; *p != '\0'; p++)
00337 {
00338 if (isspace((int) ((unsigned char) *p)) != 0)
00339 continue;
00340 if (*p == '=')
00341 break;
00342 q=strchr(Base64,*p);
00343 if (q == (char *) NULL)
00344 {
00345 decode=(unsigned char *) RelinquishMagickMemory(decode);
00346 return((unsigned char *) NULL);
00347 }
00348 switch (state)
00349 {
00350 case 0:
00351 {
00352 decode[i]=(q-Base64) << 2;
00353 state++;
00354 break;
00355 }
00356 case 1:
00357 {
00358 decode[i++]|=(q-Base64) >> 4;
00359 decode[i]=((q-Base64) & 0x0f) << 4;
00360 state++;
00361 break;
00362 }
00363 case 2:
00364 {
00365 decode[i++]|=(q-Base64) >> 2;
00366 decode[i]=((q-Base64) & 0x03) << 6;
00367 state++;
00368 break;
00369 }
00370 case 3:
00371 {
00372 decode[i++]|=(q-Base64);
00373 state=0;
00374 break;
00375 }
00376 }
00377 }
00378
00379
00380
00381 if (*p != '=')
00382 {
00383 if (state != 0)
00384 {
00385 decode=(unsigned char *) RelinquishMagickMemory(decode);
00386 return((unsigned char *) NULL);
00387 }
00388 }
00389 else
00390 {
00391 p++;
00392 switch (state)
00393 {
00394 case 0:
00395 case 1:
00396 {
00397
00398
00399
00400 decode=(unsigned char *) RelinquishMagickMemory(decode);
00401 return((unsigned char *) NULL);
00402 }
00403 case 2:
00404 {
00405 for ( ; *p != '\0'; p++)
00406 if (isspace((int) ((unsigned char) *p)) == 0)
00407 break;
00408 if (*p != '=')
00409 {
00410 decode=(unsigned char *) RelinquishMagickMemory(decode);
00411 return((unsigned char *) NULL);
00412 }
00413 p++;
00414 }
00415 case 3:
00416 {
00417 for ( ; *p != '\0'; p++)
00418 if (isspace((int) ((unsigned char) *p)) == 0)
00419 {
00420 decode=(unsigned char *) RelinquishMagickMemory(decode);
00421 return((unsigned char *) NULL);
00422 }
00423 if ((int) decode[i] != 0)
00424 {
00425 decode=(unsigned char *) RelinquishMagickMemory(decode);
00426 return((unsigned char *) NULL);
00427 }
00428 }
00429 }
00430 }
00431 *length=i;
00432 return(decode);
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 MagickExport char *Base64Encode(const unsigned char *blob,
00466 const size_t blob_length,size_t *encode_length)
00467 {
00468 char
00469 *encode;
00470
00471 register const unsigned char
00472 *p;
00473
00474 register size_t
00475 i;
00476
00477 size_t
00478 remainder;
00479
00480 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00481 assert(blob != (const unsigned char *) NULL);
00482 assert(blob_length != 0);
00483 assert(encode_length != (size_t *) NULL);
00484 *encode_length=0;
00485 encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
00486 if (encode == (char *) NULL)
00487 return((char *) NULL);
00488 i=0;
00489 for (p=blob; p < (blob+blob_length-2); p+=3)
00490 {
00491 encode[i++]=Base64[(int) (*p >> 2)];
00492 encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
00493 encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
00494 encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
00495 }
00496 remainder=blob_length % 3;
00497 if (remainder != 0)
00498 {
00499 long
00500 j;
00501
00502 unsigned char
00503 code[3];
00504
00505 code[0]='\0';
00506 code[1]='\0';
00507 code[2]='\0';
00508 for (j=0; j < (long) remainder; j++)
00509 code[j]=(*p++);
00510 encode[i++]=Base64[(int) (code[0] >> 2)];
00511 encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
00512 if (remainder == 1)
00513 encode[i++]='=';
00514 else
00515 encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
00516 encode[i++]='=';
00517 }
00518 *encode_length=i;
00519 encode[i++]='\0';
00520 return(encode);
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 MagickExport void ChopPathComponents(char *path,const unsigned long components)
00549 {
00550 register long
00551 i;
00552
00553 for (i=0; i < (long) components; i++)
00554 GetPathComponent(path,HeadPath,path);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 MagickExport void ExpandFilename(char *path)
00581 {
00582 char
00583 expand_path[MaxTextExtent];
00584
00585 if (path == (char *) NULL)
00586 return;
00587 if (*path != '~')
00588 return;
00589 (void) CopyMagickString(expand_path,path,MaxTextExtent);
00590 if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
00591 {
00592 char
00593 *home;
00594
00595
00596
00597
00598 (void) CopyMagickString(expand_path,".",MaxTextExtent);
00599 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00600 home=GetEnvironmentValue("HOME");
00601 if (home == (char *) NULL)
00602 home=GetEnvironmentValue("USERPROFILE");
00603 if (home != (char *) NULL)
00604 {
00605 (void) CopyMagickString(expand_path,home,MaxTextExtent);
00606 (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
00607 home=DestroyString(home);
00608 }
00609 }
00610 else
00611 {
00612 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
00613 char
00614 username[MaxTextExtent];
00615
00616 register char
00617 *p;
00618
00619 struct passwd
00620 *entry;
00621
00622
00623
00624
00625 (void) CopyMagickString(username,path+1,MaxTextExtent);
00626 p=strchr(username,'/');
00627 if (p != (char *) NULL)
00628 *p='\0';
00629 entry=getpwnam(username);
00630 if (entry == (struct passwd *) NULL)
00631 return;
00632 (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
00633 if (p != (char *) NULL)
00634 {
00635 (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
00636 (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
00637 }
00638 #endif
00639 }
00640 (void) CopyMagickString(path,expand_path,MaxTextExtent);
00641 }
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
00672 char ***arguments)
00673 {
00674 char
00675 *cwd,
00676 home_directory[MaxTextExtent],
00677 **vector;
00678
00679 long
00680 count,
00681 parameters;
00682
00683 register long
00684 i,
00685 j;
00686
00687 unsigned long
00688 number_files;
00689
00690
00691
00692
00693 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00694 assert(number_arguments != (int *) NULL);
00695 assert(arguments != (char ***) NULL);
00696 vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
00697 sizeof(*vector));
00698 if (vector == (char **) NULL)
00699 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00700
00701
00702
00703 *home_directory='\0';
00704 cwd=getcwd(home_directory,MaxTextExtent);
00705 count=0;
00706 for (i=0; i < (long) *number_arguments; i++)
00707 {
00708 char
00709 **filelist,
00710 filename[MaxTextExtent],
00711 magick[MaxTextExtent],
00712 *option,
00713 path[MaxTextExtent],
00714 subimage[MaxTextExtent];
00715
00716 MagickBooleanType
00717 destroy;
00718
00719 option=(*arguments)[i];
00720 *magick='\0';
00721 *path='\0';
00722 *filename='\0';
00723 *subimage='\0';
00724 vector[count++]=ConstantString(option);
00725 destroy=MagickTrue;
00726 parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
00727 if (parameters > 0)
00728 {
00729
00730
00731
00732 for (j=0; j < parameters; j++)
00733 {
00734 i++;
00735 if (i == (long) *number_arguments)
00736 break;
00737 option=(*arguments)[i];
00738 vector[count++]=ConstantString(option);
00739 }
00740 continue;
00741 }
00742 if ((*option == '"') || (*option == '\''))
00743 continue;
00744 GetPathComponent(option,TailPath,filename);
00745 GetPathComponent(option,MagickPath,magick);
00746 if ((LocaleCompare(magick,"CAPTION") == 0) ||
00747 (LocaleCompare(magick,"LABEL") == 0) ||
00748 (LocaleCompare(magick,"VID") == 0))
00749 continue;
00750 if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
00751 continue;
00752 if (*filename != '@')
00753 {
00754
00755
00756
00757 GetPathComponent(option,HeadPath,path);
00758 GetPathComponent(option,SubimagePath,subimage);
00759 ExpandFilename(path);
00760 filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
00761 &number_files);
00762 }
00763 else
00764 {
00765 char
00766 *files;
00767
00768 ExceptionInfo
00769 *exception;
00770
00771 int
00772 number_images;
00773
00774
00775
00776
00777 exception=AcquireExceptionInfo();
00778 files=FileToString(filename+1,~0,exception);
00779 exception=DestroyExceptionInfo(exception);
00780 if (files == (char *) NULL)
00781 continue;
00782 StripString(files);
00783 filelist=StringToArgv(files,&number_images);
00784 files=DestroyString(files);
00785 number_files=(unsigned long) number_images;
00786 if (filelist != (char **) NULL)
00787 {
00788 number_files--;
00789 for (j=0; j < (long) number_files; j++)
00790 filelist[j]=filelist[j+1];
00791 }
00792 }
00793 if (filelist == (char **) NULL)
00794 continue;
00795 for (j=0; j < (long) number_files; j++)
00796 if (IsPathDirectory(filelist[j]) <= 0)
00797 break;
00798 if (j == (long) number_files)
00799 {
00800 for (j=0; j < (long) number_files; j++)
00801 filelist[j]=DestroyString(filelist[j]);
00802 filelist=(char **) RelinquishMagickMemory(filelist);
00803 continue;
00804 }
00805
00806
00807
00808 vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
00809 count+number_files+1,sizeof(*vector));
00810 if (vector == (char **) NULL)
00811 return(MagickFalse);
00812 for (j=0; j < (long) number_files; j++)
00813 {
00814 (void) CopyMagickString(filename,path,MaxTextExtent);
00815 if (*path != '\0')
00816 (void) ConcatenateMagickString(filename,DirectorySeparator,
00817 MaxTextExtent);
00818 (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
00819 filelist[j]=DestroyString(filelist[j]);
00820 if (strlen(filename) >= MaxTextExtent)
00821 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00822 {
00823 char
00824 path[MaxTextExtent];
00825
00826 *path='\0';
00827 if (*magick != '\0')
00828 {
00829 (void) ConcatenateMagickString(path,magick,MaxTextExtent);
00830 (void) ConcatenateMagickString(path,":",MaxTextExtent);
00831 }
00832 (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00833 if (*subimage != '\0')
00834 {
00835 (void) ConcatenateMagickString(path,"[",MaxTextExtent);
00836 (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
00837 (void) ConcatenateMagickString(path,"]",MaxTextExtent);
00838 }
00839 if (strlen(path) >= MaxTextExtent)
00840 ThrowFatalException(OptionFatalError,"FilenameTruncated");
00841 if (destroy != MagickFalse)
00842 {
00843 count--;
00844 vector[count]=DestroyString(vector[count]);
00845 destroy=MagickFalse;
00846 }
00847 vector[count++]=ConstantString(path);
00848 }
00849 }
00850 filelist=(char **) RelinquishMagickMemory(filelist);
00851 }
00852 vector[count]=(char *) NULL;
00853 if (IsEventLogging() != MagickFalse)
00854 {
00855 char
00856 *command_line;
00857
00858 command_line=AcquireString(vector[0]);
00859 for (i=1; i < count; i++)
00860 {
00861 (void) ConcatenateString(&command_line," {");
00862 (void) ConcatenateString(&command_line,vector[i]);
00863 (void) ConcatenateString(&command_line,"}");
00864 }
00865 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
00866 "Command line: %s",command_line);
00867 command_line=DestroyString(command_line);
00868 }
00869 *number_arguments=(int) count;
00870 *arguments=vector;
00871 return(MagickTrue);
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
00900 {
00901 char
00902 *cwd;
00903
00904 *path='\0';
00905 cwd=getcwd(path,(unsigned long) extent);
00906 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK)
00907 {
00908 char
00909 link_path[MaxTextExtent],
00910 real_path[PATH_MAX+1];
00911
00912 ssize_t
00913 count;
00914
00915 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
00916 (long) getpid());
00917 count=readlink(link_path,real_path,PATH_MAX);
00918 if (count == -1)
00919 {
00920 (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
00921 (long) getpid());
00922 count=readlink(link_path,real_path,PATH_MAX);
00923 }
00924 if ((count > 0) && (count <= (ssize_t) PATH_MAX))
00925 {
00926 real_path[count]='\0';
00927 (void) CopyMagickString(path,real_path,extent);
00928 }
00929 }
00930 #endif
00931 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
00932 {
00933 char
00934 executable_path[PATH_MAX << 1],
00935 real_path[PATH_MAX+1];
00936
00937 uint32_t
00938 length;
00939
00940 length=sizeof(executable_path);
00941 if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
00942 (realpath(executable_path,real_path) != (char *) NULL))
00943 (void) CopyMagickString(path,real_path,extent);
00944 }
00945 #endif
00946 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
00947 {
00948 const char
00949 *execution_path;
00950
00951 execution_path=(const char *) getexecname();
00952 if (execution_path != (const char *) NULL)
00953 {
00954 if (*execution_path != *DirectorySeparator)
00955 (void) ConcatenateMagickString(path,DirectorySeparator,extent);
00956 (void) ConcatenateMagickString(path,execution_path,extent);
00957 }
00958 }
00959 #endif
00960 #if defined(__WINDOWS__)
00961 NTGetExecutionPath(path,extent);
00962 #endif
00963 return(IsPathAccessible(path));
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 #if defined(MAGICKCORE_HAVE__WFOPEN)
00992 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
00993 {
00994 register const unsigned char
00995 *p;
00996
00997 if (utf16 != (wchar_t *) NULL)
00998 {
00999 register wchar_t
01000 *q;
01001
01002 wchar_t
01003 c;
01004
01005
01006
01007
01008 q=utf16;
01009 for (p=utf8; *p != '\0'; p++)
01010 {
01011 if ((*p & 0x80) == 0)
01012 *q=(*p);
01013 else
01014 if ((*p & 0xE0) == 0xC0)
01015 {
01016 c=(*p);
01017 *q=(c & 0x1F) << 6;
01018 p++;
01019 if ((*p & 0xC0) != 0x80)
01020 return(0);
01021 *q|=(*p & 0x3F);
01022 }
01023 else
01024 if ((*p & 0xF0) == 0xE0)
01025 {
01026 c=(*p);
01027 *q=c << 12;
01028 p++;
01029 if ((*p & 0xC0) != 0x80)
01030 return(0);
01031 c=(*p);
01032 *q|=(c & 0x3F) << 6;
01033 p++;
01034 if ((*p & 0xC0) != 0x80)
01035 return(0);
01036 *q|=(*p & 0x3F);
01037 }
01038 else
01039 return(0);
01040 q++;
01041 }
01042 *q++='\0';
01043 return(q-utf16);
01044 }
01045
01046
01047
01048 for (p=utf8; *p != '\0'; p++)
01049 {
01050 if ((*p & 0x80) == 0)
01051 ;
01052 else
01053 if ((*p & 0xE0) == 0xC0)
01054 {
01055 p++;
01056 if ((*p & 0xC0) != 0x80)
01057 return(0);
01058 }
01059 else
01060 if ((*p & 0xF0) == 0xE0)
01061 {
01062 p++;
01063 if ((*p & 0xC0) != 0x80)
01064 return(0);
01065 p++;
01066 if ((*p & 0xC0) != 0x80)
01067 return(0);
01068 }
01069 else
01070 return(0);
01071 }
01072 return(p-utf8);
01073 }
01074
01075 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
01076 {
01077 size_t
01078 length;
01079
01080 wchar_t
01081 *utf16;
01082
01083 length=UTF8ToUTF16(source,(wchar_t *) NULL);
01084 if (length == 0)
01085 {
01086 register long
01087 i;
01088
01089
01090
01091
01092 length=strlen(source);
01093 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01094 if (utf16 == (wchar_t *) NULL)
01095 return((wchar_t *) NULL);
01096 for (i=0; i <= (long) length; i++)
01097 utf16[i]=source[i];
01098 return(utf16);
01099 }
01100 utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
01101 if (utf16 == (wchar_t *) NULL)
01102 return((wchar_t *) NULL);
01103 length=UTF8ToUTF16(source,utf16);
01104 return(utf16);
01105 }
01106 #endif
01107
01108 MagickExport MagickBooleanType GetPathAttributes(const char *path,
01109 void *attributes)
01110 {
01111 MagickBooleanType
01112 status;
01113
01114 if (path == (const char *) NULL)
01115 {
01116 errno=EINVAL;
01117 return(MagickFalse);
01118 }
01119 #if !defined(MAGICKCORE_HAVE__WSTAT)
01120 status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
01121 #else
01122 {
01123 wchar_t
01124 *unicode_path;
01125
01126 unicode_path=ConvertUTF8ToUTF16(path);
01127 if (unicode_path == (wchar_t *) NULL)
01128 return(MagickFalse);
01129 status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
01130 MagickFalse;
01131 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01132 }
01133 #endif
01134 return(status);
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165 MagickExport void GetPathComponent(const char *path,PathType type,
01166 char *component)
01167 {
01168 char
01169 magick[MaxTextExtent],
01170 *q,
01171 subimage[MaxTextExtent];
01172
01173 register char
01174 *p;
01175
01176 assert(path != (const char *) NULL);
01177 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
01178 assert(component != (char *) NULL);
01179 if (*path == '\0')
01180 {
01181 *component='\0';
01182 return;
01183 }
01184 (void) CopyMagickString(component,path,MaxTextExtent);
01185 *magick='\0';
01186 #if defined(__OS2__)
01187 if (path[1] != ":")
01188 #endif
01189 for (p=component; *p != '\0'; p++)
01190 if ((*p == ':') && (IsPathDirectory(path) < 0) &&
01191 (IsPathAccessible(path) == MagickFalse))
01192 {
01193
01194
01195
01196 (void) CopyMagickString(magick,component,(size_t) (p-component+1));
01197 if (IsMagickConflict(magick) != MagickFalse)
01198 *magick='\0';
01199 else
01200 for (q=component; *q != '\0'; q++)
01201 *q=(*++p);
01202 break;
01203 }
01204 *subimage='\0';
01205 p=component;
01206 if (*p != '\0')
01207 p=component+strlen(component)-1;
01208 if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
01209 (IsPathAccessible(path) == MagickFalse))
01210 {
01211
01212
01213
01214 for (q=p-1; q > component; q--)
01215 if (*q == '[')
01216 break;
01217 if (*q == '[')
01218 {
01219 (void) CopyMagickString(subimage,q+1,MaxTextExtent);
01220 subimage[p-q-1]='\0';
01221 if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
01222 (IsGeometry(subimage) == MagickFalse))
01223 *subimage='\0';
01224 else
01225 *q='\0';
01226 }
01227 }
01228 p=component;
01229 if (*p != '\0')
01230 for (p=component+strlen(component)-1; p > component; p--)
01231 if (IsBasenameSeparator(*p) != MagickFalse)
01232 break;
01233 switch (type)
01234 {
01235 case MagickPath:
01236 {
01237 (void) CopyMagickString(component,magick,MaxTextExtent);
01238 break;
01239 }
01240 case RootPath:
01241 {
01242 for (p=component+(strlen(component)-1); p > component; p--)
01243 {
01244 if (IsBasenameSeparator(*p) != MagickFalse)
01245 break;
01246 if (*p == '.')
01247 break;
01248 }
01249 if (*p == '.')
01250 *p='\0';
01251 break;
01252 }
01253 case HeadPath:
01254 {
01255 *p='\0';
01256 break;
01257 }
01258 case TailPath:
01259 {
01260 if (IsBasenameSeparator(*p) != MagickFalse)
01261 (void) CopyMagickMemory((unsigned char *) component,
01262 (const unsigned char *) (p+1),strlen(p+1)+1);
01263 break;
01264 }
01265 case BasePath:
01266 {
01267 if (IsBasenameSeparator(*p) != MagickFalse)
01268 (void) CopyMagickString(component,p+1,MaxTextExtent);
01269 for (p=component+(strlen(component)-1); p > component; p--)
01270 if (*p == '.')
01271 {
01272 *p='\0';
01273 break;
01274 }
01275 break;
01276 }
01277 case ExtensionPath:
01278 {
01279 if (IsBasenameSeparator(*p) != MagickFalse)
01280 (void) CopyMagickString(component,p+1,MaxTextExtent);
01281 p=component;
01282 if (*p != '\0')
01283 for (p=component+strlen(component)-1; p > component; p--)
01284 if (*p == '.')
01285 break;
01286 *component='\0';
01287 if (*p == '.')
01288 (void) CopyMagickString(component,p+1,MaxTextExtent);
01289 break;
01290 }
01291 case SubimagePath:
01292 {
01293 (void) CopyMagickString(component,subimage,MaxTextExtent);
01294 break;
01295 }
01296 case CanonicalPath:
01297 case UndefinedPath:
01298 break;
01299 }
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327 MagickExport char **GetPathComponents(const char *path,
01328 unsigned long *number_components)
01329 {
01330 char
01331 **components;
01332
01333 register const char
01334 *p,
01335 *q;
01336
01337 register long
01338 i;
01339
01340 if (path == (char *) NULL)
01341 return((char **) NULL);
01342 *number_components=1;
01343 for (p=path; *p != '\0'; p++)
01344 if (IsBasenameSeparator(*p))
01345 (*number_components)++;
01346 components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
01347 sizeof(*components));
01348 if (components == (char **) NULL)
01349 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01350 p=path;
01351 for (i=0; i < (long) *number_components; i++)
01352 {
01353 for (q=p; *q != '\0'; q++)
01354 if (IsBasenameSeparator(*q))
01355 break;
01356 components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
01357 sizeof(*components));
01358 if (components[i] == (char *) NULL)
01359 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01360 (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
01361 p=q+1;
01362 }
01363 components[i]=(char *) NULL;
01364 return(components);
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 MagickExport MagickBooleanType IsPathAccessible(const char *path)
01391 {
01392 MagickBooleanType
01393 status;
01394
01395 struct stat
01396 attributes;
01397
01398 if ((path == (const char *) NULL) || (*path == '\0'))
01399 return(MagickFalse);
01400 status=GetPathAttributes(path,&attributes);
01401 if (status == MagickFalse)
01402 return(status);
01403 if (S_ISREG(attributes.st_mode) == 0)
01404 return(MagickFalse);
01405 if (access(path,F_OK) != 0)
01406 return(MagickFalse);
01407 return(MagickTrue);
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 static int IsPathDirectory(const char *path)
01434 {
01435 MagickBooleanType
01436 status;
01437
01438 struct stat
01439 attributes;
01440
01441 if ((path == (const char *) NULL) || (*path == '\0'))
01442 return(MagickFalse);
01443 status=GetPathAttributes(path,&attributes);
01444 if (status == MagickFalse)
01445 return(-1);
01446 if (S_ISDIR(attributes.st_mode) == 0)
01447 return(0);
01448 return(1);
01449 }
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 MagickExport MagickBooleanType IsMagickTrue(const char *value)
01478 {
01479 if (value == (const char *) NULL)
01480 return(MagickFalse);
01481 if (LocaleCompare(value,"true") == 0)
01482 return(MagickTrue);
01483 if (LocaleCompare(value,"on") == 0)
01484 return(MagickTrue);
01485 if (LocaleCompare(value,"yes") == 0)
01486 return(MagickTrue);
01487 if (LocaleCompare(value,"1") == 0)
01488 return(MagickTrue);
01489 return(MagickFalse);
01490 }
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 #if defined(__cplusplus) || defined(c_plusplus)
01528 extern "C" {
01529 #endif
01530
01531 static int FileCompare(const void *x,const void *y)
01532 {
01533 register const char
01534 **p,
01535 **q;
01536
01537 p=(const char **) x;
01538 q=(const char **) y;
01539 return(LocaleCompare(*p,*q));
01540 }
01541
01542 #if defined(__cplusplus) || defined(c_plusplus)
01543 }
01544 #endif
01545
01546 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
01547 struct dirent **result)
01548 {
01549 #if defined(MAGICKCORE_HAVE_READDIR_R)
01550 return(readdir_r(directory,entry,result));
01551 #else
01552 (void) entry;
01553 errno=0;
01554 *result=readdir(directory);
01555 return(errno);
01556 #endif
01557 }
01558
01559 MagickExport char **ListFiles(const char *directory,const char *pattern,
01560 unsigned long *number_entries)
01561 {
01562 char
01563 **filelist;
01564
01565 DIR
01566 *current_directory;
01567
01568 struct dirent
01569 *buffer,
01570 *entry;
01571
01572 unsigned long
01573 max_entries;
01574
01575
01576
01577
01578 assert(directory != (const char *) NULL);
01579 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
01580 assert(pattern != (const char *) NULL);
01581 assert(number_entries != (unsigned long *) NULL);
01582 *number_entries=0;
01583 current_directory=opendir(directory);
01584 if (current_directory == (DIR *) NULL)
01585 return((char **) NULL);
01586
01587
01588
01589 max_entries=2048;
01590 filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
01591 sizeof(*filelist));
01592 if (filelist == (char **) NULL)
01593 {
01594 (void) closedir(current_directory);
01595 return((char **) NULL);
01596 }
01597
01598
01599
01600 buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
01601 if (buffer == (struct dirent *) NULL)
01602 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01603 while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
01604 (entry != (struct dirent *) NULL))
01605 {
01606 if (*entry->d_name == '.')
01607 continue;
01608 if ((IsPathDirectory(entry->d_name) > 0) ||
01609 #if defined(__WINDOWS__)
01610 (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
01611 #else
01612 (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
01613 #endif
01614 {
01615 if (*number_entries >= max_entries)
01616 {
01617
01618
01619
01620 max_entries<<=1;
01621 filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
01622 max_entries,sizeof(*filelist));
01623 if (filelist == (char **) NULL)
01624 break;
01625 }
01626 #if defined(vms)
01627 {
01628 register char
01629 *p;
01630
01631 p=strchr(entry->d_name,';');
01632 if (p)
01633 *p='\0';
01634 if (*number_entries > 0)
01635 if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
01636 continue;
01637 }
01638 #endif
01639 filelist[*number_entries]=(char *) AcquireString(entry->d_name);
01640 if (IsPathDirectory(entry->d_name) > 0)
01641 (void) ConcatenateMagickString(filelist[*number_entries],
01642 DirectorySeparator,MaxTextExtent);
01643 (*number_entries)++;
01644 }
01645 }
01646 buffer=(struct dirent *) RelinquishMagickMemory(buffer);
01647 (void) closedir(current_directory);
01648 if (filelist == (char **) NULL)
01649 return((char **) NULL);
01650
01651
01652
01653 qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
01654 FileCompare);
01655 return(filelist);
01656 }
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 MagickExport unsigned long MultilineCensus(const char *label)
01683 {
01684 unsigned long
01685 number_lines;
01686
01687
01688
01689
01690 if (label == (char *) NULL)
01691 return(0);
01692 for (number_lines=1; *label != '\0'; label++)
01693 if (*label == '\n')
01694 number_lines++;
01695 return(number_lines);
01696 }
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
01724 {
01725 FILE
01726 *file;
01727
01728 if ((path == (const char *) NULL) || (mode == (const char *) NULL))
01729 {
01730 errno=EINVAL;
01731 return((FILE *) NULL);
01732 }
01733 file=(FILE *) NULL;
01734 #if defined(MAGICKCORE_HAVE__WFOPEN)
01735 {
01736 wchar_t
01737 *unicode_mode,
01738 *unicode_path;
01739
01740 unicode_path=ConvertUTF8ToUTF16(path);
01741 if (unicode_path == (wchar_t *) NULL)
01742 return((FILE *) NULL);
01743 unicode_mode=ConvertUTF8ToUTF16(mode);
01744 if (unicode_mode == (wchar_t *) NULL)
01745 {
01746 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01747 return((FILE *) NULL);
01748 }
01749 file=_wfopen(unicode_path,unicode_mode);
01750 unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
01751 unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
01752 }
01753 #endif
01754 if (file == (FILE *) NULL)
01755 file=fopen(path,mode);
01756 return(file);
01757 }
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 MagickExport int SystemCommand(const MagickBooleanType verbose,
01786 const char *command)
01787 {
01788 int
01789 status;
01790
01791 if (verbose != MagickFalse)
01792 {
01793 (void) fprintf(stderr,"%s\n",command);
01794 (void) fflush(stderr);
01795 }
01796 status=(-1);
01797 #if defined(MAGICKCORE_POSIX_SUPPORT)
01798 #if !defined(MAGICKCORE_HAVE_EXECVP)
01799 status=system(command);
01800 #else
01801 if (strspn(command,"&;<>|") == 0)
01802 status=system(command);
01803 else
01804 {
01805 char
01806 **arguments;
01807
01808 int
01809 number_arguments;
01810
01811 arguments=StringToArgv(command,&number_arguments);
01812 if (arguments == (char **) NULL)
01813 status=system(command);
01814 else
01815 {
01816 pid_t
01817 child_pid;
01818
01819 register long
01820 i;
01821
01822
01823
01824
01825 child_pid=fork();
01826 if (child_pid == (pid_t) -1)
01827 status=system(command);
01828 else
01829 if (child_pid == 0)
01830 {
01831 status=execvp(arguments[1],arguments+1);
01832 _exit(1);
01833 }
01834 else
01835 {
01836 int
01837 child_status;
01838
01839 pid_t
01840 pid;
01841
01842 child_status=0;
01843 pid=waitpid(child_pid,&child_status,0);
01844 if (pid == -1)
01845 status=(-1);
01846 else
01847 {
01848 if (WIFEXITED(child_status) != 0)
01849 status=WEXITSTATUS(child_status);
01850 else
01851 if (WIFSIGNALED(child_status))
01852 status=(-1);
01853 }
01854 }
01855 for (i=0; i < number_arguments; i++)
01856 arguments[i]=DestroyString(arguments[i]);
01857 arguments=(char **) RelinquishMagickMemory(arguments);
01858 }
01859 }
01860 #endif
01861 #elif defined(__WINDOWS__)
01862 status=NTSystemCommand(command);
01863 #elif defined(macintosh)
01864 status=MACSystemCommand(command);
01865 #elif defined(vms)
01866 status=system(command);
01867 #else
01868 # error No suitable system() method.
01869 #endif
01870 if (status < 0)
01871 {
01872 char
01873 *message;
01874
01875 ExceptionInfo
01876 *exception;
01877
01878 exception=AcquireExceptionInfo();
01879 message=GetExceptionMessage(errno);
01880 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
01881 "`%s': %s",command,message);
01882 message=DestroyString(message);
01883 CatchException(exception);
01884 exception=DestroyExceptionInfo(exception);
01885 }
01886 return(status);
01887 }