1 /*
2 **
3 ** save.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyrigth (C) 2004 Jose E. Marchesi
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING.  If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author:   Johannes Plass (plass@thep.physik.uni-mainz.de)
24 **           Department of Physics
25 **           Johannes Gutenberg-University
26 **           Mainz, Germany
27 **
28 **           Jose E. Marchesi (jemarch@gnu.org)
29 **           GNU Project
30 **
31 */
32 #include "ac_config.h"
33 
34 /*
35 #define MESSAGES
36 */
37 #include "message.h"
38 
39 #include <stdlib.h>
40 #include <stdio.h>
41 
42 #include "paths.h"
43 #include INC_X11(Intrinsic.h)
44 #include "Ghostview.h"
45 
46 #include "types.h"
47 #include "config.h"
48 #include "error.h"
49 #include "file.h"
50 #include "main_resources.h"
51 #include "main_globals.h"
52 #include "misc.h"
53 #include "note.h"
54 #include "process.h"
55 #include "ps.h"
56 #include "doc_misc.h"
57 #include "save.h"
58 
59 
60 #   include <sys/types.h>
61 #   include <unistd.h>
62 
63 
64 /*############################################################*/
65 /* save_alllocSaveData */
66 /*############################################################*/
67 
68 SaveData
save_allocSaveData(void)69 save_allocSaveData(void)
70 {
71    SaveData sd;
72    Cardinal size = sizeof(SaveDataStruct);
73 
74    BEGINMESSAGE(save_alllocSaveData)
75    sd = (SaveData) XtMalloc(size);
76    memset((void*) sd ,0,(size_t)size);
77    ENDMESSAGE(save_allocSaveData)
78    return(sd);
79 }
80 
81 /*############################################################*/
82 /* save_freeSaveData */
83 /*############################################################*/
84 
85 void
save_freeSaveData(SaveData sd)86 save_freeSaveData(SaveData sd)
87 {
88    BEGINMESSAGE(save_freeSaveData)
89    XtFree(sd->save_fn);
90    XtFree(sd->src_fn);
91    XtFree(sd->conv_fn);
92    XtFree(sd->pagelist);
93    XtFree(sd->print_cmd);
94    XtFree((XtPointer)sd);
95    ENDMESSAGE(save_freeSaveData)
96 }
97 
98 /*------------------------------------------------------------*/
99 /* print_file */
100 /*------------------------------------------------------------*/
101 
102 
103 #   define SYSTEM_SUCCEEDED_ON(bbb)  (system(bbb) == 0)
104 #   define SYSTEM_FAILED_ON(bbb)     (system(bbb) != 0)
105 
106 
107 static String
print_file(String print_command,String print_filename)108 print_file(String print_command, String print_filename)
109 {
110    String error=NULL;
111    char *print_quoted_filename;
112    char *c,*p;
113    Cardinal m,n;
114    String printfail=GV_ERROR_PRINT_FAIL;
115 
116    BEGINMESSAGE(print_file)
117 
118    print_quoted_filename = quote_filename(print_filename);
119    p = XtNewString(print_command);
120    n=0;
121    c=p;
122    while ((c=strstr(c,"%s"))) { c+=2; n++; }
123    m = (strlen(p)+(n>0?n:1)*strlen(print_quoted_filename)+5)*sizeof(char);
124    c = (char*) XtMalloc(m);
125    if (n>0) {
126      char *e,*s;
127      e=s=p;
128      c[0]='\0';
129      while (s) {
130        s=strstr(e,"%s");
131        if (s) *s='\0';
132        strcat(c,e);
133        if (s) {
134 	 strcat(c,print_quoted_filename);
135          e=s+2;
136        }
137        else s=NULL;
138      }
139    } else {
140      sprintf(c, "%s %s",p,print_quoted_filename);
141    }
142    INFSMESSAGE(printing:,c)
143    if (SYSTEM_FAILED_ON(c)) {
144      m = (strlen(printfail)+strlen(c)+1)*sizeof(char);
145        error = (char*) XtMalloc(m);
146      sprintf(error,printfail,c);
147    }
148    XtFree(c);
149    XtFree(p);
150    XtFree(print_quoted_filename);
151    ENDMESSAGE(print_file)
152    return(error);
153 }
154 
155 /*------------------------------------------------------------*/
156 /* save_forkPDFToPSConversionDone */
157 /*------------------------------------------------------------*/
158 
159 static void
save_forkPDFToPSConversionDone(XtPointer client_data,int type)160 save_forkPDFToPSConversionDone(XtPointer client_data, int type)
161 {
162    char *error=NULL;
163    SaveData sd = (SaveData) client_data;
164 
165    BEGINMESSAGE(save_forkPDFToPSConversionDone)
166 
167    if (type==PROCESS_NOTIFY) {
168       INFMESSAGE(call is of type PROCESS_NOTIFY)
169       error = save_saveFile(sd);
170       if (error) {
171          NotePopupShowMessage(error);
172          XtFree(error);
173       }
174    } else if (type==PROCESS_KILL) {
175       INFMESSAGE(call is of type PROCESS_KILL)
176       if (sd->conv_fn)  {
177          INFSMESSAGE(deleting file, sd->conv_fn)
178          unlink(sd->conv_fn);
179       }
180       save_freeSaveData(sd);
181    }
182 
183    ENDMESSAGE(save_forkPDFToPSConversionDone)
184 }
185 
186 /*------------------------------------------------------------*/
187 /* save_forkPDFToPSConversion */
188 /*------------------------------------------------------------*/
189 
190 static String
save_forkPDFToPSConversion(SaveData sd)191 save_forkPDFToPSConversion(SaveData sd)
192 {
193    char command[512], tmp[512];
194    char proc_name[256];
195    char *error=NULL;
196    char *pos;
197    char *pdfpos;
198    char *pspos;
199    char *quoted_src_fn, *quoted_conv_fn;
200    char* src = command;
201    char* dest = tmp;
202    int spaceFound = 0;
203 
204    BEGINMESSAGE(save_forkPDFToPSConversion)
205 
206    pos=file_locateFilename(sd->src_fn);
207    strcpy(proc_name,pos);
208    strcat(proc_name," conversion");
209 
210    quoted_src_fn = quote_filename(sd->src_fn);
211    quoted_conv_fn = quote_filename(sd->conv_fn);
212    if ((pdfpos = strstr(gv_gs_cmd_conv_pdf,"%pdf")) &&
213        (pspos = strstr(gv_gs_cmd_conv_pdf,"%ps"))) {
214      command[0] = '\0';
215      if (pdfpos < pspos) {
216        strncat(command,gv_gs_cmd_conv_pdf,(pdfpos-gv_gs_cmd_conv_pdf));
217        strcat(command,quoted_src_fn);
218        strncat(command,pdfpos+4,(pspos-pdfpos-4));
219        strcat(command,quoted_conv_fn);
220        strcat(command,pspos+3);
221      } else {
222        strncat(command,gv_gs_cmd_conv_pdf,(pspos-gv_gs_cmd_conv_pdf));
223        strcat(command,quoted_conv_fn);
224        strncat(command,pspos+3,(pdfpos-pspos-3));
225        strcat(command,quoted_src_fn);
226        strcat(command,pdfpos+4);
227      }
228    } else {
229      sprintf(command,gv_gs_cmd_conv_pdf,quoted_conv_fn,quoted_src_fn);
230    }
231    XtFree(quoted_src_fn);
232    XtFree(quoted_conv_fn);
233 
234    if (strstr(gv_gs_cmd_scan_pdf, "-P") || !gv_gs_safer)
235       strcpy(tmp, gv_gs_cmd_scan_pdf);
236    else
237    {
238       while (*src)
239       {
240          int isSpace = *src == ' ';
241          *(dest++) = *(src++);
242 	 if (!spaceFound && isSpace)
243 	 {
244 	    strcpy(dest, "-P- -dSAFER ");
245 	    dest+=12;
246 	    spaceFound = 1;
247 	 }
248       }
249       *dest = 0;
250    }
251 
252    INFSMESSAGE(starting conversion:,tmp)
253    process_fork(proc_name,tmp,save_forkPDFToPSConversionDone,(XtPointer)sd);
254    ENDMESSAGE(save_forkPDFToPSConversion)
255    return(error);
256 }
257 
258 /*------------------------------------------------------------*/
259 /* save_copyToFile */
260 /*------------------------------------------------------------*/
261 
262 static String
save_copyToFile(String save_filename,String src_filename,char * pagelist,int scanstyle)263 save_copyToFile(String save_filename, String src_filename, char *pagelist, int scanstyle)
264 {
265    FILE *save_file=NULL;
266    FILE *src_file=NULL;
267    String error=NULL;
268    String openfail=GV_ERROR_OPEN_FAIL;
269    char *tmp;
270 
271    BEGINMESSAGE(save_copyToFile)
272 
273    if ((save_file = fopen(save_filename, "w")) == NULL)
274       error = open_fail_error(errno,openfail,save_filename,0);
275    if (!error && (src_file=fopen(src_filename,"r"))==NULL)
276       error = open_fail_error(errno,openfail,src_filename,0);
277    if (!error) {
278       if (pagelist) {
279          Document src_doc=NULL;
280 	 String s = XtNewString(src_filename);
281 	 s = file_getUsefulName(s);
282          INFMESSAGE(scanning document)
283          doc_scanFile(&src_file,&src_doc,src_filename,s,NULL,NULL,NULL,NULL,scanstyle,gv_gs_safeDir);
284          if (src_doc) {
285             INFMESSAGE(calling pscopydoc)
286             pscopydoc(save_file,src_filename,src_doc,pagelist);
287             psfree(src_doc);
288          } else {
289             char *error_scan_fail = "Failed to scan file %s\n";
290             char tmp[512];
291             sprintf(tmp,error_scan_fail,src_filename);
292             error=XtNewString(tmp);
293          }
294       } else {
295          char buf[BUFSIZ];
296          int  bytes;
297          INFMESSAGE(copying file literaly)
298          while ((bytes = read(fileno(src_file),buf,BUFSIZ)))
299                bytes = write(fileno(save_file), buf, bytes);
300       }
301    }
302    tmp = close_file(src_file,src_filename);   if (!error) error = tmp;
303    tmp = close_file(save_file,save_filename); if (!error) error = tmp;
304 
305    ENDMESSAGE(save_copyToFile)
306    return(error);
307 }
308 
309 /*############################################################*/
310 /* save_saveFile */
311 /*############################################################*/
312 
313 String
save_saveFile(sd)314 save_saveFile(sd)
315    SaveData sd;
316 {
317    char *src_fn;
318    String error=NULL,s;
319 
320    BEGINMESSAGE(save_saveFile)
321 
322    if (!sd->save_fn && !sd->print_cmd && sd->save_to_file) {
323       INFMESSAGE(save_filename not useful)
324       ENDMESSAGE(save_saveFile)
325       return(error);
326    }
327 
328    if (!error && sd->convert && !sd->conv_fn)
329      {
330 
331      s = sd->save_fn ? sd->save_fn : sd->src_fn;
332      s = XtNewString(s);
333      s = file_getUsefulName(s);
334      s = file_pdfname2psname(s);
335      sd->conv_fn = file_getTmpFilename(NULL, s, NULL);
336      XtFree(s);
337      if (sd->conv_fn == NULL)
338 	     return XtNewString("Cannot create temporary file!");
339      INFSMESSAGE(converting from file,sd->src_fn)
340      INFSMESSAGE(converting to file,sd->conv_fn)
341      error = save_forkPDFToPSConversion(sd);
342      ENDMESSAGE(save_saveFile)
343      return(error);
344    }
345 
346    src_fn  = sd->src_fn;
347    if (sd->conv_fn) src_fn = sd->conv_fn;
348 
349    if (!error && sd->save_to_file) {
350       if (!sd->save_fn) {
351 	s = XtNewString(sd->src_fn);
352 	s = file_getUsefulName(s);
353 	s = file_pdfname2psname(s);
354 	sd->save_fn = file_getTmpFilename(NULL, s, NULL);
355 	XtFree(s);
356       }
357       if (!sd->save_fn) {
358         error = XtNewString("Cannot create temporary file!");
359       } else {
360         INFSMESSAGE(saving from file,src_fn)
361         INFSMESSAGE(saving to file,sd->save_fn)
362         error = save_copyToFile(sd->save_fn,src_fn,sd->pagelist,sd->scanstyle);
363         src_fn = sd->save_fn;
364       }
365    }
366 
367    if (!error && sd->save_to_printer) {
368       INFSMESSAGE(saving to printer from file,src_fn)
369       error = print_file(sd->print_cmd,src_fn);
370       if (src_fn != sd->src_fn && !(sd->print_kills_file)) {
371          INFSMESSAGE(deleting file, src_fn)
372          unlink(src_fn);
373       }
374    }
375 
376    if (sd->conv_fn)  {
377       INFSMESSAGE(deleting file, sd->conv_fn)
378       unlink(sd->conv_fn);
379    }
380    save_freeSaveData(sd);
381 
382    ENDMESSAGE(save_saveFile)
383    return(error);
384 }
385