]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-attachment.c
Port to gio and drop gnome-vfs dependency. Fixes bug #510401. Based on
[evince.git] / libdocument / ev-attachment.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <config.h>
21 #include <glib/gi18n.h>
22 #include <glib/gstdio.h>
23 #include "ev-file-helpers.h"
24 #include "ev-attachment.h"
25
26 enum
27 {
28         PROP_0,
29         PROP_NAME,
30         PROP_DESCRIPTION,
31         PROP_MTIME,
32         PROP_CTIME,
33         PROP_SIZE,
34         PROP_DATA
35 };
36
37 struct _EvAttachmentPrivate {
38         gchar                   *name;
39         gchar                   *description;
40         GTime                    mtime;
41         GTime                    ctime;
42         gsize                    size;
43         gchar                   *data;
44         gchar                   *mime_type;
45
46         GAppInfo                *app;
47         GFile                   *tmp_file;
48 };
49
50 #define EV_ATTACHMENT_GET_PRIVATE(object) \
51                 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_ATTACHMENT, EvAttachmentPrivate))
52
53 G_DEFINE_TYPE (EvAttachment, ev_attachment, G_TYPE_OBJECT)
54
55 GQuark
56 ev_attachment_error_quark (void)
57 {
58         static GQuark error_quark = 0;
59         
60         if (error_quark == 0)
61                 error_quark =
62                         g_quark_from_static_string ("ev-attachment-error-quark");
63         
64         return error_quark;
65 }
66
67 static void
68 ev_attachment_finalize (GObject *object)
69 {
70         EvAttachment *attachment = EV_ATTACHMENT (object);
71
72         if (attachment->priv->name) {
73                 g_free (attachment->priv->name);
74                 attachment->priv->name = NULL;
75         }
76
77         if (attachment->priv->description) {
78                 g_free (attachment->priv->description);
79                 attachment->priv->description = NULL;
80         }
81
82         if (attachment->priv->data) {
83                 g_free (attachment->priv->data);
84                 attachment->priv->data = NULL;
85         }
86
87         if (attachment->priv->mime_type) {
88                 g_free (attachment->priv->mime_type);
89                 attachment->priv->mime_type = NULL;
90         }
91
92         if (attachment->priv->app) {
93                 g_object_unref (attachment->priv->app);
94                 attachment->priv->app = NULL;
95         }
96
97         if (attachment->priv->tmp_file) {
98                 ev_tmp_file_unlink (attachment->priv->tmp_file);
99                 g_object_unref (attachment->priv->tmp_file);
100                 attachment->priv->tmp_file = NULL;
101         }
102
103         (* G_OBJECT_CLASS (ev_attachment_parent_class)->finalize) (object);
104 }
105
106 static void
107 ev_attachment_set_property (GObject      *object,
108                             guint         prop_id,
109                             const GValue *value,
110                             GParamSpec   *param_spec)
111 {
112         EvAttachment *attachment = EV_ATTACHMENT (object);
113
114         switch (prop_id) {
115         case PROP_NAME:
116                 attachment->priv->name = g_value_dup_string (value);
117                 break;
118         case PROP_DESCRIPTION:
119                 attachment->priv->description = g_value_dup_string (value);
120                 break;
121         case PROP_MTIME:
122                 attachment->priv->mtime = g_value_get_ulong (value);
123                 break;
124         case PROP_CTIME:
125                 attachment->priv->ctime = g_value_get_ulong (value);
126                 break;
127         case PROP_SIZE:
128                 attachment->priv->size = g_value_get_uint (value);
129                 break;
130         case PROP_DATA:
131                 attachment->priv->data = g_value_get_pointer (value);
132                 attachment->priv->mime_type = g_content_type_guess (attachment->priv->name,
133                                                                     (guchar *) attachment->priv->data,
134                                                                     attachment->priv->size,
135                                                                     NULL);
136                 break;
137         default:
138                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
139                                                    prop_id,
140                                                    param_spec);
141                 break;
142         }
143 }
144
145 static void
146 ev_attachment_class_init (EvAttachmentClass *klass)
147 {
148         GObjectClass *g_object_class;
149
150         g_object_class = G_OBJECT_CLASS (klass);
151
152         g_object_class->set_property = ev_attachment_set_property;
153
154         g_type_class_add_private (g_object_class, sizeof (EvAttachmentPrivate));
155
156         /* Properties */
157         g_object_class_install_property (g_object_class,
158                                          PROP_NAME,
159                                          g_param_spec_string ("name",
160                                                               "Name",
161                                                               "The attachment name",
162                                                               NULL,
163                                                               G_PARAM_WRITABLE |
164                                                               G_PARAM_CONSTRUCT_ONLY));
165         g_object_class_install_property (g_object_class,
166                                          PROP_DESCRIPTION,
167                                          g_param_spec_string ("description",
168                                                               "Description",
169                                                               "The attachment description",
170                                                               NULL,
171                                                               G_PARAM_WRITABLE |
172                                                               G_PARAM_CONSTRUCT_ONLY));
173         g_object_class_install_property (g_object_class,
174                                          PROP_MTIME,
175                                          g_param_spec_ulong ("mtime",
176                                                              "ModifiedTime", 
177                                                              "The attachment modification date",
178                                                              0, G_MAXULONG, 0,
179                                                              G_PARAM_WRITABLE |
180                                                              G_PARAM_CONSTRUCT_ONLY));
181         g_object_class_install_property (g_object_class,
182                                          PROP_CTIME,
183                                          g_param_spec_ulong ("ctime",
184                                                              "CreationTime",
185                                                              "The attachment creation date",
186                                                              0, G_MAXULONG, 0,
187                                                              G_PARAM_WRITABLE |
188                                                              G_PARAM_CONSTRUCT_ONLY));
189         g_object_class_install_property (g_object_class,
190                                          PROP_SIZE,
191                                          g_param_spec_uint ("size",
192                                                             "Size",
193                                                             "The attachment size",
194                                                             0, G_MAXUINT, 0,
195                                                             G_PARAM_WRITABLE |
196                                                             G_PARAM_CONSTRUCT_ONLY));
197         g_object_class_install_property (g_object_class,
198                                          PROP_DATA,
199                                          g_param_spec_pointer ("data",
200                                                                "Data",
201                                                                "The attachment data",
202                                                                G_PARAM_WRITABLE |
203                                                                G_PARAM_CONSTRUCT_ONLY));
204         
205         g_object_class->finalize = ev_attachment_finalize;
206 }
207
208 static void
209 ev_attachment_init (EvAttachment *attachment)
210 {
211         attachment->priv = EV_ATTACHMENT_GET_PRIVATE (attachment);
212
213         attachment->priv->name = NULL;
214         attachment->priv->description = NULL;
215         attachment->priv->data = NULL;
216         attachment->priv->mime_type = NULL;
217
218         attachment->priv->tmp_file = NULL;
219 }
220
221 EvAttachment *
222 ev_attachment_new (const gchar *name,
223                    const gchar *description,
224                    GTime        mtime,
225                    GTime        ctime,
226                    gsize        size,
227                    gpointer     data)
228 {
229         EvAttachment *attachment;
230
231         attachment = g_object_new (EV_TYPE_ATTACHMENT,
232                                    "name", name,
233                                    "description", description,
234                                    "mtime", mtime,
235                                    "ctime", ctime,
236                                    "size", size,
237                                    "data", data,
238                                    NULL);
239
240         return attachment;
241 }
242
243 const gchar *
244 ev_attachment_get_name (EvAttachment *attachment)
245 {
246         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
247
248         return attachment->priv->name;
249 }
250
251 const gchar *
252 ev_attachment_get_description (EvAttachment *attachment)
253 {
254         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
255
256         return attachment->priv->description;
257 }
258
259 GTime
260 ev_attachment_get_modification_date (EvAttachment *attachment)
261 {
262         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
263
264         return attachment->priv->mtime;
265 }
266
267 GTime
268 ev_attachment_get_creation_date (EvAttachment *attachment)
269 {
270         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
271
272         return attachment->priv->ctime;
273 }
274
275 const gchar *
276 ev_attachment_get_mime_type (EvAttachment *attachment)
277 {
278         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
279
280         return attachment->priv->mime_type;
281 }
282
283 gboolean
284 ev_attachment_save (EvAttachment *attachment,
285                     GFile        *file,
286                     GError      **error)
287 {
288         GFileOutputStream *output_stream;
289         GError *ioerror = NULL;
290         gssize  written_bytes;
291
292         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
293         g_return_val_if_fail (G_IS_FILE (file), FALSE);
294
295         output_stream = g_file_create (file, 0, NULL, &ioerror);
296         if (output_stream == NULL) {
297                 char *uri;
298                 
299                 uri = g_file_get_uri (file);
300                 g_set_error (error,
301                              EV_ATTACHMENT_ERROR, 
302                              ioerror->code,
303                              _("Couldn't save attachment “%s”: %s"),
304                              uri, 
305                              ioerror->message);
306
307                 g_error_free (ioerror);
308                 g_free (uri);
309                 
310                 return FALSE;
311         }
312         
313         written_bytes = g_output_stream_write (G_OUTPUT_STREAM (output_stream),
314                                                attachment->priv->data,
315                                                attachment->priv->size,
316                                                NULL, &ioerror);
317         if (written_bytes == -1) {
318                 char *uri;
319                 
320                 uri = g_file_get_uri (file);
321                 g_set_error (error,
322                              EV_ATTACHMENT_ERROR,
323                              ioerror->code,
324                              _("Couldn't save attachment “%s”: %s"),
325                              uri,
326                              ioerror->message);
327                 
328                 g_output_stream_close (G_OUTPUT_STREAM (output_stream), NULL, NULL);
329                 g_error_free (ioerror);
330                 g_free (uri);
331
332                 return FALSE;
333         }
334
335         g_output_stream_close (G_OUTPUT_STREAM (output_stream), NULL, NULL);
336
337         return TRUE;
338         
339 }
340
341 static gboolean
342 ev_attachment_launch_app (EvAttachment *attachment,
343                           GError      **error)
344 {
345         gboolean result;
346         GList   *files = NULL;
347         GError  *ioerror = NULL;
348
349         g_assert (G_IS_FILE (attachment->priv->tmp_file));
350         g_assert (G_IS_APP_INFO (attachment->priv->app));
351
352         files = g_list_prepend (files, attachment->priv->tmp_file);
353         result = g_app_info_launch (attachment->priv->app, files,
354                                     NULL, &ioerror);
355
356         if (!result) {
357                 g_set_error (error,
358                              EV_ATTACHMENT_ERROR,
359                              (gint) result,
360                              _("Couldn't open attachment “%s”: %s"),
361                              attachment->priv->name,
362                              ioerror->message);
363
364                 g_list_free (files);
365                 g_error_free (ioerror);
366                 
367                 return FALSE;
368         }
369
370         g_list_free (files);
371         
372         return TRUE;
373 }
374
375 gboolean
376 ev_attachment_open (EvAttachment *attachment,
377                     GError      **error)
378 {
379         GAppInfo *app_info;
380         gboolean  retval = FALSE;
381
382         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
383         
384         if (!attachment->priv->app) {
385                 app_info = g_app_info_get_default_for_type (attachment->priv->mime_type, TRUE);
386                 attachment->priv->app = app_info;
387         }
388
389         if (!attachment->priv->app) {
390                 g_set_error (error,
391                              EV_ATTACHMENT_ERROR,
392                              0,
393                              _("Couldn't open attachment “%s”"),
394                              attachment->priv->name);
395                 
396                 return FALSE;
397         }
398
399         if (attachment->priv->tmp_file &&
400             g_file_query_exists (attachment->priv->tmp_file, NULL)) {
401                 retval = ev_attachment_launch_app (attachment, error);
402         } else {
403                 GFile *tmpdir;
404                 GFile *file;
405                 
406                 tmpdir = g_file_new_for_path (ev_tmp_dir ());
407                 file = g_file_get_child (tmpdir, attachment->priv->name);
408
409                 if (ev_attachment_save (attachment, file, error)) {
410                         if (attachment->priv->tmp_file)
411                                 g_object_unref (attachment->priv->tmp_file);
412                         attachment->priv->tmp_file = g_object_ref (file);
413
414                         retval = ev_attachment_launch_app (attachment, error);
415                 }
416
417                 g_object_unref (file);
418                 g_object_unref (tmpdir);
419         }
420
421         return retval;
422 }
423