/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + I n v o k e P o s t s c r i p t D e l e g a t e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % InvokePostscriptDelegate() executes the postscript interpreter with the % specified command. % % The format of the InvokePostscriptDelegate method is: % % MagickPassFail InvokePostscriptDelegate(const unsigned int verbose, % const char *command, ExceptionInfo *exception) % % A description of each parameter follows: % % o status: Method InvokePostscriptDelegate returns MagickPass if the command % is successfully executed, otherwise MagickFail. % % o verbose: A value other than zero displays the command prior to % executing it. % % o command: The address of a character string containing the command to % execute. The command is formulated through direct FormatString() % substitutions rather than using TranslateText. % % */ MagickExport MagickPassFail InvokePostscriptDelegate(const unsigned int verbose, const char *command,ExceptionInfo *exception) { register long i; char **argv; int argc; int status; #if defined(HasGS) || defined(MSWINDOWS) gs_main_instance *interpreter; int pexit_code; #if defined(MSWINDOWS) const GhostscriptVectors *gs_func; gs_func=NTGhostscriptDLLVectors(); #elif defined(HasGS) GhostscriptVectors gs_func_struct; const GhostscriptVectors *gs_func; gs_func=(&gs_func_struct); gs_func_struct.exit=gsapi_exit; gs_func_struct.init_with_args=gsapi_init_with_args; gs_func_struct.new_instance=gsapi_new_instance; gs_func_struct.run_string=gsapi_run_string; gs_func_struct.delete_instance=gsapi_delete_instance; #endif if (gs_func != (GhostscriptVectors *) NULL) { /* Allocate an interpreter. */ interpreter = (gs_main_instance *) NULL; status=(gs_func->new_instance)(&interpreter,(void *) NULL); if (status < 0) { ThrowException(exception,DelegateError, FailedToAllocateGhostscriptInterpreter,command); return(MagickFail); } /* Initialize interpreter with argument list. */ argv=StringToArgv(command,&argc); if (argv == (char **) NULL) { ThrowException(exception,DelegateError,FailedToAllocateArgumentList, command); return(MagickFail); } if (verbose) { char buffer[MaxTextExtent]; #if defined(MSWINDOWS) (void) NTGhostscriptDLL(buffer,sizeof(buffer)); #else (void) strlcpy(buffer,"[ghostscript library]",sizeof(buffer)); #endif (void) fputs(buffer,stderr); for (i=2 ; i < argc ; i++) (void) fprintf(stderr," \"%s\"",argv[i]); (void) fflush(stderr); } status=(gs_func->init_with_args)(interpreter,argc-1,argv+1); if (status == 0) { status=(gs_func->run_string) (interpreter,"systemdict /start get exec\n",0,&pexit_code); if ((status == 0) || (status <= -100)) { char reason[MaxTextExtent]; FormatString(reason,"Ghostscript returns status %d, exit code %d", status,pexit_code); (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s",reason); ThrowException(exception,DelegateError,PostscriptDelegateFailed,command); } } /* Exit interpreter. */ (gs_func->exit)(interpreter); /* Deallocate interpreter. */ (gs_func->delete_instance)(interpreter); for (i=0; i < argc; i++) MagickFreeMemory(argv[i]); MagickFreeMemory(argv); if ((status == 0) || (status <= -100)) return(MagickFail); return(MagickPass); } #endif /* defined(HasGS) || defined(MSWINDOWS) */ status=MagickFail; #if defined(POSIX) { argv = StringToArgv(command,&argc); if (argv == (char **) NULL) { ThrowException(exception,DelegateError, FailedToAllocateArgumentList, command); } else { if (MagickSpawnVP(verbose,argv[1],argv+1) == 0) status=MagickPass; for (i=0; i < argc; i++) MagickFreeMemory(argv[i]); MagickFreeMemory(argv); } } #else if (SystemCommand(verbose,command) == 0) status=MagickPass; #endif return status; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d X P S I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadXPSImage() reads a Printer Control Language image file and returns it. % It allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadXPSImage method is: % % Image *ReadXPSImage(const ImageInfo *image_info,ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadXPSImage(const ImageInfo *image_info,ExceptionInfo *exception) { #define CropBox "CropBox" #define DeviceCMYK "DeviceCMYK" #define MediaBox "MediaBox" #define RenderXPSText " Rendering XPS... " char command[MaxTextExtent], density[MaxTextExtent], filename[MaxTextExtent], geometry[MaxTextExtent], options[MaxTextExtent], input_filename[MaxTextExtent]; const DelegateInfo *delegate_info; Image *image, *next_image; ImageInfo *read_info; MagickBooleanType cmyk, status; PointInfo delta; RectangleInfo bounding_box, page; register char *p; register ssize_t c; SegmentInfo bounds; size_t height, width; ssize_t count; assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); /* Open image file. */ image=AcquireImage(image_info); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } status=AcquireUniqueSymbolicLink(image_info->filename,input_filename); if (status == MagickFalse) { ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile", image_info->filename); image=DestroyImageList(image); return((Image *) NULL); } /* Set the page density. */ delta.x=DefaultResolution; delta.y=DefaultResolution; if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0)) { GeometryInfo geometry_info; MagickStatusType flags; flags=ParseGeometry(PSDensityGeometry,&geometry_info); image->x_resolution=geometry_info.rho; image->y_resolution=geometry_info.sigma; if ((flags & SigmaValue) == 0) image->y_resolution=image->x_resolution; } (void) FormatLocaleString(density,MaxTextExtent,"%gx%g", image->x_resolution,image->y_resolution); /* Determine page geometry from the XPS media box. */ cmyk=image->colorspace == CMYKColorspace ? MagickTrue : MagickFalse; count=0; (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box)); (void) ResetMagickMemory(&bounds,0,sizeof(bounds)); (void) ResetMagickMemory(&page,0,sizeof(page)); (void) ResetMagickMemory(command,0,sizeof(command)); p=command; for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image)) { if (image_info->page != (char *) NULL) continue; /* Note XPS elements. */ *p++=(char) c; if ((c != (int) '/') && (c != '\n') && ((size_t) (p-command) < (MaxTextExtent-1))) continue; *p='\0'; p=command; /* Is this a CMYK document? */ if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0) cmyk=MagickTrue; if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0) { /* Note region defined by crop box. */ count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf", &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); if (count != 4) count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf", &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); } if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0) { /* Note region defined by media box. */ count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf", &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); if (count != 4) count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf", &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2); } if (count != 4) continue; /* Set XPS render geometry. */ width=(size_t) (floor(bounds.x2+0.5)-ceil(bounds.x1-0.5)); height=(size_t) (floor(bounds.y2+0.5)-ceil(bounds.y1-0.5)); if (width > page.width) page.width=width; if (height > page.height) page.height=height; } (void) CloseBlob(image); /* Render XPS with the GhostXPS delegate. */ if ((page.width == 0) || (page.height == 0)) (void) ParseAbsoluteGeometry(PSPageGeometry,&page); if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g",(double) page.width,(double) page.height); if (image_info->monochrome != MagickFalse) delegate_info=GetDelegateInfo("xps:mono",(char *) NULL,exception); else if (cmyk != MagickFalse) delegate_info=GetDelegateInfo("xps:cmyk",(char *) NULL,exception); else delegate_info=GetDelegateInfo("xps:color",(char *) NULL,exception); if (delegate_info == (const DelegateInfo *) NULL) return((Image *) NULL); *options='\0'; if ((page.width == 0) || (page.height == 0)) (void) ParseAbsoluteGeometry(PSPageGeometry,&page); if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); page.width=(size_t) floor(page.width*image->y_resolution/delta.x+0.5); page.height=(size_t) floor(page.height*image->y_resolution/delta.y+0.5); (void) FormatLocaleString(options,MaxTextExtent,"-g%.20gx%.20g ",(double) page.width,(double) page.height); image=DestroyImage(image); read_info=CloneImageInfo(image_info); *read_info->magick='\0'; if (read_info->number_scenes != 0) { if (read_info->number_scenes != 1) (void) FormatLocaleString(options,MaxTextExtent,"-dLastPage=%.20g", (double) (read_info->scene+read_info->number_scenes)); else (void) FormatLocaleString(options,MaxTextExtent, "-dFirstPage=%.20g -dLastPage=%.20g",(double) read_info->scene+1, (double) (read_info->scene+read_info->number_scenes)); read_info->number_scenes=0; if (read_info->scenes != (char *) NULL) *read_info->scenes='\0'; } if (read_info->authenticate != (char *) NULL) (void) FormatLocaleString(options+strlen(options),MaxTextExtent, " -sXPSPassword=%s",read_info->authenticate); (void) CopyMagickString(filename,read_info->filename,MaxTextExtent); (void) AcquireUniqueFilename(read_info->filename); (void) FormatLocaleString(command,MaxTextExtent, GetDelegateCommands(delegate_info), read_info->antialias != MagickFalse ? 4 : 1, read_info->antialias != MagickFalse ? 4 : 1,density,options, read_info->filename,input_filename); status=SystemCommand(MagickFalse,read_info->verbose,command,exception) != 0 ? MagickTrue : MagickFalse; image=ReadImage(read_info,exception); (void) RelinquishUniqueFileResource(read_info->filename); (void) RelinquishUniqueFileResource(input_filename); read_info=DestroyImageInfo(read_info); if (image == (Image *) NULL) ThrowReaderException(DelegateError,"XPSDelegateFailed"); if (LocaleCompare(image->magick,"BMP") == 0) { Image *cmyk_image; cmyk_image=ConsolidateCMYKImages(image,&image->exception); if (cmyk_image != (Image *) NULL) { image=DestroyImageList(image); image=cmyk_image; } } do { (void) CopyMagickString(image->filename,filename,MaxTextExtent); image->page=page; next_image=SyncNextImageInList(image); if (next_image != (Image *) NULL) image=next_image; } while (next_image != (Image *) NULL); return(GetFirstImageInList(image)); }
MagickExport unsigned int InvokeDelegate(ImageInfo *image_info,Image *image, const char *decode,const char *encode,ExceptionInfo *exception) { char *command, **commands, filename[MaxTextExtent]; const DelegateInfo *delegate_info; register long i; unsigned int status, temporary_image_filename; /* Get delegate. */ assert(image_info != (ImageInfo *) NULL); assert(image_info->signature == MagickSignature); assert(image != (Image *) NULL); assert(image->signature == MagickSignature); temporary_image_filename=(*image->filename == '\0'); if (temporary_image_filename) { /* Allocate a temporary filename if image is unnamed. */ if(!AcquireTemporaryFileName(image->filename)) { (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image->filename); return(False); } } (void) strlcpy(filename,image->filename,MaxTextExtent); delegate_info=GetDelegateInfo(decode,encode,exception); if (delegate_info == (DelegateInfo *) NULL) { if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) ThrowException(exception,DelegateError,NoTagFound, decode ? decode : encode); return(False); } if (*image_info->filename == '\0') { /* ReadImage will normally have already set image_info->filename to the name of a temporary file. If not, then assign one. Setting image_info->temporary to True indicates that there is a temporary file to be removed later. */ if(!AcquireTemporaryFileName(image_info->filename)) { if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->filename); return(False); } image_info->temporary=True; } if (delegate_info->mode != 0) if ((decode && (delegate_info->encode != (char *) NULL)) || (encode && (delegate_info->decode != (char *) NULL))) { char decode_filename[MaxTextExtent], *magick; ImageInfo *clone_info; register Image *p; /* Delegate requires a particular image format. */ if (!AcquireTemporaryFileName(image_info->unique)) { if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->unique); return(False); } if (!AcquireTemporaryFileName(image_info->zero)) { if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) LiberateTemporaryFile(image_info->unique); (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->zero); return(False); } /* Expand sprintf-style codes in delegate command to command string */ magick=TranslateText(image_info,image,decode != (char *) NULL ? delegate_info->encode : delegate_info->decode); if (magick == (char *) NULL) { (void) LiberateTemporaryFile(image_info->unique); (void) LiberateTemporaryFile(image_info->zero); if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) ThrowException(exception,DelegateError,DelegateFailed, decode ? decode : encode); return(False); } LocaleUpper(magick); clone_info=CloneImageInfo(image_info); (void) strlcpy((char *) clone_info->magick,magick,MaxTextExtent); (void) strlcpy(image->magick,magick,MaxTextExtent); MagickFreeMemory(magick); (void) strlcpy(decode_filename,image->filename,MaxTextExtent); FormatString(clone_info->filename,"%.1024s:",delegate_info->decode); (void) SetImageInfo(clone_info,True,exception); (void) strlcpy(clone_info->filename,image_info->filename, MaxTextExtent); for (p=image; p != (Image *) NULL; p=p->next) { FormatString(p->filename,"%.1024s:%.1024s",delegate_info->decode, decode_filename); status=WriteImage(clone_info,p); if (status == False) { (void) LiberateTemporaryFile(image_info->unique); (void) LiberateTemporaryFile(image_info->zero); if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); DestroyImageInfo(clone_info); (void) ThrowException(exception,DelegateError,DelegateFailed, decode ? decode : encode); return(False); } if (clone_info->adjoin) break; } (void) LiberateTemporaryFile(image_info->unique); (void) LiberateTemporaryFile(image_info->zero); DestroyImageInfo(clone_info); } /* Invoke delegate. */ (void) strlcpy(image->filename,filename,MaxTextExtent); commands=StringToList(delegate_info->commands); if (commands == (char **) NULL) { if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); (void) ThrowException(exception,ResourceLimitError,MemoryAllocationFailed,decode ? decode : encode); return(False); } command=(char *) NULL; status=True; /* For each delegate command ... */ for (i=0; commands[i] != (char *) NULL; i++) { status=True; /* Allocate convenience temporary files */ if (!AcquireTemporaryFileName(image_info->unique)) { (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->unique); status=False; goto error_exit; } if (!AcquireTemporaryFileName(image_info->zero)) { (void) ThrowException(exception,FileOpenError,UnableToCreateTemporaryFile,image_info->zero); (void) LiberateTemporaryFile(image_info->unique); status=False; goto error_exit; } #if defined(POSIX) { MagickBool needs_shell; /* Check to see if command template must be executed via shell due to using constructs requiring multiple processes or I/O redirection. */ needs_shell = MagickFalse; { char * p; p = commands[i]; for (p = commands[i]; *p; p++) { if (('&' == *p) || (';' == *p) || ('<' == *p) || ('>' == *p) || ('|' == *p)) { needs_shell = MagickTrue; break; } } } if (MagickFalse == needs_shell) { int arg_count, j; char **arg_array; /* Convert command template into an argument array. Translate each argument array element individually in order to absolutely avoid any possibility that the number of arguments may be altered due to substituted data. */ arg_array = StringToArgv(commands[i],&arg_count); for (j = 0; arg_array[j] != (const char*) NULL; j++) { if (strchr(arg_array[j], '%') != (const char*) NULL) { char *expanded = TranslateText(image_info,image,arg_array[j]); if (expanded != (char *) NULL) { MagickFreeMemory(arg_array[j]); arg_array[j] = expanded; } } } /* Execute delegate using our secure "spawn" facility. */ status = MagickSpawnVP(image_info->verbose,arg_array[1],arg_array+1); } else { /* Expand sprintf-style codes in delegate command to command string, escaping replacement text appropriately */ command=TranslateTextEx(image_info,image,commands[i],UnixShellTextEscape); if (command == (char *) NULL) break; /* Execute delegate using command shell. */ status=SystemCommand(image_info->verbose,command); } } #else { /* Expand sprintf-style codes in delegate command to command string */ command=TranslateText(image_info,image,commands[i]); if (command == (char *) NULL) break; /* Execute delegate using command shell. */ status=SystemCommand(image_info->verbose,command); } #endif MagickFreeMemory(command); /* Liberate convenience temporary files */ (void) LiberateTemporaryFile(image_info->unique); (void) LiberateTemporaryFile(image_info->zero); if (status != False) { (void) ThrowException(exception,DelegateError,DelegateFailed, commands[i]); goto error_exit; } MagickFreeMemory(commands[i]); } /* Free resources. */ error_exit: if (temporary_image_filename) (void) LiberateTemporaryFile(image->filename); for ( ; commands[i] != (char *) NULL; i++) MagickFreeMemory(commands[i]); MagickFreeMemory(commands); return(status != False); }