I#27 - [IMAPx] Ignore DavMail's CR/LF in BODYSTRUCTURE response
[evolution-data-server.git] / src / libedataserver / e-source-mail-signature.c
blob3807fcdf29af210e04a8e3d9aafde7a0738a7949
1 /*
2 * e-source-mail-signature.c
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.
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.
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/>.
18 /**
19 * SECTION: e-source-mail-signature
20 * @include: libedataserver/libedataserver.h
21 * @short_description: #ESource extension for email signatures
23 * The #ESourceMailSignature extension refers to a personalized email
24 * signature.
26 * Access the extension as follows:
28 * |[
29 * #include <libedataserver/libedataserver.h>
31 * ESourceMailSignature *extension;
33 * extension = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_SIGNATURE);
34 * ]|
35 **/
37 #include "evolution-data-server-config.h"
39 #include <string.h>
40 #include <glib/gi18n-lib.h>
42 #include <libedataserver/e-data-server-util.h>
44 #include "e-source-mail-signature.h"
46 #define E_SOURCE_MAIL_SIGNATURE_GET_PRIVATE(obj) \
47 (G_TYPE_INSTANCE_GET_PRIVATE \
48 ((obj), E_TYPE_SOURCE_MAIL_SIGNATURE, ESourceMailSignaturePrivate))
50 typedef struct _AsyncContext AsyncContext;
52 struct _ESourceMailSignaturePrivate {
53 GFile *file;
54 gchar *mime_type;
57 struct _AsyncContext {
58 gchar *contents;
59 gchar *symlink_target;
60 gsize length;
63 enum {
64 PROP_0,
65 PROP_FILE,
66 PROP_MIME_TYPE
69 G_DEFINE_TYPE (
70 ESourceMailSignature,
71 e_source_mail_signature,
72 E_TYPE_SOURCE_EXTENSION)
74 static void
75 async_context_free (AsyncContext *async_context)
77 g_free (async_context->contents);
78 g_free (async_context->symlink_target);
80 g_slice_free (AsyncContext, async_context);
83 static void
84 source_mail_signature_set_property (GObject *object,
85 guint property_id,
86 const GValue *value,
87 GParamSpec *pspec)
89 switch (property_id) {
90 case PROP_MIME_TYPE:
91 e_source_mail_signature_set_mime_type (
92 E_SOURCE_MAIL_SIGNATURE (object),
93 g_value_get_string (value));
94 return;
97 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100 static void
101 source_mail_signature_get_property (GObject *object,
102 guint property_id,
103 GValue *value,
104 GParamSpec *pspec)
106 switch (property_id) {
107 case PROP_FILE:
108 g_value_set_object (
109 value,
110 e_source_mail_signature_get_file (
111 E_SOURCE_MAIL_SIGNATURE (object)));
112 return;
114 case PROP_MIME_TYPE:
115 g_value_take_string (
116 value,
117 e_source_mail_signature_dup_mime_type (
118 E_SOURCE_MAIL_SIGNATURE (object)));
119 return;
122 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
125 static void
126 source_mail_signature_dispose (GObject *object)
128 ESourceMailSignaturePrivate *priv;
130 priv = E_SOURCE_MAIL_SIGNATURE_GET_PRIVATE (object);
132 if (priv->file != NULL) {
133 g_object_unref (priv->file);
134 priv->file = NULL;
137 /* Chain up to parent's dispose() method. */
138 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->
139 dispose (object);
142 static void
143 source_mail_signature_finalize (GObject *object)
145 ESourceMailSignaturePrivate *priv;
147 priv = E_SOURCE_MAIL_SIGNATURE_GET_PRIVATE (object);
149 g_free (priv->mime_type);
151 /* Chain up to parent's finalize() method. */
152 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->
153 finalize (object);
156 static void
157 source_mail_signature_constructed (GObject *object)
159 ESourceMailSignaturePrivate *priv;
160 ESourceExtension *extension;
161 ESource *source;
162 const gchar *config_dir;
163 const gchar *uid;
164 gchar *base_dir;
165 gchar *path;
167 priv = E_SOURCE_MAIL_SIGNATURE_GET_PRIVATE (object);
169 /* Chain up to parent's constructed() method. */
170 G_OBJECT_CLASS (e_source_mail_signature_parent_class)->constructed (object);
172 extension = E_SOURCE_EXTENSION (object);
173 source = e_source_extension_ref_source (extension);
174 uid = e_source_get_uid (source);
176 config_dir = e_get_user_config_dir ();
177 base_dir = g_build_filename (config_dir, "signatures", NULL);
178 path = g_build_filename (base_dir, uid, NULL);
179 priv->file = g_file_new_for_path (path);
180 g_mkdir_with_parents (base_dir, 0700);
181 g_free (base_dir);
182 g_free (path);
184 g_object_unref (source);
187 static void
188 e_source_mail_signature_class_init (ESourceMailSignatureClass *class)
190 GObjectClass *object_class;
191 ESourceExtensionClass *extension_class;
193 g_type_class_add_private (
194 class, sizeof (ESourceMailSignaturePrivate));
196 object_class = G_OBJECT_CLASS (class);
197 object_class->set_property = source_mail_signature_set_property;
198 object_class->get_property = source_mail_signature_get_property;
199 object_class->dispose = source_mail_signature_dispose;
200 object_class->finalize = source_mail_signature_finalize;
201 object_class->constructed = source_mail_signature_constructed;
203 extension_class = E_SOURCE_EXTENSION_CLASS (class);
204 extension_class->name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
206 g_object_class_install_property (
207 object_class,
208 PROP_FILE,
209 g_param_spec_object (
210 "file",
211 "File",
212 "File containing signature content",
213 G_TYPE_FILE,
214 G_PARAM_READABLE |
215 G_PARAM_STATIC_STRINGS));
217 g_object_class_install_property (
218 object_class,
219 PROP_MIME_TYPE,
220 g_param_spec_string (
221 "mime-type",
222 "MIME Type",
223 "MIME type of the signature content",
224 NULL,
225 G_PARAM_READWRITE |
226 G_PARAM_CONSTRUCT |
227 G_PARAM_STATIC_STRINGS |
228 E_SOURCE_PARAM_SETTING));
231 static void
232 e_source_mail_signature_init (ESourceMailSignature *extension)
234 extension->priv = E_SOURCE_MAIL_SIGNATURE_GET_PRIVATE (extension);
238 * e_source_mail_signature_get_file:
239 * @extension: an #ESourceMailSignature
241 * Returns a #GFile instance pointing to the signature file for @extension.
242 * The signature file may be a regular file containing the static signature
243 * content, or it may be a symbolic link to an executable file that produces
244 * the signature content.
246 * e_source_mail_signature_load() uses this to load the signature content.
248 * Returns: (transfer none): a #GFile
250 * Since: 3.6
252 GFile *
253 e_source_mail_signature_get_file (ESourceMailSignature *extension)
255 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
257 return extension->priv->file;
261 * e_source_mail_signature_get_mime_type:
262 * @extension: an #ESourceMailSignature
264 * Returns the MIME type of the signature content for @extension, or %NULL
265 * if it has not yet been determined.
267 * e_source_mail_signature_load() sets this automatically if the MIME type
268 * has not yet been determined.
270 * Returns: (nullable): the MIME type of the signature content, or %NULL
272 * Since: 3.6
274 const gchar *
275 e_source_mail_signature_get_mime_type (ESourceMailSignature *extension)
277 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
279 return extension->priv->mime_type;
283 * e_source_mail_signature_dup_mime_type:
284 * @extension: an #ESourceMailSignature
286 * Thread-safe variation of e_source_mail_signature_get_mime_type().
287 * Use this function when accessing @extension from multiple threads.
289 * The returned string should be freed with g_free() when no longer needed.
291 * Returns: (nullable): a newly-allocated copy of #ESourceMailSignature:mime-type,
292 * or %NULL
294 * Since: 3.6
296 gchar *
297 e_source_mail_signature_dup_mime_type (ESourceMailSignature *extension)
299 const gchar *protected;
300 gchar *duplicate;
302 g_return_val_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension), NULL);
304 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
306 protected = e_source_mail_signature_get_mime_type (extension);
307 duplicate = g_strdup (protected);
309 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
311 return duplicate;
315 * e_source_mail_signature_set_mime_type:
316 * @extension: an #ESourceMailSignature
317 * @mime_type: (allow-none): a MIME type, or %NULL
319 * Sets the MIME type of the signature content for @extension.
321 * e_source_mail_signature_load() sets this automatically if the MIME type
322 * has not yet been determined.
324 * The internal copy of @mime_type is automatically stripped of leading
325 * and trailing whitespace. If the resulting string is empty, %NULL is
326 * set instead.
328 * Since: 3.6
330 void
331 e_source_mail_signature_set_mime_type (ESourceMailSignature *extension,
332 const gchar *mime_type)
334 g_return_if_fail (E_IS_SOURCE_MAIL_SIGNATURE (extension));
336 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
338 if (g_strcmp0 (extension->priv->mime_type, mime_type) == 0) {
339 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
340 return;
343 g_free (extension->priv->mime_type);
344 extension->priv->mime_type = e_util_strdup_strip (mime_type);
346 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
348 g_object_notify (G_OBJECT (extension), "mime-type");
351 /********************** e_source_mail_signature_load() ***********************/
353 /* Helper for e_source_mail_signature_load() */
354 static void
355 source_mail_signature_load_thread (GSimpleAsyncResult *simple,
356 GObject *object,
357 GCancellable *cancellable)
359 AsyncContext *async_context;
360 GError *error = NULL;
362 async_context = g_simple_async_result_get_op_res_gpointer (simple);
364 e_source_mail_signature_load_sync (
365 E_SOURCE (object),
366 &async_context->contents,
367 &async_context->length,
368 cancellable, &error);
370 if (error != NULL)
371 g_simple_async_result_take_error (simple, error);
375 * e_source_mail_signature_load_sync:
376 * @source: an #ESource
377 * @contents: (out): return location for the signature content
378 * @length: (allow-none) (out): return location for the length of the signature
379 * content, or %NULL if the length is not needed
380 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
381 * @error: return location for a #GError, or %NULL
383 * Loads a signature from the signature file for @source, which is
384 * given by e_source_mail_signature_get_file(). The signature contents
385 * are placed in @contents, and @length is set to the size of the @contents
386 * string. The @contents string should be freed with g_free() when no
387 * longer needed.
389 * If the signature file is executable, it will be executed and its output
390 * captured as the email signature content. If the signature file is not
391 * executable, the email signature content is read directly from the file.
393 * Returns: %TRUE on success, %FALSE on failure
395 * Since: 3.6
397 gboolean
398 e_source_mail_signature_load_sync (ESource *source,
399 gchar **contents,
400 gsize *length,
401 GCancellable *cancellable,
402 GError **error)
404 ESourceMailSignature *extension;
405 GFileInfo *file_info;
406 GFile *file;
407 const gchar *content_type;
408 const gchar *extension_name;
409 gchar *local_contents = NULL;
410 gboolean can_execute;
411 gboolean success;
412 gchar *guessed_content_type;
413 gchar *command_line;
414 gchar *mime_type;
415 gchar *path;
417 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
418 g_return_val_if_fail (contents != NULL, FALSE);
420 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
421 extension = e_source_get_extension (source, extension_name);
422 file = e_source_mail_signature_get_file (extension);
424 file_info = g_file_query_info (
425 file,
426 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE ","
427 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
428 G_FILE_QUERY_INFO_NONE,
429 cancellable, error);
431 if (file_info == NULL)
432 return FALSE;
434 can_execute = g_file_info_get_attribute_boolean (
435 file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE);
437 content_type = g_file_info_get_content_type (file_info);
438 mime_type = g_content_type_get_mime_type (content_type);
440 if (can_execute)
441 goto execute;
443 /*** Load signature file contents ***/
445 success = g_file_load_contents (
446 file, cancellable, &local_contents, NULL, NULL, error);
448 if (!success)
449 goto exit;
451 g_return_val_if_fail (local_contents != NULL, FALSE);
453 /* Signatures are saved as UTF-8, but we still need to check that
454 * the signature is valid UTF-8 because the user may be opening a
455 * signature file this is in his/her locale character set. If it
456 * is not UTF-8 then try converting from the current locale. */
457 if (!g_utf8_validate (local_contents, -1, NULL)) {
458 gchar *utf8;
460 utf8 = g_locale_to_utf8 (
461 local_contents, -1, NULL, NULL, error);
463 if (utf8 == NULL) {
464 success = FALSE;
465 goto exit;
468 g_free (local_contents);
469 local_contents = utf8;
472 goto exit;
474 execute:
476 /*** Execute signature file and capture output ***/
478 path = g_file_get_path (file);
480 if (path == NULL) {
481 g_set_error (
482 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
483 _("Signature script must be a local file"));
484 success = FALSE;
485 goto exit;
488 /* Enclose the path in single-quotes for compatibility on Windows.
489 * (See g_spawn_command_line_sync() documentation for rationale.) */
490 command_line = g_strdup_printf ("'%s'", path);
492 success = g_spawn_command_line_sync (
493 command_line, &local_contents, NULL, NULL, error);
495 g_free (command_line);
496 g_free (path);
498 /* Check if we failed to spawn the script. */
499 if (!success)
500 goto exit;
502 /* Check if we were cancelled while the script was running. */
503 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
504 success = FALSE;
505 goto exit;
508 g_return_val_if_fail (local_contents != NULL, FALSE);
510 /* Signature scripts are supposed to generate UTF-8 content, but
511 * because users are known to never read the manual, we try to do
512 * our best if the content isn't valid UTF-8 by assuming that the
513 * content is in the user's locale character set. */
514 if (!g_utf8_validate (local_contents, -1, NULL)) {
515 gchar *utf8;
517 utf8 = g_locale_to_utf8 (
518 local_contents, -1, NULL, NULL, error);
520 if (utf8 == NULL) {
521 success = FALSE;
522 goto exit;
525 g_free (local_contents);
526 local_contents = utf8;
529 g_free (mime_type);
531 /* Try and guess the content type of the script output
532 * so it can be applied correctly to the mail message. */
533 guessed_content_type = g_content_type_guess (
534 NULL, (guchar *) local_contents,
535 strlen (local_contents), NULL);
536 mime_type = g_content_type_get_mime_type (guessed_content_type);
537 g_free (guessed_content_type);
539 exit:
540 if (success) {
541 const gchar *ext_mime_type;
543 if (length != NULL)
544 *length = strlen (local_contents);
546 *contents = local_contents;
547 local_contents = NULL;
549 ext_mime_type =
550 e_source_mail_signature_get_mime_type (extension);
552 /* Don't override the MIME type if it's already set. */
553 if (ext_mime_type == NULL || *ext_mime_type == '\0')
554 e_source_mail_signature_set_mime_type (
555 extension, mime_type);
558 g_object_unref (file_info);
559 g_free (local_contents);
560 g_free (mime_type);
562 return success;
566 * e_source_mail_signature_load:
567 * @source: an #ESource
568 * @io_priority: the I/O priority of the request
569 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
570 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
571 * is satisfied
572 * @user_data: (closure): data to pass to the callback function
574 * Asynchronously loads a signature from the signature file for @source,
575 * which is given by e_source_mail_signature_get_file().
577 * If the signature file is executable, it will be executed and its output
578 * captured as the email signature content. If the signature file is not
579 * executable, the email signature content is read directly from the file.
581 * When the operation is finished, @callback will be called. You can
582 * then call e_source_mail_signature_load_finish() to get the result of
583 * the operation.
585 * Since: 3.6
587 void
588 e_source_mail_signature_load (ESource *source,
589 gint io_priority,
590 GCancellable *cancellable,
591 GAsyncReadyCallback callback,
592 gpointer user_data)
594 GSimpleAsyncResult *simple;
595 AsyncContext *async_context;
597 g_return_if_fail (E_IS_SOURCE (source));
599 async_context = g_slice_new0 (AsyncContext);
601 simple = g_simple_async_result_new (
602 G_OBJECT (source), callback, user_data,
603 e_source_mail_signature_load);
605 g_simple_async_result_set_check_cancellable (simple, cancellable);
607 g_simple_async_result_set_op_res_gpointer (
608 simple, async_context, (GDestroyNotify) async_context_free);
610 g_simple_async_result_run_in_thread (
611 simple, source_mail_signature_load_thread,
612 io_priority, cancellable);
614 g_object_unref (simple);
618 * e_source_mail_signature_load_finish:
619 * @source: an #ESource
620 * @result: a #GAsyncResult
621 * @contents: (out): return location for the signature content
622 * @length: (allow-none) (out): return location for the length of the signature
623 * content, or %NULL if the length is not needed
624 * @error: return location for a #GError, or %NULL
626 * Finishes an operation started with e_source_mail_signature_load(). The
627 * signature file contents are placed in @contents, and @length is set to
628 * the size of the @contents string. The @contents string should be freed
629 * with g_free() when no longer needed.
631 * Returns: %TRUE on success, %FALSE on failure
633 * Since: 3.6
635 gboolean
636 e_source_mail_signature_load_finish (ESource *source,
637 GAsyncResult *result,
638 gchar **contents,
639 gsize *length,
640 GError **error)
642 GSimpleAsyncResult *simple;
643 AsyncContext *async_context;
645 g_return_val_if_fail (
646 g_simple_async_result_is_valid (
647 result, G_OBJECT (source),
648 e_source_mail_signature_load), FALSE);
650 g_return_val_if_fail (contents != NULL, FALSE);
652 simple = G_SIMPLE_ASYNC_RESULT (result);
653 async_context = g_simple_async_result_get_op_res_gpointer (simple);
655 if (g_simple_async_result_propagate_error (simple, error))
656 return FALSE;
658 g_return_val_if_fail (async_context->contents != NULL, FALSE);
660 *contents = async_context->contents;
661 async_context->contents = NULL;
663 if (length != NULL)
664 *length = async_context->length;
666 return TRUE;
669 /********************* e_source_mail_signature_replace() *********************/
671 /* Helper for e_source_mail_signature_replace() */
672 static void
673 source_mail_signature_replace_thread (GSimpleAsyncResult *simple,
674 GObject *object,
675 GCancellable *cancellable)
677 AsyncContext *async_context;
678 GError *error = NULL;
680 async_context = g_simple_async_result_get_op_res_gpointer (simple);
682 e_source_mail_signature_replace_sync (
683 E_SOURCE (object), async_context->contents,
684 async_context->length, cancellable, &error);
686 if (error != NULL)
687 g_simple_async_result_take_error (simple, error);
691 * e_source_mail_signature_replace_sync:
692 * @source: an #ESource
693 * @contents: the signature contents
694 * @length: the length of @contents in bytes
695 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
696 * @error: return location for a #GError, or %NULL
698 * Replaces the signature file for @source with the given @contents
699 * of @length bytes. The signature file for @source is given by
700 * e_source_mail_signature_get_file().
702 * Returns: %TRUE on success, %FALSE on failure
704 * Since: 3.6
706 gboolean
707 e_source_mail_signature_replace_sync (ESource *source,
708 const gchar *contents,
709 gsize length,
710 GCancellable *cancellable,
711 GError **error)
713 ESourceMailSignature *extension;
714 const gchar *extension_name;
715 GFile *file;
717 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
718 g_return_val_if_fail (contents != NULL, FALSE);
720 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
721 extension = e_source_get_extension (source, extension_name);
722 file = e_source_mail_signature_get_file (extension);
724 return g_file_replace_contents (
725 file, contents, length, NULL, FALSE,
726 G_FILE_CREATE_REPLACE_DESTINATION,
727 NULL, cancellable, error);
731 * e_source_mail_signature_replace:
732 * @source: an #ESource
733 * @contents: the signature contents
734 * @length: the length of @contents in bytes
735 * @io_priority: the I/O priority of the request
736 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
737 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
738 * is satisfied
739 * @user_data: (closure): data to pass to the callback function
741 * Asynchrously replaces the signature file for @source with the given
742 * @contents of @length bytes. The signature file for @source is given
743 * by e_source_mail_signature_get_file().
745 * When the operation is finished, @callback will be called. You can
746 * then call e_source_mail_signature_replace_finish() to get the result
747 * of the operation.
749 * Since: 3.6
751 void
752 e_source_mail_signature_replace (ESource *source,
753 const gchar *contents,
754 gsize length,
755 gint io_priority,
756 GCancellable *cancellable,
757 GAsyncReadyCallback callback,
758 gpointer user_data)
760 GSimpleAsyncResult *simple;
761 AsyncContext *async_context;
763 g_return_if_fail (E_IS_SOURCE (source));
764 g_return_if_fail (contents != NULL);
766 async_context = g_slice_new0 (AsyncContext);
767 async_context->contents = g_strdup (contents);
768 async_context->length = length;
770 simple = g_simple_async_result_new (
771 G_OBJECT (source), callback, user_data,
772 e_source_mail_signature_replace);
774 g_simple_async_result_set_check_cancellable (simple, cancellable);
776 g_simple_async_result_set_op_res_gpointer (
777 simple, async_context, (GDestroyNotify) async_context_free);
779 g_simple_async_result_run_in_thread (
780 simple, source_mail_signature_replace_thread,
781 io_priority, cancellable);
783 g_object_unref (simple);
787 * e_source_mail_signature_replace_finish:
788 * @source: an #ESource
789 * @result: a #GAsyncResult
790 * @error: return location for a #GError, or %NULL
792 * Finishes an operation started with e_source_mail_signature_replace().
794 * Returns: %TRUE on success, %FALSE on failure
796 * Since: 3.6
798 gboolean
799 e_source_mail_signature_replace_finish (ESource *source,
800 GAsyncResult *result,
801 GError **error)
803 GSimpleAsyncResult *simple;
805 g_return_val_if_fail (
806 g_simple_async_result_is_valid (
807 result, G_OBJECT (source),
808 e_source_mail_signature_replace), FALSE);
810 simple = G_SIMPLE_ASYNC_RESULT (result);
812 /* Assume success unless a GError is set. */
813 return !g_simple_async_result_propagate_error (simple, error);
816 /********************* e_source_mail_signature_symlink() *********************/
818 /* Helper for e_source_mail_signature_symlink() */
819 static void
820 source_mail_signature_symlink_thread (GSimpleAsyncResult *simple,
821 GObject *object,
822 GCancellable *cancellable)
824 AsyncContext *async_context;
825 GError *error = NULL;
827 async_context = g_simple_async_result_get_op_res_gpointer (simple);
829 e_source_mail_signature_symlink_sync (
830 E_SOURCE (object),
831 async_context->symlink_target,
832 cancellable, &error);
834 if (error != NULL)
835 g_simple_async_result_take_error (simple, error);
839 * e_source_mail_signature_symlink_sync:
840 * @source: an #ESource
841 * @symlink_target: executable filename to link to
842 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
843 * @error: return location for a #GError, or %NULL
845 * Replaces the signature file for @source with a symbolic link to
846 * @symlink_target, which should be an executable file that prints
847 * a mail signature to standard output. The signature file for
848 * @source is given by e_source_mail_signature_get_file().
850 * Returns: %TRUE on success, %FALSE on failure
852 * Since: 3.6
854 gboolean
855 e_source_mail_signature_symlink_sync (ESource *source,
856 const gchar *symlink_target,
857 GCancellable *cancellable,
858 GError **error)
860 ESourceMailSignature *extension;
861 const gchar *extension_name;
862 GFile *file;
864 g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
865 g_return_val_if_fail (symlink_target != NULL, FALSE);
867 extension_name = E_SOURCE_EXTENSION_MAIL_SIGNATURE;
868 extension = e_source_get_extension (source, extension_name);
869 file = e_source_mail_signature_get_file (extension);
871 /* The file may not exist, so we don't care if this fails.
872 * If it fails for a different reason than G_IO_ERROR_NOT_FOUND
873 * then the next step will probably also fail and we'll capture
874 * THAT error. */
875 g_file_delete (file, cancellable, NULL);
877 return g_file_make_symbolic_link (
878 file, symlink_target, cancellable, error);
882 * e_source_mail_signature_symlink:
883 * @source: an #ESource
884 * @symlink_target: executable filename to link to
885 * @io_priority: the I/O priority of the request
886 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
887 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
888 * is satisfied
889 * @user_data: (closure): data to pass to the callback function
891 * Asynchronously replaces the signature file for @source with a symbolic
892 * link to @symlink_target, which should be an executable file that prints
893 * a mail signature to standard output. The signature file for @source
894 * is given by e_source_mail_signature_get_file().
896 * When the operation is finished, @callback will be called. You can
897 * then call e_source_mail_signature_symlink_finish() to get the result
898 * of the operation.
900 * Since: 3.6
902 void
903 e_source_mail_signature_symlink (ESource *source,
904 const gchar *symlink_target,
905 gint io_priority,
906 GCancellable *cancellable,
907 GAsyncReadyCallback callback,
908 gpointer user_data)
910 GSimpleAsyncResult *simple;
911 AsyncContext *async_context;
913 g_return_if_fail (E_IS_SOURCE (source));
914 g_return_if_fail (symlink_target != NULL);
916 async_context = g_slice_new0 (AsyncContext);
917 async_context->symlink_target = g_strdup (symlink_target);
919 simple = g_simple_async_result_new (
920 G_OBJECT (source), callback, user_data,
921 e_source_mail_signature_symlink);
923 g_simple_async_result_set_check_cancellable (simple, cancellable);
925 g_simple_async_result_set_op_res_gpointer (
926 simple, async_context, (GDestroyNotify) async_context_free);
928 g_simple_async_result_run_in_thread (
929 simple, source_mail_signature_symlink_thread,
930 io_priority, cancellable);
932 g_object_unref (simple);
936 * e_source_mail_signature_symlink_finish:
937 * @source: an #ESource
938 * @result: a #GAsyncResult
939 * @error: return location for a #GError, or %NULL
941 * Finishes an operation started with e_source_mail_signature_symlink().
943 * Returns: %TRUE on success, %FALSE on failure
945 * Since: 3.6
947 gboolean
948 e_source_mail_signature_symlink_finish (ESource *source,
949 GAsyncResult *result,
950 GError **error)
952 GSimpleAsyncResult *simple;
954 g_return_val_if_fail (
955 g_simple_async_result_is_valid (
956 result, G_OBJECT (source),
957 e_source_mail_signature_symlink), FALSE);
959 simple = G_SIMPLE_ASYNC_RESULT (result);
961 /* Assume success unless a GError is set. */
962 return !g_simple_async_result_propagate_error (simple, error);