• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   Copyright 1999-2021 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((size_t) length+1,sizeof(char *));
35   else
36     {
37       offset=(ssize_t) strlen(*messages);
38       *messages=(char *) ResizeQuantumMemory(*messages,(size_t) (offset+length+
39         1),sizeof(char *));
40     }
41   if (*messages == (char *) NULL)
42     return(0);
43   (void) memcpy(*messages+offset,message,(size_t) length);
44   (*messages)[length+offset] ='\0';
45   return(length);
46 }
47 
GhostscriptVersion(const GhostInfo * ghost_info)48 static double GhostscriptVersion(const GhostInfo *ghost_info)
49 {
50   gsapi_revision_t
51     revision;
52 
53   if ((ghost_info->revision)(&revision,(int) sizeof(revision)) != 0)
54     return(0.0);
55   if (revision.revision > 1000)
56     return(revision.revision/1000.0);
57   return(revision.revision/100.0);
58 }
59 #endif
60 
ExecuteGhostscriptCommand(const MagickBooleanType verbose,const char * command,char * message,ExceptionInfo * exception)61 static inline MagickBooleanType ExecuteGhostscriptCommand(
62   const MagickBooleanType verbose,const char *command,char *message,
63   ExceptionInfo *exception)
64 {
65   int
66     status;
67 
68   status=ExternalDelegateCommand(MagickFalse,verbose,command,message,
69     exception);
70   if (status == 0)
71     return(MagickTrue);
72   if (status < 0)
73     return(MagickFalse);
74   (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
75     "FailedToExecuteCommand","`%s' (%d)",command,status);
76   return(MagickFalse);
77 }
78 
InvokeGhostscriptDelegate(const MagickBooleanType verbose,const char * command,char * message,ExceptionInfo * exception)79 static inline MagickBooleanType InvokeGhostscriptDelegate(
80   const MagickBooleanType verbose,const char *command,char *message,
81   ExceptionInfo *exception)
82 {
83   int
84     status;
85 
86 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
87 #define SetArgsStart(command,args_start) \
88   if (args_start == (const char *) NULL) \
89     { \
90       if (*command != '"') \
91         args_start=strchr(command,' '); \
92       else \
93         { \
94           args_start=strchr(command+1,'"'); \
95           if (args_start != (const char *) NULL) \
96             args_start++; \
97         } \
98     }
99 
100   char
101     **argv,
102     *errors;
103 
104   const char
105     *args_start = (const char *) NULL;
106 
107   const GhostInfo
108     *ghost_info;
109 
110   gs_main_instance
111     *interpreter;
112 
113   int
114     argc,
115     code;
116 
117   ssize_t
118     i;
119 
120 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
121   ghost_info=NTGhostscriptDLLVectors();
122 #else
123   GhostInfo
124     ghost_info_struct;
125 
126   ghost_info=(&ghost_info_struct);
127   (void) memset(&ghost_info_struct,0,sizeof(ghost_info_struct));
128   ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
129     gsapi_delete_instance;
130   ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
131   ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
132     gsapi_new_instance;
133   ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
134     gsapi_init_with_args;
135   ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
136     int *)) gsapi_run_string;
137   ghost_info_struct.set_stdio=(int (*)(gs_main_instance *,int (*)(void *,char *,
138     int),int (*)(void *,const char *,int),int (*)(void *, const char *, int)))
139     gsapi_set_stdio;
140   ghost_info_struct.revision=(int (*)(gsapi_revision_t *,int)) gsapi_revision;
141 #endif
142   if (ghost_info == (GhostInfo *) NULL)
143     return(ExecuteGhostscriptCommand(verbose,command,message,exception));
144   if (verbose != MagickFalse)
145     {
146       (void) fprintf(stdout,"[ghostscript library %.2f]",
147         GhostscriptVersion(ghost_info));
148       SetArgsStart(command,args_start);
149       (void) fputs(args_start,stdout);
150     }
151   interpreter=(gs_main_instance *) NULL;
152   errors=(char *) NULL;
153   status=(ghost_info->new_instance)(&interpreter,(void *) &errors);
154   if (status < 0)
155     return(ExecuteGhostscriptCommand(verbose,command,message,exception));
156   code=0;
157   argv=StringToArgv(command,&argc);
158   if (argv == (char **) NULL)
159     {
160       (ghost_info->delete_instance)(interpreter);
161       return(MagickFalse);
162     }
163   (void) (ghost_info->set_stdio)(interpreter,(int (MagickDLLCall *)(void *,
164     char *,int)) NULL,GhostscriptDelegateMessage,GhostscriptDelegateMessage);
165   status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
166   if (status == 0)
167     status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
168       0,&code);
169   (ghost_info->exit)(interpreter);
170   (ghost_info->delete_instance)(interpreter);
171   for (i=0; i < (ssize_t) argc; i++)
172     argv[i]=DestroyString(argv[i]);
173   argv=(char **) RelinquishMagickMemory(argv);
174   if (status != 0)
175     {
176       SetArgsStart(command,args_start);
177       if (status == -101) /* quit */
178         (void) FormatLocaleString(message,MaxTextExtent,
179           "[ghostscript library %.2f]%s: %s",GhostscriptVersion(ghost_info),
180           args_start,errors);
181       else
182         {
183           (void) ThrowMagickException(exception,GetMagickModule(),
184             DelegateError,"PostscriptDelegateFailed",
185             "`[ghostscript library %.2f]%s': %s",GhostscriptVersion(ghost_info),
186             args_start,errors);
187           if (errors != (char *) NULL)
188             errors=DestroyString(errors);
189           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
190             "Ghostscript returns status %d, exit code %d",status,code);
191           return(MagickFalse);
192         }
193     }
194   if (errors != (char *) NULL)
195     errors=DestroyString(errors);
196   return(MagickTrue);
197 #else
198   status=ExternalDelegateCommand(MagickFalse,verbose,command,(char *) NULL,
199     exception);
200   return(status == 0 ? MagickTrue : MagickFalse);
201 #endif
202 }
203 
IsGhostscriptRendered(const char * path)204 static MagickBooleanType IsGhostscriptRendered(const char *path)
205 {
206   MagickBooleanType
207     status;
208 
209   struct stat
210     attributes;
211 
212   if ((path == (const char *) NULL) || (*path == '\0'))
213     return(MagickFalse);
214   status=GetPathAttributes(path,&attributes);
215   if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
216       (attributes.st_size > 0))
217     return(MagickTrue);
218   return(MagickFalse);
219 }
220 
ReadGhostScriptXMPProfile(MagickByteBuffer * buffer,StringInfo ** profile)221 static inline void ReadGhostScriptXMPProfile(MagickByteBuffer *buffer,
222   StringInfo **profile)
223 {
224 #define BeginXMPPacket  "?xpacket begin="
225 #define EndXMPPacket  "<?xpacket end="
226 
227   int
228     c;
229 
230   MagickBooleanType
231     found_end,
232     status;
233 
234   char
235     *p;
236 
237   size_t
238     length;
239 
240   ssize_t
241     count;
242 
243   if (*profile != (StringInfo *) NULL)
244     return;
245   status=CompareMagickByteBuffer(buffer,BeginXMPPacket,strlen(BeginXMPPacket));
246   if (status == MagickFalse)
247     return;
248   length=8192;
249   *profile=AcquireStringInfo(length);
250   found_end=MagickFalse;
251   p=(char *) GetStringInfoDatum(*profile);
252   *p++='<';
253   count=1;
254   for (c=ReadMagickByteBuffer(buffer); c != EOF; c=ReadMagickByteBuffer(buffer))
255   {
256     if (count == (ssize_t) length)
257       {
258         length<<=1;
259         SetStringInfoLength(*profile,length);
260         p=(char *) GetStringInfoDatum(*profile)+count;
261       }
262     count++;
263     *p++=(char) c;
264     if (found_end == MagickFalse)
265       found_end=CompareMagickByteBuffer(buffer,EndXMPPacket,
266         strlen(EndXMPPacket));
267     else
268       {
269         if (c == (int) '>')
270           break;
271       }
272   }
273   SetStringInfoLength(*profile,(size_t) count);
274 }
275 
276 #endif
277