1 /*
2 * e-source-mail-signature.c
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /**
19 * SECTION: e-source-mail-signature
20 * @include: libedataserver/libedataserver.h
21 * @short_description: #ESource extension for email signatures
22 *
23 * The #ESourceMailSignature extension refers to a personalized email
24 * signature.
25 *
26 * Access the extension as follows:
27 *
28 * |[
29 * #include <libedataserver/libedataserver.h>
30 *
31 * ESourceMailSignature *extension;
32 *
33 * extension = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_SIGNATURE);
34 * ]|
35 **/
36
37 #include "evolution-data-server-config.h"
38
39 #include <string.h>
40 #include <glib/gi18n-lib.h>
41
42 #include <libedataserver/e-data-server-util.h>
43
44 #include "e-source-mail-signature.h"
45
46 typedef struct _AsyncContext AsyncContext;
47
48 struct _ESourceMailSignaturePrivate {
49 GFile *file;
50 gchar *mime_type;
51 };
52
53 struct _AsyncContext {
54 gchar *contents;
55 gchar *symlink_target;
56 gsize length;
57 };
58
59 enum {
60 PROP_0,
61 PROP_FILE,
62 PROP_MIME_TYPE
63 };
64
G_DEFINE_TYPE_WITH_PRIVATE(ESourceMailSignature,e_source_mail_signature,E_TYPE_SOURCE_EXTENSION)65 G_DEFINE_TYPE_WITH_PRIVATE (
66 ESourceMailSignature,
67 e_source_mail_signature,
68 E_TYPE_SOURCE_EXTENSION)
69
70 static void
71 async_context_free (AsyncContext *async_context)
72 {
73 g_free (async_context->contents);
74 g_free (async_context->symlink_target);
75
76 g_slice_free (AsyncContext, async_context);
77 }
78
79 static void
source_mail_signature_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)80 source_mail_signature_set_property (GObject *object,
81 guint property_id,
82 const GValue *value,
83 GParamSpec *pspec)
84 {
85 switch (property_id) {
86 case PROP_MIME_TYPE:
87 e_source_mail_signature_set_mime_type (
88 E_SOURCE_MAIL_SIGNATURE (object),
89 g_value_get_string (value));
90 return;
91 }
92
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
94 }
95
96 static void
source_mail_signature_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)97 source_mail_signature_get_property (GObject *object,
98 guint property_id,
99 GValue *value,
100 GParamSpec *pspec)
101 {
102 switch (property_id) {
103 case PROP_FILE:
104 g_value_set_object (
105 value,
106 e_source_mail_signature_get_file (
107 E_SOURCE_MAIL_SIGNATURE (object)));
108 return;
109
110 case PROP_MIME_TYPE:
111 g_value_take_string (
112 value,
113 e_source_mail_signature_dup_mime_type (
114 E_SOURCE_MAIL_SIGNATURE (object)));
115 return;
116 }
117
118 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
119 }
120
121 static void
source_mail_signature_dispose(GObject * object)122 source_mail_signature_dispose (GObject *object)
123 {
124 ESourceMailSignaturePrivate *priv;
125
126 priv = E_SOURCE_MAIL_SIGNATURE (object)->priv;
127 g_clear_object (&priv->file);
128
129 /* Chain up to parent's dispose() method. */
130 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->
131 dispose (object);
132 }
133
134 static void
source_mail_signature_finalize(GObject * object)135 source_mail_signature_finalize (GObject *object)
136 {
137 ESourceMailSignaturePrivate *priv;
138
139 priv = E_SOURCE_MAIL_SIGNATURE (object)->priv;
140
141 g_free (priv->mime_type);
142
143 /* Chain up to parent's finalize() method. */
144 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->
145 finalize (object);
146 }
147
148 static void
source_mail_signature_constructed(GObject * object)149 source_mail_signature_constructed (GObject *object)
150 {
151 ESourceMailSignaturePrivate *priv;
152 ESourceExtension *extension;
153 ESource *source;
154 const gchar *config_dir;
155 const gchar *uid;
156 gchar *base_dir;
157 gchar *path;
158
159 priv = E_SOURCE_MAIL_SIGNATURE (object)->priv;
160
161 /* Chain up to parent's constructed() method. */
162 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->constructed (object);
163
164 extension = E_SOURCE_EXTENSION (object);
165 source = e_source_extension_ref_source (extension);
166 uid = e_source_get_uid (source);
167
168 config_dir = e_get_user_config_dir ();
169 base_dir = g_build_filename (config_dir, "signatures", NULL);
170 path = g_build_filename (base_dir, uid, NULL);
171 priv->file = g_file_new_for_path (path);
172 g_mkdir_with_parents (base_dir, 0700);
173 g_free (base_dir);
174 g_free (path);
175
176 g_object_unref (source);
177 }
178
179 static void
e_source_mail_signature_class_init(ESourceMailSignatureClass * class)180 e_source_mail_signature_class_init (ESourceMailSignatureClass *class)
181 {
182 GObjectClass *object_class;
183 ESourceExtensionClass *extension_class;
184
185 object_class = G_OBJECT_CLASS (class);
186 object_class->set_property = source_mail_signature_set_property;
187 object_class->get_property = source_mail_signature_get_property;
188 object_class->dispose = source_mail_signature_dispose;
189 object_class->finalize = source_mail_signature_finalize;
190 object_class->constructed = source_mail_signature_constructed;
191
192 extension_class = E_SOURCE_EXTENSION_CLASS (class);
193 extension_class->name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
194
195 g_object_class_install_property (
196 object_class,
197 PROP_FILE,
198 g_param_spec_object (
199 "file",
200 "File",
201 "File containing signature content",
202 G_TYPE_FILE,
203 G_PARAM_READABLE |
204 G_PARAM_STATIC_STRINGS));
205
206 g_object_class_install_property (
207 object_class,
208 PROP_MIME_TYPE,
209 g_param_spec_string (
210 "mime-type",
211 "MIME Type",
212 "MIME type of the signature content",
213 NULL,
214 G_PARAM_READWRITE |
215 G_PARAM_CONSTRUCT |
216 G_PARAM_EXPLICIT_NOTIFY |
217 G_PARAM_STATIC_STRINGS |
218 E_SOURCE_PARAM_SETTING));
219 }
220
221 static void
e_source_mail_signature_init(ESourceMailSignature * extension)222 e_source_mail_signature_init (ESourceMailSignature *extension)
223 {
224 extension->priv = e_source_mail_signature_get_instance_private (extension);
225 }
226
227 /**
228 * e_source_mail_signature_get_file:
229 * @extension: an #ESourceMailSignature
230 *
231 * Returns a #GFile instance pointing to the signature file for @extension.
232 * The signature file may be a regular file containing the static signature
233 * content, or it may be a symbolic link to an executable file that produces
234 * the signature content.
235 *
236 * e_source_mail_signature_load() uses this to load the signature content.
237 *
238 * Returns: (transfer none): a #GFile
239 *
240 * Since: 3.6
241 **/
242 GFile *
e_source_mail_signature_get_file(ESourceMailSignature * extension)243 e_source_mail_signature_get_file (ESourceMailSignature *extension)
244 {
245 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
246
247 return extension->priv->file;
248 }
249
250 /**
251 * e_source_mail_signature_get_mime_type:
252 * @extension: an #ESourceMailSignature
253 *
254 * Returns the MIME type of the signature content for @extension, or %NULL
255 * if it has not yet been determined.
256 *
257 * e_source_mail_signature_load() sets this automatically if the MIME type
258 * has not yet been determined.
259 *
260 * Returns: (nullable): the MIME type of the signature content, or %NULL
261 *
262 * Since: 3.6
263 **/
264 const gchar *
e_source_mail_signature_get_mime_type(ESourceMailSignature * extension)265 e_source_mail_signature_get_mime_type (ESourceMailSignature *extension)
266 {
267 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
268
269 return extension->priv->mime_type;
270 }
271
272 /**
273 * e_source_mail_signature_dup_mime_type:
274 * @extension: an #ESourceMailSignature
275 *
276 * Thread-safe variation of e_source_mail_signature_get_mime_type().
277 * Use this function when accessing @extension from multiple threads.
278 *
279 * The returned string should be freed with g_free() when no longer needed.
280 *
281 * Returns: (nullable): a newly-allocated copy of #ESourceMailSignature:mime-type,
282 * or %NULL
283 *
284 * Since: 3.6
285 **/
286 gchar *
e_source_mail_signature_dup_mime_type(ESourceMailSignature * extension)287 e_source_mail_signature_dup_mime_type (ESourceMailSignature *extension)
288 {
289 const gchar *protected;
290 gchar *duplicate;
291
292 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
293
294 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
295
296 protected = e_source_mail_signature_get_mime_type (extension);
297 duplicate = g_strdup (protected);
298
299 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
300
301 return duplicate;
302 }
303
304 /**
305 * e_source_mail_signature_set_mime_type:
306 * @extension: an #ESourceMailSignature
307 * @mime_type: (nullable): a MIME type, or %NULL
308 *
309 * Sets the MIME type of the signature content for @extension.
310 *
311 * e_source_mail_signature_load() sets this automatically if the MIME type
312 * has not yet been determined.
313 *
314 * The internal copy of @mime_type is automatically stripped of leading
315 * and trailing whitespace. If the resulting string is empty, %NULL is
316 * set instead.
317 *
318 * Since: 3.6
319 **/
320 void
e_source_mail_signature_set_mime_type(ESourceMailSignature * extension,const gchar * mime_type)321 e_source_mail_signature_set_mime_type (ESourceMailSignature *extension,
322 const gchar *mime_type)
323 {
324 g_return_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension));
325
326 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
327
328 if (e_util_strcmp0 (extension->priv->mime_type, mime_type) == 0) {
329 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
330 return;
331 }
332
333 g_free (extension->priv->mime_type);
334 extension->priv->mime_type = e_util_strdup_strip (mime_type);
335
336 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
337
338 g_object_notify (G_OBJECT (extension), "mime-type");
339 }
340
341 /********************** e_source_mail_signature_load() ***********************/
342
343 /* Helper for e_source_mail_signature_load() */
344 static void
source_mail_signature_load_thread(GSimpleAsyncResult * simple,GObject * object,GCancellable * cancellable)345 source_mail_signature_load_thread (GSimpleAsyncResult *simple,
346 GObject *object,
347 GCancellable *cancellable)
348 {
349 AsyncContext *async_context;
350 GError *error = NULL;
351
352 async_context = g_simple_async_result_get_op_res_gpointer (simple);
353
354 e_source_mail_signature_load_sync (
355 E_SOURCE (object),
356 &async_context->contents,
357 &async_context->length,
358 cancellable, &error);
359
360 if (error != NULL)
361 g_simple_async_result_take_error (simple, error);
362 }
363
364 /**
365 * e_source_mail_signature_load_sync:
366 * @source: an #ESource
367 * @contents: (out): return location for the signature content
368 * @length: (optional) (out): return location for the length of the signature
369 * content, or %NULL if the length is not needed
370 * @cancellable: optional #GCancellable object, or %NULL
371 * @error: return location for a #GError, or %NULL
372 *
373 * Loads a signature from the signature file for @source, which is
374 * given by e_source_mail_signature_get_file(). The signature contents
375 * are placed in @contents, and @length is set to the size of the @contents
376 * string. The @contents string should be freed with g_free() when no
377 * longer needed.
378 *
379 * If the signature file is executable, it will be executed and its output
380 * captured as the email signature content. If the signature file is not
381 * executable, the email signature content is read directly from the file.
382 *
383 * Returns: %TRUE on success, %FALSE on failure
384 *
385 * Since: 3.6
386 **/
387 gboolean
e_source_mail_signature_load_sync(ESource * source,gchar ** contents,gsize * length,GCancellable * cancellable,GError ** error)388 e_source_mail_signature_load_sync (ESource *source,
389 gchar **contents,
390 gsize *length,
391 GCancellable *cancellable,
392 GError **error)
393 {
394 ESourceMailSignature *extension;
395 GFileInfo *file_info;
396 GFile *file;
397 const gchar *content_type;
398 const gchar *extension_name;
399 gchar *local_contents = NULL;
400 gboolean can_execute;
401 gboolean success;
402 gchar *guessed_content_type;
403 gchar *command_line;
404 gchar *mime_type;
405 gchar *path;
406
407 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
408 g_return_val_if_fail (contents != NULL, FALSE);
409
410 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
411 extension = e_source_get_extension (source, extension_name);
412 file = e_source_mail_signature_get_file (extension);
413
414 file_info = g_file_query_info (
415 file,
416 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE ","
417 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
418 G_FILE_QUERY_INFO_NONE,
419 cancellable, error);
420
421 if (file_info == NULL)
422 return FALSE;
423
424 can_execute = g_file_info_get_attribute_boolean (
425 file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
426
427 content_type = g_file_info_get_content_type (file_info);
428 mime_type = g_content_type_get_mime_type (content_type);
429
430 if (can_execute)
431 goto execute;
432
433 /*** Load signature file contents ***/
434
435 success = g_file_load_contents (
436 file, cancellable, &local_contents, NULL, NULL, error);
437
438 if (!success)
439 goto exit;
440
441 g_return_val_if_fail (local_contents != NULL, FALSE);
442
443 /* Signatures are saved as UTF-8, but we still need to check that
444 * the signature is valid UTF-8 because the user may be opening a
445 * signature file this is in his/her locale character set. If it
446 * is not UTF-8 then try converting from the current locale. */
447 if (!g_utf8_validate (local_contents, -1, NULL)) {
448 gchar *utf8;
449
450 utf8 = g_locale_to_utf8 (
451 local_contents, -1, NULL, NULL, error);
452
453 if (utf8 == NULL) {
454 success = FALSE;
455 goto exit;
456 }
457
458 g_free (local_contents);
459 local_contents = utf8;
460 }
461
462 goto exit;
463
464 execute:
465
466 /*** Execute signature file and capture output ***/
467
468 path = g_file_get_path (file);
469
470 if (path == NULL) {
471 g_set_error (
472 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
473 _("Signature script must be a local file"));
474 success = FALSE;
475 goto exit;
476 }
477
478 /* Enclose the path in single-quotes for compatibility on Windows.
479 * (See g_spawn_command_line_sync() documentation for rationale.) */
480 command_line = g_strdup_printf ("'%s'", path);
481
482 success = g_spawn_command_line_sync (
483 command_line, &local_contents, NULL, NULL, error);
484
485 g_free (command_line);
486 g_free (path);
487
488 /* Check if we failed to spawn the script. */
489 if (!success)
490 goto exit;
491
492 /* Check if we were cancelled while the script was running. */
493 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
494 success = FALSE;
495 goto exit;
496 }
497
498 g_return_val_if_fail (local_contents != NULL, FALSE);
499
500 /* Signature scripts are supposed to generate UTF-8 content, but
501 * because users are known to never read the manual, we try to do
502 * our best if the content isn't valid UTF-8 by assuming that the
503 * content is in the user's locale character set. */
504 if (!g_utf8_validate (local_contents, -1, NULL)) {
505 gchar *utf8;
506
507 utf8 = g_locale_to_utf8 (
508 local_contents, -1, NULL, NULL, error);
509
510 if (utf8 == NULL) {
511 success = FALSE;
512 goto exit;
513 }
514
515 g_free (local_contents);
516 local_contents = utf8;
517 }
518
519 g_free (mime_type);
520
521 /* Try and guess the content type of the script output
522 * so it can be applied correctly to the mail message. */
523 guessed_content_type = g_content_type_guess (
524 NULL, (guchar *) local_contents,
525 strlen (local_contents), NULL);
526 mime_type = g_content_type_get_mime_type (guessed_content_type);
527 g_free (guessed_content_type);
528
529 exit:
530 if (success) {
531 const gchar *ext_mime_type;
532
533 if (length != NULL)
534 *length = strlen (local_contents);
535
536 *contents = local_contents;
537 local_contents = NULL;
538
539 ext_mime_type =
540 e_source_mail_signature_get_mime_type (extension);
541
542 /* Don't override the MIME type if it's already set. */
543 if (ext_mime_type == NULL || *ext_mime_type == '\0')
544 e_source_mail_signature_set_mime_type (
545 extension, mime_type);
546 }
547
548 g_object_unref (file_info);
549 g_free (local_contents);
550 g_free (mime_type);
551
552 return success;
553 }
554
555 /**
556 * e_source_mail_signature_load:
557 * @source: an #ESource
558 * @io_priority: the I/O priority of the request
559 * @cancellable: optional #GCancellable object, or %NULL
560 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
561 * @user_data: data to pass to the callback function
562 *
563 * Asynchronously loads a signature from the signature file for @source,
564 * which is given by e_source_mail_signature_get_file().
565 *
566 * If the signature file is executable, it will be executed and its output
567 * captured as the email signature content. If the signature file is not
568 * executable, the email signature content is read directly from the file.
569 *
570 * When the operation is finished, @callback will be called. You can
571 * then call e_source_mail_signature_load_finish() to get the result of
572 * the operation.
573 *
574 * Since: 3.6
575 **/
576 void
e_source_mail_signature_load(ESource * source,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)577 e_source_mail_signature_load (ESource *source,
578 gint io_priority,
579 GCancellable *cancellable,
580 GAsyncReadyCallback callback,
581 gpointer user_data)
582 {
583 GSimpleAsyncResult *simple;
584 AsyncContext *async_context;
585
586 g_return_if_fail (E_IS_SOURCE (source));
587
588 async_context = g_slice_new0 (AsyncContext);
589
590 simple = g_simple_async_result_new (
591 G_OBJECT (source), callback, user_data,
592 e_source_mail_signature_load);
593
594 g_simple_async_result_set_check_cancellable (simple, cancellable);
595
596 g_simple_async_result_set_op_res_gpointer (
597 simple, async_context, (GDestroyNotify) async_context_free);
598
599 g_simple_async_result_run_in_thread (
600 simple, source_mail_signature_load_thread,
601 io_priority, cancellable);
602
603 g_object_unref (simple);
604 }
605
606 /**
607 * e_source_mail_signature_load_finish:
608 * @source: an #ESource
609 * @result: a #GAsyncResult
610 * @contents: (out): return location for the signature content
611 * @length: (optional) (out): return location for the length of the signature
612 * content, or %NULL if the length is not needed
613 * @error: return location for a #GError, or %NULL
614 *
615 * Finishes an operation started with e_source_mail_signature_load(). The
616 * signature file contents are placed in @contents, and @length is set to
617 * the size of the @contents string. The @contents string should be freed
618 * with g_free() when no longer needed.
619 *
620 * Returns: %TRUE on success, %FALSE on failure
621 *
622 * Since: 3.6
623 **/
624 gboolean
e_source_mail_signature_load_finish(ESource * source,GAsyncResult * result,gchar ** contents,gsize * length,GError ** error)625 e_source_mail_signature_load_finish (ESource *source,
626 GAsyncResult *result,
627 gchar **contents,
628 gsize *length,
629 GError **error)
630 {
631 GSimpleAsyncResult *simple;
632 AsyncContext *async_context;
633
634 g_return_val_if_fail (
635 g_simple_async_result_is_valid (
636 result, G_OBJECT (source),
637 e_source_mail_signature_load), FALSE);
638
639 g_return_val_if_fail (contents != NULL, FALSE);
640
641 simple = G_SIMPLE_ASYNC_RESULT (result);
642 async_context = g_simple_async_result_get_op_res_gpointer (simple);
643
644 if (g_simple_async_result_propagate_error (simple, error))
645 return FALSE;
646
647 g_return_val_if_fail (async_context->contents != NULL, FALSE);
648
649 *contents = async_context->contents;
650 async_context->contents = NULL;
651
652 if (length != NULL)
653 *length = async_context->length;
654
655 return TRUE;
656 }
657
658 /********************* e_source_mail_signature_replace() *********************/
659
660 /* Helper for e_source_mail_signature_replace() */
661 static void
source_mail_signature_replace_thread(GSimpleAsyncResult * simple,GObject * object,GCancellable * cancellable)662 source_mail_signature_replace_thread (GSimpleAsyncResult *simple,
663 GObject *object,
664 GCancellable *cancellable)
665 {
666 AsyncContext *async_context;
667 GError *error = NULL;
668
669 async_context = g_simple_async_result_get_op_res_gpointer (simple);
670
671 e_source_mail_signature_replace_sync (
672 E_SOURCE (object), async_context->contents,
673 async_context->length, cancellable, &error);
674
675 if (error != NULL)
676 g_simple_async_result_take_error (simple, error);
677 }
678
679 /**
680 * e_source_mail_signature_replace_sync:
681 * @source: an #ESource
682 * @contents: the signature contents
683 * @length: the length of @contents in bytes
684 * @cancellable: optional #GCancellable object, or %NULL
685 * @error: return location for a #GError, or %NULL
686 *
687 * Replaces the signature file for @source with the given @contents
688 * of @length bytes. The signature file for @source is given by
689 * e_source_mail_signature_get_file().
690 *
691 * Returns: %TRUE on success, %FALSE on failure
692 *
693 * Since: 3.6
694 **/
695 gboolean
e_source_mail_signature_replace_sync(ESource * source,const gchar * contents,gsize length,GCancellable * cancellable,GError ** error)696 e_source_mail_signature_replace_sync (ESource *source,
697 const gchar *contents,
698 gsize length,
699 GCancellable *cancellable,
700 GError **error)
701 {
702 ESourceMailSignature *extension;
703 const gchar *extension_name;
704 GFile *file;
705
706 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
707 g_return_val_if_fail (contents != NULL, FALSE);
708
709 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
710 extension = e_source_get_extension (source, extension_name);
711 file = e_source_mail_signature_get_file (extension);
712
713 return g_file_replace_contents (
714 file, contents, length, NULL, FALSE,
715 G_FILE_CREATE_REPLACE_DESTINATION,
716 NULL, cancellable, error);
717 }
718
719 /**
720 * e_source_mail_signature_replace:
721 * @source: an #ESource
722 * @contents: the signature contents
723 * @length: the length of @contents in bytes
724 * @io_priority: the I/O priority of the request
725 * @cancellable: optional #GCancellable object, or %NULL
726 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
727 * @user_data: data to pass to the callback function
728 *
729 * Asynchrously replaces the signature file for @source with the given
730 * @contents of @length bytes. The signature file for @source is given
731 * by e_source_mail_signature_get_file().
732 *
733 * When the operation is finished, @callback will be called. You can
734 * then call e_source_mail_signature_replace_finish() to get the result
735 * of the operation.
736 *
737 * Since: 3.6
738 **/
739 void
e_source_mail_signature_replace(ESource * source,const gchar * contents,gsize length,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)740 e_source_mail_signature_replace (ESource *source,
741 const gchar *contents,
742 gsize length,
743 gint io_priority,
744 GCancellable *cancellable,
745 GAsyncReadyCallback callback,
746 gpointer user_data)
747 {
748 GSimpleAsyncResult *simple;
749 AsyncContext *async_context;
750
751 g_return_if_fail (E_IS_SOURCE (source));
752 g_return_if_fail (contents != NULL);
753
754 async_context = g_slice_new0 (AsyncContext);
755 async_context->contents = g_strdup (contents);
756 async_context->length = length;
757
758 simple = g_simple_async_result_new (
759 G_OBJECT (source), callback, user_data,
760 e_source_mail_signature_replace);
761
762 g_simple_async_result_set_check_cancellable (simple, cancellable);
763
764 g_simple_async_result_set_op_res_gpointer (
765 simple, async_context, (GDestroyNotify) async_context_free);
766
767 g_simple_async_result_run_in_thread (
768 simple, source_mail_signature_replace_thread,
769 io_priority, cancellable);
770
771 g_object_unref (simple);
772 }
773
774 /**
775 * e_source_mail_signature_replace_finish:
776 * @source: an #ESource
777 * @result: a #GAsyncResult
778 * @error: return location for a #GError, or %NULL
779 *
780 * Finishes an operation started with e_source_mail_signature_replace().
781 *
782 * Returns: %TRUE on success, %FALSE on failure
783 *
784 * Since: 3.6
785 **/
786 gboolean
e_source_mail_signature_replace_finish(ESource * source,GAsyncResult * result,GError ** error)787 e_source_mail_signature_replace_finish (ESource *source,
788 GAsyncResult *result,
789 GError **error)
790 {
791 GSimpleAsyncResult *simple;
792
793 g_return_val_if_fail (
794 g_simple_async_result_is_valid (
795 result, G_OBJECT (source),
796 e_source_mail_signature_replace), FALSE);
797
798 simple = G_SIMPLE_ASYNC_RESULT (result);
799
800 /* Assume success unless a GError is set. */
801 return !g_simple_async_result_propagate_error (simple, error);
802 }
803
804 /********************* e_source_mail_signature_symlink() *********************/
805
806 /* Helper for e_source_mail_signature_symlink() */
807 static void
source_mail_signature_symlink_thread(GSimpleAsyncResult * simple,GObject * object,GCancellable * cancellable)808 source_mail_signature_symlink_thread (GSimpleAsyncResult *simple,
809 GObject *object,
810 GCancellable *cancellable)
811 {
812 AsyncContext *async_context;
813 GError *error = NULL;
814
815 async_context = g_simple_async_result_get_op_res_gpointer (simple);
816
817 e_source_mail_signature_symlink_sync (
818 E_SOURCE (object),
819 async_context->symlink_target,
820 cancellable, &error);
821
822 if (error != NULL)
823 g_simple_async_result_take_error (simple, error);
824 }
825
826 /**
827 * e_source_mail_signature_symlink_sync:
828 * @source: an #ESource
829 * @symlink_target: executable filename to link to
830 * @cancellable: optional #GCancellable object, or %NULL
831 * @error: return location for a #GError, or %NULL
832 *
833 * Replaces the signature file for @source with a symbolic link to
834 * @symlink_target, which should be an executable file that prints
835 * a mail signature to standard output. The signature file for
836 * @source is given by e_source_mail_signature_get_file().
837 *
838 * Returns: %TRUE on success, %FALSE on failure
839 *
840 * Since: 3.6
841 **/
842 gboolean
e_source_mail_signature_symlink_sync(ESource * source,const gchar * symlink_target,GCancellable * cancellable,GError ** error)843 e_source_mail_signature_symlink_sync (ESource *source,
844 const gchar *symlink_target,
845 GCancellable *cancellable,
846 GError **error)
847 {
848 ESourceMailSignature *extension;
849 const gchar *extension_name;
850 GFile *file;
851
852 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
853 g_return_val_if_fail (symlink_target != NULL, FALSE);
854
855 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
856 extension = e_source_get_extension (source, extension_name);
857 file = e_source_mail_signature_get_file (extension);
858
859 /* The file may not exist, so we don't care if this fails.
860 * If it fails for a different reason than G_IO_ERROR_NOT_FOUND
861 * then the next step will probably also fail and we'll capture
862 * THAT error. */
863 g_file_delete (file, cancellable, NULL);
864
865 return g_file_make_symbolic_link (
866 file, symlink_target, cancellable, error);
867 }
868
869 /**
870 * e_source_mail_signature_symlink:
871 * @source: an #ESource
872 * @symlink_target: executable filename to link to
873 * @io_priority: the I/O priority of the request
874 * @cancellable: optional #GCancellable object, or %NULL
875 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
876 * @user_data: data to pass to the callback function
877 *
878 * Asynchronously replaces the signature file for @source with a symbolic
879 * link to @symlink_target, which should be an executable file that prints
880 * a mail signature to standard output. The signature file for @source
881 * is given by e_source_mail_signature_get_file().
882 *
883 * When the operation is finished, @callback will be called. You can
884 * then call e_source_mail_signature_symlink_finish() to get the result
885 * of the operation.
886 *
887 * Since: 3.6
888 **/
889 void
e_source_mail_signature_symlink(ESource * source,const gchar * symlink_target,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)890 e_source_mail_signature_symlink (ESource *source,
891 const gchar *symlink_target,
892 gint io_priority,
893 GCancellable *cancellable,
894 GAsyncReadyCallback callback,
895 gpointer user_data)
896 {
897 GSimpleAsyncResult *simple;
898 AsyncContext *async_context;
899
900 g_return_if_fail (E_IS_SOURCE (source));
901 g_return_if_fail (symlink_target != NULL);
902
903 async_context = g_slice_new0 (AsyncContext);
904 async_context->symlink_target = g_strdup (symlink_target);
905
906 simple = g_simple_async_result_new (
907 G_OBJECT (source), callback, user_data,
908 e_source_mail_signature_symlink);
909
910 g_simple_async_result_set_check_cancellable (simple, cancellable);
911
912 g_simple_async_result_set_op_res_gpointer (
913 simple, async_context, (GDestroyNotify) async_context_free);
914
915 g_simple_async_result_run_in_thread (
916 simple, source_mail_signature_symlink_thread,
917 io_priority, cancellable);
918
919 g_object_unref (simple);
920 }
921
922 /**
923 * e_source_mail_signature_symlink_finish:
924 * @source: an #ESource
925 * @result: a #GAsyncResult
926 * @error: return location for a #GError, or %NULL
927 *
928 * Finishes an operation started with e_source_mail_signature_symlink().
929 *
930 * Returns: %TRUE on success, %FALSE on failure
931 *
932 * Since: 3.6
933 **/
934 gboolean
e_source_mail_signature_symlink_finish(ESource * source,GAsyncResult * result,GError ** error)935 e_source_mail_signature_symlink_finish (ESource *source,
936 GAsyncResult *result,
937 GError **error)
938 {
939 GSimpleAsyncResult *simple;
940
941 g_return_val_if_fail (
942 g_simple_async_result_is_valid (
943 result, G_OBJECT (source),
944 e_source_mail_signature_symlink), FALSE);
945
946 simple = G_SIMPLE_ASYNC_RESULT (result);
947
948 /* Assume success unless a GError is set. */
949 return !g_simple_async_result_propagate_error (simple, error);
950 }
951
952