]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-file-helpers.c
Support for PDF, PS and EPS compressed files. Fixes bug #307087.
[evince.git] / libdocument / ev-file-helpers.c
1 /*
2  *  Copyright (C) 2002 Jorn Baayen
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  *  $Id$
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <glib.h>
30 #include <glib/gstdio.h>
31 #include <errno.h>
32 #include <libgnomevfs/gnome-vfs-uri.h>
33 #include <libgnomevfs/gnome-vfs-utils.h>
34 #include <libgnomevfs/gnome-vfs-ops.h>
35 #include <libgnomevfs/gnome-vfs-xfer.h>
36
37 #include "ev-file-helpers.h"
38
39 static gchar *dot_dir = NULL;
40 static gchar *tmp_dir = NULL;
41 static gint   count = 0;
42
43 static gboolean
44 ensure_dir_exists (const char *dir)
45 {
46         if (g_file_test (dir, G_FILE_TEST_IS_DIR))
47                 return TRUE;
48         
49         if (g_mkdir (dir, 488) == 0)
50                 return TRUE;
51
52         if (errno == EEXIST)
53                 return g_file_test (dir, G_FILE_TEST_IS_DIR);
54         
55         g_warning ("Failed to create directory %s: %s", dir, strerror (errno));
56         return FALSE;
57 }
58
59 const gchar *
60 ev_dot_dir (void)
61 {
62         if (dot_dir == NULL) {
63                 gboolean exists;
64
65                 dot_dir = g_build_filename (gnome_user_dir_get (),
66                                             "evince",
67                                             NULL);
68
69                 exists = ensure_dir_exists (dot_dir);
70                 if (!exists)
71                         exit (1);
72         }
73
74         return dot_dir;
75 }
76
77 const gchar *
78 ev_tmp_dir (void)
79 {
80         if (tmp_dir == NULL) {
81                 gboolean exists;
82                 gchar   *dirname;
83
84                 dirname = g_strdup_printf ("evince-%u", getpid ());
85                 tmp_dir = g_build_filename (g_get_tmp_dir (),
86                                             dirname,
87                                             NULL);
88                 g_free (dirname);
89
90                 exists = ensure_dir_exists (tmp_dir);
91                 g_assert (exists);
92         }
93
94         return tmp_dir;
95 }
96
97 void
98 ev_file_helpers_init (void)
99 {
100 }
101
102 void
103 ev_file_helpers_shutdown (void)
104 {       
105         if (tmp_dir != NULL)    
106                 g_rmdir (tmp_dir);
107
108         g_free (tmp_dir);
109         g_free (dot_dir);
110
111         dot_dir = NULL;
112         tmp_dir = NULL;
113 }
114
115 gchar * 
116 ev_tmp_filename (const gchar *prefix)
117 {
118         gchar *basename;
119         gchar *filename = NULL;
120
121         do {
122                 if (filename != NULL)
123                         g_free (filename);
124                         
125                 basename = g_strdup_printf ("%s-%d",
126                                             prefix ? prefix : "document",
127                                             count ++);
128                 
129                 filename = g_build_filename (ev_tmp_dir (),
130                                              basename, NULL);
131                 
132                 g_free (basename);
133         } while (g_file_test (filename, G_FILE_TEST_EXISTS));
134                         
135         return filename;
136 }
137
138 gboolean
139 ev_xfer_uri_simple (const char *from,
140                     const char *to,
141                     GError     **error)
142 {
143         GnomeVFSResult result;
144         GnomeVFSURI *source_uri;
145         GnomeVFSURI *target_uri;
146         
147         if (!from)
148                 return FALSE;
149         
150         source_uri = gnome_vfs_uri_new (from);
151         target_uri = gnome_vfs_uri_new (to);
152
153         result = gnome_vfs_xfer_uri (source_uri, target_uri, 
154                                      GNOME_VFS_XFER_DEFAULT | GNOME_VFS_XFER_FOLLOW_LINKS,
155                                      GNOME_VFS_XFER_ERROR_MODE_ABORT,
156                                      GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
157                                      NULL,
158                                      NULL);
159         gnome_vfs_uri_unref (target_uri);
160         gnome_vfs_uri_unref (source_uri);
161     
162         if (result != GNOME_VFS_OK)
163                 g_set_error (error,
164                              G_FILE_ERROR,
165                              G_FILE_ERROR_FAILED,
166                              gnome_vfs_result_to_string (result));
167         return (result == GNOME_VFS_OK);
168
169 }
170
171 /* Compressed files support */
172 #define BZIPCOMMAND "bzip2"
173 #define GZIPCOMMAND "gzip"
174 #define N_ARGS      5
175 #define BUFFER_SIZE 1024
176
177 gchar *
178 ev_file_uncompress (const gchar       *uri,
179                     EvCompressionType  type,
180                     GError           **error)
181 {
182         gchar *argv[N_ARGS];
183         gchar *uri_unc = NULL;
184         gchar *filename, *filename_unc;
185         gchar *cmd;
186         gint   fd, pout;
187
188         g_return_val_if_fail (uri != NULL, NULL);
189
190         if (type == EV_COMPRESSION_NONE)
191                 return NULL;
192
193         cmd = g_find_program_in_path ((type == EV_COMPRESSION_BZIP2) ? BZIPCOMMAND : GZIPCOMMAND);
194         if (!cmd)
195                 return NULL;
196
197
198         filename = g_filename_from_uri (uri, NULL, NULL);
199         if (!filename) {
200                 g_free (cmd);
201                 return NULL;
202         }
203         
204         filename_unc = g_build_filename (ev_tmp_dir (), "evinceXXXXXX", NULL);
205         fd = g_mkstemp (filename_unc);
206         if (fd < 0) {
207                 g_free (cmd);
208                 g_free (filename);
209                 g_free (filename_unc);
210                 return NULL;
211         }
212         
213         argv[0] = cmd;
214         argv[1] = "-cd";
215         argv[2] = filename;
216         argv[3] = filename_unc;
217         argv[4] = NULL;
218
219         if (g_spawn_async_with_pipes (NULL, argv, NULL,
220                                       G_SPAWN_STDERR_TO_DEV_NULL,
221                                       NULL, NULL, NULL,
222                                       NULL, &pout, NULL, error)) {
223                 GIOChannel *in, *out;
224                 gchar buf[BUFFER_SIZE];
225                 GIOStatus read_st, write_st;
226                 gsize bytes_read, bytes_written;
227
228                 in = g_io_channel_unix_new (pout);
229                 g_io_channel_set_encoding (in, NULL, NULL);
230                 out = g_io_channel_unix_new (fd);
231                 g_io_channel_set_encoding (out, NULL, NULL);
232
233                 do {
234                         read_st = g_io_channel_read_chars (in, buf,
235                                                            BUFFER_SIZE,
236                                                            &bytes_read,
237                                                            error);
238                         if (read_st == G_IO_STATUS_NORMAL) {
239                                 write_st = g_io_channel_write_chars (out, buf,
240                                                                      bytes_read,
241                                                                      &bytes_written,
242                                                                      error);
243                                 if (write_st == G_IO_STATUS_ERROR)
244                                         break;
245                         } else if (read_st == G_IO_STATUS_ERROR) {
246                                 break;
247                         }
248                 } while (bytes_read > 0);
249                 
250                 g_io_channel_unref (in);
251                 g_io_channel_unref (out);
252         }
253
254         close (fd);
255
256         if (*error == NULL) {
257                 uri_unc = g_filename_to_uri (filename_unc,
258                                              NULL, NULL);
259         }
260
261         g_free (cmd);
262         g_free (filename);
263         g_free (filename_unc);
264
265         return uri_unc;
266 }