• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization
3   dedicated to making software imaging solutions freely available.
4 
5   You may not use this file except in compliance with the License.  You may
6   obtain a copy of the License at
7 
8     https://imagemagick.org/script/license.php
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 #ifndef MAGICK_GHOSTSCRIPT_BUFFER_PRIVATE_H
17 #define MAGICK_GHOSTSCRIPT_BUFFER_PRIVATE_H
18 
19 #include "coders/bytebuffer-private.h"
20 
21 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
GhostscriptDelegateMessage(void * handle,const char * message,int length)22 static int MagickDLLCall GhostscriptDelegateMessage(void *handle,
23   const char *message,int length)
24 {
25   char
26     **messages;
27 
28   ssize_t
29     offset;
30 
31   offset=0;
32   messages=(char **) handle;
33   if (*messages == (char *) NULL)
34     *messages=(char *) AcquireQuantumMemory(length+1,sizeof(char *));
35   else
36     {
37       offset=strlen(*messages);
38       *messages=(char *) ResizeQuantumMemory(*messages,offset+length+1,
39         sizeof(char *));
40     }
41   if (*messages == (char *) NULL)
42     return(0);
43   (void) memcpy(*messages+offset,message,length);
44   (*messages)[length+offset] ='\0';
45   return(length);
46 }
47 #endif
48 
InvokeGhostscriptDelegate(const MagickBooleanType verbose,const char * command,char * message,ExceptionInfo * exception)49 static MagickBooleanType InvokeGhostscriptDelegate(
50   const MagickBooleanType verbose,const char *command,char *message,
51   ExceptionInfo *exception)
52 {
53   int
54     status;
55 
56 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
57 #define SetArgsStart(command,args_start) \
58   if (args_start == (const char *) NULL) \
59     { \
60       if (*command != '"') \
61         args_start=strchr(command,' '); \
62       else \
63         { \
64           args_start=strchr(command+1,'"'); \
65           if (args_start != (const char *) NULL) \
66             args_start++; \
67         } \
68     }
69 
70 #define ExecuteGhostscriptCommand(command,status) \
71 { \
72   status=ExternalDelegateCommand(MagickFalse,verbose,command,message, \
73     exception); \
74   if (status == 0) \
75     return(MagickTrue); \
76   if (status < 0) \
77     return(MagickFalse); \
78   (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, \
79     "FailedToExecuteCommand","`%s' (%d)",command,status); \
80   return(MagickFalse); \
81 }
82 
83   char
84     **argv,
85     *errors;
86 
87   const char
88     *args_start = (const char *) NULL;
89 
90   const GhostInfo
91     *ghost_info;
92 
93   gs_main_instance
94     *interpreter;
95 
96   gsapi_revision_t
97     revision;
98 
99   int
100     argc,
101     code;
102 
103   register ssize_t
104     i;
105 
106 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
107   ghost_info=NTGhostscriptDLLVectors();
108 #else
109   GhostInfo
110     ghost_info_struct;
111 
112   ghost_info=(&ghost_info_struct);
113   (void) memset(&ghost_info_struct,0,sizeof(ghost_info_struct));
114   ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
115     gsapi_delete_instance;
116   ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
117   ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
118     gsapi_new_instance;
119   ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
120     gsapi_init_with_args;
121   ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
122     int *)) gsapi_run_string;
123   ghost_info_struct.set_stdio=(int (*)(gs_main_instance *,int (*)(void *,char *,
124     int),int (*)(void *,const char *,int),int (*)(void *, const char *, int)))
125     gsapi_set_stdio;
126   ghost_info_struct.revision=(int (*)(gsapi_revision_t *,int)) gsapi_revision;
127 #endif
128   if (ghost_info == (GhostInfo *) NULL)
129     ExecuteGhostscriptCommand(command,status);
130   if ((ghost_info->revision)(&revision,sizeof(revision)) != 0)
131     revision.revision=0;
132   if (verbose != MagickFalse)
133     {
134       (void) fprintf(stdout,"[ghostscript library %.2f]",(double)
135         revision.revision/100.0);
136       SetArgsStart(command,args_start);
137       (void) fputs(args_start,stdout);
138     }
139   interpreter=(gs_main_instance *) NULL;
140   errors=(char *) NULL;
141   status=(ghost_info->new_instance)(&interpreter,(void *) &errors);
142   if (status < 0)
143     ExecuteGhostscriptCommand(command,status);
144   code=0;
145   argv=StringToArgv(command,&argc);
146   if (argv == (char **) NULL)
147     {
148       (ghost_info->delete_instance)(interpreter);
149       return(MagickFalse);
150     }
151   (void) (ghost_info->set_stdio)(interpreter,(int (MagickDLLCall *)(void *,
152     char *,int)) NULL,GhostscriptDelegateMessage,GhostscriptDelegateMessage);
153   status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
154   if (status == 0)
155     status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
156       0,&code);
157   (ghost_info->exit)(interpreter);
158   (ghost_info->delete_instance)(interpreter);
159   for (i=0; i < (ssize_t) argc; i++)
160     argv[i]=DestroyString(argv[i]);
161   argv=(char **) RelinquishMagickMemory(argv);
162   if (status != 0)
163     {
164       SetArgsStart(command,args_start);
165       if (status == -101) /* quit */
166         (void) FormatLocaleString(message,MaxTextExtent,
167           "[ghostscript library %.2f]%s: %s",(double) revision.revision/100.0,
168           args_start,errors);
169       else
170         {
171           (void) ThrowMagickException(exception,GetMagickModule(),
172             DelegateError,"PostscriptDelegateFailed",
173             "`[ghostscript library %.2f]%s': %s",(double) revision.revision/
174             100.0,args_start,errors);
175           if (errors != (char *) NULL)
176             errors=DestroyString(errors);
177           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
178             "Ghostscript returns status %d, exit code %d",status,code);
179           return(MagickFalse);
180         }
181     }
182   if (errors != (char *) NULL)
183     errors=DestroyString(errors);
184   return(MagickTrue);
185 #else
186   status=ExternalDelegateCommand(MagickFalse,verbose,command,(char *) NULL,
187     exception);
188   return(status == 0 ? MagickTrue : MagickFalse);
189 #endif
190 }
191 
IsGhostscriptRendered(const char * path)192 static MagickBooleanType IsGhostscriptRendered(const char *path)
193 {
194   MagickBooleanType
195     status;
196 
197   struct stat
198     attributes;
199 
200   if ((path == (const char *) NULL) || (*path == '\0'))
201     return(MagickFalse);
202   status=GetPathAttributes(path,&attributes);
203   if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
204       (attributes.st_size > 0))
205     return(MagickTrue);
206   return(MagickFalse);
207 }
208 
ReadGhostScriptXMPProfile(MagickByteBuffer * buffer,StringInfo ** profile)209 static void ReadGhostScriptXMPProfile(MagickByteBuffer *buffer,
210   StringInfo **profile)
211 {
212 #define BeginXMPPacket  "?xpacket begin="
213 #define EndXMPPacket  "<?xpacket end="
214 
215   int
216     c;
217 
218   MagickBooleanType
219     found_end,
220     status;
221 
222   register char
223     *p;
224 
225   size_t
226     length;
227 
228   ssize_t
229     count;
230 
231   if (*profile != (StringInfo *) NULL)
232     return;
233   status=CompareMagickByteBuffer(buffer,BeginXMPPacket,strlen(BeginXMPPacket));
234   if (status == MagickFalse)
235     return;
236   length=8192;
237   *profile=AcquireStringInfo(length);
238   found_end=MagickFalse;
239   p=(char *) GetStringInfoDatum(*profile);
240   *p++='<';
241   count=1;
242   for (c=ReadMagickByteBuffer(buffer); c != EOF; c=ReadMagickByteBuffer(buffer))
243   {
244     if (count == (ssize_t) length)
245       {
246         length<<=1;
247         SetStringInfoLength(*profile,length);
248         p=(char *) GetStringInfoDatum(*profile)+count;
249       }
250     count++;
251     *p++=(char) c;
252     if (found_end == MagickFalse)
253       found_end=CompareMagickByteBuffer(buffer,EndXMPPacket,
254         strlen(EndXMPPacket));
255     else
256       {
257         if (c == (int) '>')
258           break;
259       }
260   }
261   SetStringInfoLength(*profile,(size_t) count);
262 }
263 
264 #endif
265