/** * mail_importer_add_line: * importer: A MailImporter structure. * str: Next line of the mbox. * finished: TRUE if @str is the last line of the message. * * Adds lines to the message until it is finished, and then adds * the complete message to the folder. */ void mail_importer_add_line (MailImporter *importer, const char *str, gboolean finished) { CamelMimeMessage *msg; CamelMessageInfo *info; CamelException *ex; if (importer->mstream == NULL) importer->mstream = CAMEL_STREAM_MEM (camel_stream_mem_new ()); camel_stream_write (CAMEL_STREAM (importer->mstream), str, strlen (str)); if (finished == FALSE) return; camel_stream_reset (CAMEL_STREAM (importer->mstream)); info = camel_message_info_new(NULL); camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); msg = camel_mime_message_new (); camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), CAMEL_STREAM (importer->mstream)); camel_object_unref (importer->mstream); importer->mstream = NULL; ex = camel_exception_new (); camel_folder_append_message (importer->folder, msg, info, NULL, ex); camel_object_unref (msg); camel_exception_free (ex); camel_message_info_free(info); }
static gboolean emss_process_message (struct _write_msg *msg) { struct _EMSyncStream *emss = msg->emss; /* Force out any pending data before doing anything else. */ if (emss->buffer != NULL && emss->buffer->len > 0) { EMSS_CLASS (emss)->sync_write ( CAMEL_STREAM (emss), emss->buffer->str, emss->buffer->len); g_string_set_size (emss->buffer, 0); } switch (msg->op) { case EMSS_WRITE: EMSS_CLASS (emss)->sync_write ( CAMEL_STREAM (emss), msg->string, msg->len); break; case EMSS_FLUSH: EMSS_CLASS (emss)->sync_flush ( CAMEL_STREAM (emss)); break; case EMSS_CLOSE: EMSS_CLASS (emss)->sync_close ( CAMEL_STREAM (emss)); break; } e_flag_set (msg->done); return FALSE; }
/* there is also an identical copy of this in camel-filter-search.c */ gboolean camel_search_message_body_contains (CamelDataWrapper *object, regex_t *pattern) { CamelDataWrapper *containee; int truth = FALSE; int parts, i; containee = camel_medium_get_content_object (CAMEL_MEDIUM (object)); if (containee == NULL) return FALSE; /* using the object types is more accurate than using the mime/types */ if (CAMEL_IS_MULTIPART (containee)) { parts = camel_multipart_get_number (CAMEL_MULTIPART (containee)); for (i = 0; i < parts && truth == FALSE; i++) { CamelDataWrapper *part = (CamelDataWrapper *)camel_multipart_get_part (CAMEL_MULTIPART (containee), i); if (part) truth = camel_search_message_body_contains (part, pattern); } } else if (CAMEL_IS_MIME_MESSAGE (containee)) { /* for messages we only look at its contents */ truth = camel_search_message_body_contains ((CamelDataWrapper *)containee, pattern); } else if (camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "text", "*")) { /* for all other text parts, we look inside, otherwise we dont care */ CamelStreamMem *mem = (CamelStreamMem *)camel_stream_mem_new (); camel_data_wrapper_write_to_stream (containee, CAMEL_STREAM (mem)); camel_stream_write (CAMEL_STREAM (mem), "", 1); truth = regexec (pattern, (char *) mem->buffer->data, 0, NULL, 0) == 0; camel_object_unref (mem); } return truth; }
static int stream_flush (CamelStream *stream) { CamelSeekableSubstream *sus = (CamelSeekableSubstream *)stream; return camel_stream_flush(CAMEL_STREAM(sus->parent_stream)); }
/** * camel_stream_mem_new_with_byte_array: * @buffer: a #GByteArray to use as the stream data * * Create a new #CamelStreamMem using @buffer as the stream data. * * Note: The newly created #CamelStreamMem will destroy @buffer * when destroyed. * * Returns a new #CamelStreamMem **/ CamelStream * camel_stream_mem_new_with_byte_array (GByteArray *buffer) { CamelStreamMem *stream_mem; stream_mem = CAMEL_STREAM_MEM (camel_object_new (CAMEL_STREAM_MEM_TYPE)); stream_mem->buffer = buffer; stream_mem->owner = TRUE; return CAMEL_STREAM (stream_mem); }
/** * camel_stream_vfs_new_with_stream: * @stream: a GInputStream or GOutputStream instance * * Creates a new fs stream using the given gio stream @stream as the * backing store. When the stream is destroyed, the file descriptor * will be closed. This will not increase reference counter on the stream. * * Returns a new #CamelStreamVFS **/ CamelStream * camel_stream_vfs_new_with_stream (GObject *stream) { CamelStreamVFS *stream_vfs; errno = EINVAL; if (!stream) return NULL; g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream) || G_IS_INPUT_STREAM (stream), NULL); errno = 0; stream_vfs = CAMEL_STREAM_VFS (camel_object_new (camel_stream_vfs_get_type ())); stream_vfs->stream = stream; return CAMEL_STREAM (stream_vfs); }
static off_t stream_seek (CamelSeekableStream *seekable_stream, off_t offset, CamelStreamSeekPolicy policy) { CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(seekable_stream); CamelStream *stream = CAMEL_STREAM(seekable_stream); off_t real_offset = 0; stream->eos = FALSE; switch (policy) { case CAMEL_STREAM_SET: real_offset = offset; break; case CAMEL_STREAM_CUR: real_offset = seekable_stream->position + offset; break; case CAMEL_STREAM_END: if (seekable_stream->bound_end == CAMEL_STREAM_UNBOUND) { real_offset = camel_seekable_stream_seek(seekable_substream->parent_stream, offset, CAMEL_STREAM_END); if (real_offset != -1) { if (real_offset<seekable_stream->bound_start) real_offset = seekable_stream->bound_start; seekable_stream->position = real_offset; } return real_offset; } real_offset = seekable_stream->bound_end + offset; break; } if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) real_offset = MIN (real_offset, seekable_stream->bound_end); if (real_offset<seekable_stream->bound_start) real_offset = seekable_stream->bound_start; seekable_stream->position = real_offset; return real_offset; }
/** * camel_seekable_substream_new: * @parent_stream: a #CamelSeekableStream object * @inf_bound: a lower bound * @sup_bound: an upper bound * * Creates a new CamelSeekableSubstream that references the portion * of @parent_stream from @inf_bound to @sup_bound. (If @sup_bound is * #CAMEL_STREAM_UNBOUND, it references to the end of stream, even if * the stream grows.) * * While the substream is open, the caller cannot assume anything about * the current position of @parent_stream. After the substream has been * closed, @parent_stream will stabilize again. * * Return value: the substream **/ CamelStream * camel_seekable_substream_new(CamelSeekableStream *parent_stream, off_t start, off_t end) { CamelSeekableSubstream *seekable_substream; g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (parent_stream), NULL); /* Create the seekable substream. */ seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (camel_object_new (camel_seekable_substream_get_type ())); /* Initialize it. */ seekable_substream->parent_stream = parent_stream; camel_object_ref (parent_stream); /* Set the bound of the substream. We can ignore any possible error * here, because if we fail to seek now, it will try again later. */ camel_seekable_stream_set_bounds ((CamelSeekableStream *)seekable_substream, start, end); return CAMEL_STREAM (seekable_substream); }
/** * camel_imap_message_cache_get: * @cache: the cache * @uid: the UID of the data to get * @part_spec: the part_spec of the data to get * @ex: exception * * Return value: a CamelStream containing the cached data (which the * caller must unref), or %NULL if that data is not cached. **/ CamelStream * camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid, const char *part_spec, CamelException *ex) { CamelStream *stream; char *path, *key; if (uid[0] == 0) return NULL; #ifdef G_OS_WIN32 /* See comment in insert_setup() */ if (!*part_spec) part_spec = "~"; #endif path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); key = strrchr (path, '/') + 1; stream = g_hash_table_lookup (cache->parts, key); if (stream) { camel_stream_reset (CAMEL_STREAM (stream)); camel_object_ref (CAMEL_OBJECT (stream)); g_free (path); return stream; } stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0); if (stream) { cache_put (cache, uid, key, stream); } else { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to cache %s: %s"), part_spec, g_strerror (errno)); } g_free (path); return stream; }
static gboolean eos (CamelStream *stream) { CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM(stream); CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM(stream); CamelSeekableStream *parent; gboolean eos; if (stream->eos) eos = TRUE; else { parent = seekable_substream->parent_stream; if (!parent_reset (seekable_substream, parent)) return TRUE; eos = camel_stream_eos (CAMEL_STREAM (parent)); if (!eos && (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND)) { eos = seekable_stream->position >= seekable_stream->bound_end; } } return eos; }
static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n) { CamelSeekableStream *parent; CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream); CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream); ssize_t v; if (n == 0) return 0; parent = seekable_substream->parent_stream; /* Go to our position in the parent stream. */ if (!parent_reset (seekable_substream, parent)) { stream->eos = TRUE; return 0; } /* Compute how many bytes should be read. */ if (seekable_stream->bound_end != CAMEL_STREAM_UNBOUND) n = MIN (seekable_stream->bound_end - seekable_stream->position, n); if (n == 0) { stream->eos = TRUE; return 0; } v = camel_stream_read (CAMEL_STREAM (parent), buffer, n); /* ignore <0 - it's an error, let the caller deal */ if (v > 0) seekable_stream->position += v; return v; }
static gboolean nntp_folder_append_message_sync (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, gchar **appended_uid, GCancellable *cancellable, GError **error) { CamelStore *parent_store; CamelNNTPStore *nntp_store; CamelNNTPStream *nntp_stream = NULL; CamelStream *filtered_stream; CamelMimeFilter *crlffilter; gint ret; guint u; struct _camel_header_raw *header, *savedhdrs, *n, *tail; const gchar *full_name; gchar *group, *line; gboolean success = TRUE; GError *local_error = NULL; full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); nntp_store = CAMEL_NNTP_STORE (parent_store); /* send 'POST' command */ ret = camel_nntp_command ( nntp_store, cancellable, error, NULL, &line, "post"); if (ret != 340) { if (ret == 440) { g_set_error ( error, CAMEL_FOLDER_ERROR, CAMEL_FOLDER_ERROR_INSUFFICIENT_PERMISSION, _("Posting failed: %s"), line); success = FALSE; } else if (ret != -1) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Posting failed: %s"), line); success = FALSE; } goto exit; } /* the 'Newsgroups: ' header */ group = g_strdup_printf ("Newsgroups: %s\r\n", full_name); /* remove mail 'To', 'CC', and 'BCC' headers */ savedhdrs = NULL; tail = (struct _camel_header_raw *) &savedhdrs; header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers; n = header->next; while (n != NULL) { if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") || !g_ascii_strcasecmp (n->name, "Bcc")) { header->next = n->next; tail->next = n; n->next = NULL; tail = n; } else { header = n; } n = header->next; } nntp_stream = camel_nntp_store_ref_stream (nntp_store); /* setup stream filtering */ filtered_stream = camel_stream_filter_new (CAMEL_STREAM (nntp_stream)); crlffilter = camel_mime_filter_crlf_new ( CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); camel_stream_filter_add ( CAMEL_STREAM_FILTER (filtered_stream), crlffilter); g_object_unref (crlffilter); /* write the message */ if (local_error == NULL) camel_stream_write ( CAMEL_STREAM (nntp_stream), group, strlen (group), cancellable, &local_error); if (local_error == NULL) camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), filtered_stream, cancellable, &local_error); if (local_error == NULL) camel_stream_flush ( filtered_stream, cancellable, &local_error); if (local_error == NULL) camel_stream_write ( CAMEL_STREAM (nntp_stream), "\r\n.\r\n", 5, cancellable, &local_error); if (local_error == NULL) camel_nntp_stream_line ( nntp_stream, (guchar **) &line, &u, cancellable, &local_error); if (local_error == NULL && atoi (line) != 240) local_error = g_error_new_literal ( CAMEL_ERROR, CAMEL_ERROR_GENERIC, line); if (local_error != NULL) { g_propagate_prefixed_error ( error, local_error, _("Posting failed: ")); success = FALSE; } g_object_unref (filtered_stream); g_free (group); header->next = savedhdrs; exit: g_clear_object (&nntp_stream); return success; }
static CamelStream * nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const gchar *id, const gchar *msgid, GCancellable *cancellable, GError **error) { CamelFolder *folder; CamelStore *parent_store; CamelDataCache *nntp_cache; CamelNNTPStore *nntp_store; CamelNNTPStream *nntp_stream = NULL; CamelStream *stream = NULL; gint ret; gchar *line; folder = CAMEL_FOLDER (nntp_folder); parent_store = camel_folder_get_parent_store (folder); nntp_store = CAMEL_NNTP_STORE (parent_store); nntp_cache = camel_nntp_store_ref_cache (nntp_store); ret = camel_nntp_command ( nntp_store, cancellable, error, nntp_folder, &line, "article %s", id); if (ret == 220) { GIOStream *base_stream; nntp_stream = camel_nntp_store_ref_stream (nntp_store); base_stream = camel_data_cache_add ( nntp_cache, "cache", msgid, NULL); if (base_stream != NULL) { gboolean success; stream = camel_stream_new (base_stream); g_object_unref (base_stream); success = (camel_stream_write_to_stream ( CAMEL_STREAM (nntp_stream), stream, cancellable, error) != -1); if (!success) goto fail; success = g_seekable_seek ( G_SEEKABLE (stream), 0, G_SEEK_SET, cancellable, error); if (!success) goto fail; } else { stream = g_object_ref (nntp_stream); } } else if (ret == 423 || ret == 430) { g_set_error ( error, CAMEL_FOLDER_ERROR, CAMEL_FOLDER_ERROR_INVALID_UID, _("Cannot get message %s: %s"), msgid, line); } else if (ret != -1) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot get message %s: %s"), msgid, line); } goto exit; fail: camel_data_cache_remove (nntp_cache, "cache", msgid, NULL); g_prefix_error (error, _("Cannot get message %s: "), msgid); g_clear_object (&stream); exit: g_clear_object (&nntp_cache); g_clear_object (&nntp_stream); return stream; }
static void nntp_folder_append_message_online (CamelFolder *folder, CamelMimeMessage *mime_message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) { CamelNNTPStore *nntp_store = (CamelNNTPStore *) folder->parent_store; CamelStream *stream = (CamelStream*)nntp_store->stream; CamelStreamFilter *filtered_stream; CamelMimeFilter *crlffilter; int ret; unsigned int u; struct _camel_header_raw *header, *savedhdrs, *n, *tail; char *group, *line; CAMEL_SERVICE_REC_LOCK(nntp_store, connect_lock); /* send 'POST' command */ ret = camel_nntp_command (nntp_store, ex, NULL, &line, "post"); if (ret != 340) { if (ret == 440) camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, _("Posting failed: %s"), line); else if (ret != -1) camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), line); CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock); return; } /* the 'Newsgroups: ' header */ group = g_strdup_printf ("Newsgroups: %s\r\n", folder->full_name); /* setup stream filtering */ crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); filtered_stream = camel_stream_filter_new_with_stream (stream); camel_stream_filter_add (filtered_stream, crlffilter); camel_object_unref (crlffilter); /* remove mail 'To', 'CC', and 'BCC' headers */ savedhdrs = NULL; tail = (struct _camel_header_raw *) &savedhdrs; header = (struct _camel_header_raw *) &CAMEL_MIME_PART (mime_message)->headers; n = header->next; while (n != NULL) { if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") || !g_ascii_strcasecmp (n->name, "Bcc")) { header->next = n->next; tail->next = n; n->next = NULL; tail = n; } else { header = n; } n = header->next; } /* write the message */ if (camel_stream_write(stream, group, strlen(group)) == -1 || camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), CAMEL_STREAM (filtered_stream)) == -1 || camel_stream_flush (CAMEL_STREAM (filtered_stream)) == -1 || camel_stream_write (stream, "\r\n.\r\n", 5) == -1 || (ret = camel_nntp_stream_line (nntp_store->stream, (unsigned char **)&line, &u)) == -1) { if (errno == EINTR) camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), g_strerror (errno)); } else if (atoi(line) != 240) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), line); } camel_object_unref (filtered_stream); g_free(group); header->next = savedhdrs; CAMEL_SERVICE_REC_UNLOCK(nntp_store, connect_lock); return; }
static CamelAuthenticationResult try_sasl (CamelPOP3Store *store, const gchar *mechanism, GCancellable *cancellable, GError **error) { CamelPOP3Engine *pop3_engine; CamelPOP3Stream *pop3_stream; CamelNetworkSettings *network_settings; CamelAuthenticationResult result; CamelSettings *settings; CamelService *service; guchar *line, *resp; CamelSasl *sasl = NULL; gchar *string; gchar *host; guint len; gint ret; service = CAMEL_SERVICE (store); settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); g_object_unref (settings); pop3_engine = camel_pop3_store_ref_engine (store); if (!pop3_engine) { g_set_error_literal ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("You must be working online to complete this operation")); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } pop3_stream = pop3_engine->stream; sasl = camel_sasl_new ("pop", mechanism, service); if (sasl == NULL) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_URL_INVALID, _("No support for %s authentication"), mechanism); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } string = g_strdup_printf ("AUTH %s\r\n", mechanism); ret = camel_stream_write_string ( CAMEL_STREAM (pop3_stream), string, cancellable, error); g_free (string); if (ret == -1) goto ioerror; while (1) { GError *local_error = NULL; if (camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, error) == -1) goto ioerror; if (strncmp ((gchar *) line, "+OK", 3) == 0) { result = CAMEL_AUTHENTICATION_ACCEPTED; break; } if (strncmp ((gchar *) line, "-ERR", 4) == 0) { result = CAMEL_AUTHENTICATION_REJECTED; break; } /* If we dont get continuation, or the sasl object's run out * of work, or we dont get a challenge, its a protocol error, * so fail, and try reset the server. */ if (strncmp ((gchar *) line, "+ ", 2) != 0 || camel_sasl_get_authenticated (sasl) || (resp = (guchar *) camel_sasl_challenge_base64_sync (sasl, (const gchar *) line + 2, cancellable, &local_error)) == NULL) { camel_stream_write_string ( CAMEL_STREAM (pop3_stream), "*\r\n", cancellable, NULL); camel_pop3_stream_line (pop3_stream, &line, &len, cancellable, NULL); if (local_error) { g_propagate_error (error, local_error); local_error = NULL; goto ioerror; } g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Cannot login to POP server %s: " "SASL Protocol error"), host); result = CAMEL_AUTHENTICATION_ERROR; goto exit; } string = g_strdup_printf ("%s\r\n", resp); ret = camel_stream_write_string ( CAMEL_STREAM (pop3_stream), string, cancellable, error); g_free (string); g_free (resp); if (ret == -1) goto ioerror; } goto exit; ioerror: g_prefix_error ( error, _("Failed to authenticate on POP server %s: "), host); result = CAMEL_AUTHENTICATION_ERROR; exit: if (sasl != NULL) g_object_unref (sasl); g_free (host); g_clear_object (&pop3_engine); return result; }
gboolean e_composer_autosave_snapshot (EMsgComposer *composer) { GtkhtmlEditor *editor; CamelMimeMessage *message; AutosaveState *state; CamelStream *stream; gint camelfd; const gchar *errmsg; g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); editor = GTKHTML_EDITOR (composer); /* If the contents are unchanged, exit early. */ if (!gtkhtml_editor_get_changed (editor)) return TRUE; state = g_object_get_data (G_OBJECT (composer), "autosave"); g_return_val_if_fail (state != NULL, FALSE); /* Open the autosave file on-demand. */ if (!composer_autosave_state_open (state, NULL)) { errmsg = _("Could not open autosave file"); goto fail; } /* Extract a MIME message from the composer. */ message = e_msg_composer_get_message_draft (composer); if (message == NULL) { errmsg = _("Unable to retrieve message from editor"); goto fail; } /* Move to the beginning of the autosave file. */ if (lseek (state->fd, (off_t) 0, SEEK_SET) < 0) { camel_object_unref (message); errmsg = g_strerror (errno); goto fail; } /* Destroy the contents of the autosave file. */ if (ftruncate (state->fd, (off_t) 0) < 0) { camel_object_unref (message); errmsg = g_strerror (errno); goto fail; } /* Duplicate the file descriptor for Camel. */ if ((camelfd = dup (state->fd)) < 0) { camel_object_unref (message); errmsg = g_strerror (errno); goto fail; } /* Open a CamelStream to the autosave file. */ stream = camel_stream_fs_new_with_fd (camelfd); /* Write the message to the CamelStream. */ if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), stream) < 0) { camel_object_unref (message); camel_object_unref (stream); errmsg = g_strerror (errno); goto fail; } /* Close the CamelStream. */ if (camel_stream_close (CAMEL_STREAM (stream)) < 0) { camel_object_unref (message); camel_object_unref (stream); errmsg = g_strerror (errno); goto fail; } /* Snapshot was successful; set various flags. */ gtkhtml_editor_set_changed (editor, FALSE); e_composer_autosave_set_saved (composer, TRUE); camel_object_unref (message); camel_object_unref (stream); return TRUE; fail: e_error_run ( GTK_WINDOW (composer), "mail-composer:no-autosave", (state->filename != NULL) ? state->filename : "", errmsg, NULL); return FALSE; }