/** * camel_imap_command_continuation: * @store: the IMAP store * @cmd: buffer containing the response/request data * @cmdlen: command length * @ex: a CamelException * * This method is for sending continuing responses to the IMAP server * after camel_imap_command() or camel_imap_command_response() returns * a continuation response. * * This function assumes you have an exclusive lock on the imap stream. * * Return value: as for camel_imap_command(). On failure, the store's * connect_lock will be released. **/ CamelImapResponse * camel_imap_command_continuation (CamelImapStore *store, const char *cmd, size_t cmdlen, CamelException *ex) { if (!camel_imap_store_connected (store, ex)) return NULL; g_return_val_if_fail(store->ostream!=NULL, NULL); g_return_val_if_fail(store->istream!=NULL, NULL); if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 || camel_stream_write (store->ostream, "\r\n", 2) == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); else camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, g_strerror (errno)); camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); CAMEL_SERVICE_REC_UNLOCK (store, connect_lock); return NULL; } return imap_read_response (store, ex); }
/* 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; }
/** * 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 gssize nntp_stream_write (CamelStream *stream, const gchar *buffer, gsize n, GCancellable *cancellable, GError **error) { CamelNNTPStream *is = (CamelNNTPStream *) stream; return camel_stream_write (is->source, buffer, n, cancellable, error); }
static ssize_t stream_write(CamelStream *stream, const char *buffer, size_t n) { CamelPOP3Stream *is = (CamelPOP3Stream *)stream; if (strncmp (buffer, "PASS ", 5) != 0) dd(printf("POP3_STREAM_WRITE(%d):\n%.*s\n", (int)n, (int)n, buffer)); else dd(printf("POP3_STREAM_WRITE(%d):\nPASS xxxxxxxx\n", (int)n)); return camel_stream_write(is->source, buffer, n); }
static void filter (CamelMimeFilter *f, char *in, size_t len, size_t prespace, char **out, size_t *outlen, size_t *outprespace) { CamelMimeFilterSave *save = (CamelMimeFilterSave *) f; if (save->stream) camel_stream_write (save->stream, in, len); *out = in; *outlen = len; *outprespace = f->outpre; }
static gssize stream_write (CamelStream *stream, const gchar *buffer, gsize n, GCancellable *cancellable, GError **error) { CamelPOP3Stream *is = (CamelPOP3Stream *) stream; if (strncmp (buffer, "PASS ", 5) != 0) dd (printf ("POP3_STREAM_WRITE (%d):\n%.*s\n", (gint)n, (gint)n, buffer)); else dd (printf ("POP3_STREAM_WRITE (%d):\nPASS xxxxxxxx\n", (gint)n)); return camel_stream_write (is->source, buffer, n, cancellable, error); }
static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelSCALIXStream *scalix = (CamelSCALIXStream *) stream; ssize_t nwritten; if (scalix->disconnected) { errno = EINVAL; return -1; } if ((nwritten = camel_stream_write (scalix->stream, buffer, n)) == 0) scalix->disconnected = TRUE; return nwritten; }
static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n) { CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; ssize_t nwritten; if (imap4->disconnected) { errno = EINVAL; return -1; } if ((nwritten = camel_stream_write (imap4->stream, buffer, n)) == 0) imap4->disconnected = TRUE; return nwritten; }
/** * camel_imap_message_cache_insert: * @cache: the cache * @uid: UID of the message data to cache * @part_spec: the IMAP part_spec of the data * @data: the data * @len: length of @data * * Caches the provided data into @cache. * * Return value: a CamelStream containing the cached data, which the * caller must unref. **/ CamelStream * camel_imap_message_cache_insert (CamelImapMessageCache *cache, const char *uid, const char *part_spec, const char *data, int len, CamelException *ex) { char *path, *key; CamelStream *stream; stream = insert_setup (cache, uid, part_spec, &path, &key, ex); if (!stream) return NULL; if (camel_stream_write (stream, data, len) == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to cache message %s: %s"), uid, g_strerror (errno)); return insert_abort (path, stream); } return insert_finish (cache, uid, path, key, stream); }
/* 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; gint truth = FALSE; gint parts, i; containee = camel_medium_get_content (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", "*") || camel_content_type_is(CAMEL_DATA_WRAPPER (containee)->mime_type, "x-evolution", "evolution-rss-feed")) { /* for all other text parts, we look inside, otherwise we dont care */ CamelStream *stream; GByteArray *byte_array; byte_array = g_byte_array_new (); stream = camel_stream_mem_new_with_byte_array (byte_array); camel_data_wrapper_write_to_stream_sync ( containee, stream, NULL, NULL); camel_stream_write (stream, "", 1, NULL, NULL); truth = regexec (pattern, (gchar *) byte_array->data, 0, NULL, 0) == 0; g_object_unref (stream); } return truth; }
static ssize_t stream_write (CamelStream *stream, const 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 written. */ 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_write((CamelStream *)parent, buffer, n); /* ignore <0 - it's an error, let the caller deal */ if (v > 0) seekable_stream->position += v; return v; }
int main (int argc, char **argv) { CamelSession *session; CamelCipherContext *ctx; CamelException *ex; CamelCipherValidity *valid; CamelStream *stream1, *stream2; struct _CamelMimePart *sigpart, *conpart, *encpart, *outpart; CamelDataWrapper *dw; GPtrArray *recipients; GByteArray *buf; char *before, *after; int ret; if (getenv("CAMEL_TEST_GPG") == NULL) return 77; camel_test_init (argc, argv); /* clear out any camel-test data */ system ("/bin/rm -rf /tmp/camel-test"); system ("/bin/mkdir /tmp/camel-test"); setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1); /* import the gpg keys */ if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1) return 77; else if (WEXITSTATUS (ret) == 127) return 77; g_message ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.pub > /dev/null 2>&1"); system ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.pub > /dev/null 2>&1"); g_message ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.sec > /dev/null 2>&1"); system ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.sec > /dev/null 2>&1"); session = camel_pgp_session_new ("/tmp/camel-test"); ex = camel_exception_new (); ctx = camel_gpg_context_new (session); camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE); camel_test_start ("Test of PGP functions"); stream1 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test stream.\n", 27); camel_stream_reset (stream1); conpart = camel_mime_part_new(); dw = camel_data_wrapper_new(); camel_data_wrapper_construct_from_stream(dw, stream1); camel_medium_set_content_object((CamelMedium *)conpart, dw); camel_object_unref(stream1); camel_object_unref(dw); sigpart = camel_mime_part_new(); camel_test_push ("PGP signing"); camel_cipher_sign (ctx, "*****@*****.**", CAMEL_CIPHER_HASH_SHA1, conpart, sigpart, ex); if (camel_exception_is_set(ex)) { printf("PGP signing failed assuming non-functional environment\n%s", camel_exception_get_description (ex)); camel_test_pull(); return 77; } camel_test_pull (); camel_exception_clear (ex); camel_test_push ("PGP verify"); valid = camel_cipher_verify (ctx, sigpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); camel_cipher_validity_free (valid); camel_test_pull (); camel_object_unref(conpart); camel_object_unref(sigpart); stream1 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44); camel_stream_reset (stream1); conpart = camel_mime_part_new(); dw = camel_data_wrapper_new(); camel_stream_reset(stream1); camel_data_wrapper_construct_from_stream(dw, stream1); camel_medium_set_content_object((CamelMedium *)conpart, dw); camel_object_unref(stream1); camel_object_unref(dw); encpart = camel_mime_part_new(); camel_exception_clear (ex); camel_test_push ("PGP encrypt"); recipients = g_ptr_array_new (); g_ptr_array_add (recipients, "*****@*****.**"); camel_cipher_encrypt (ctx, "*****@*****.**", recipients, conpart, encpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); g_ptr_array_free (recipients, TRUE); camel_test_pull (); camel_exception_clear (ex); camel_test_push ("PGP decrypt"); outpart = camel_mime_part_new(); valid = camel_cipher_decrypt (ctx, encpart, outpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); check_msg (valid->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED, "%s", valid->encrypt.description); stream1 = camel_stream_mem_new(); stream2 = camel_stream_mem_new(); camel_data_wrapper_write_to_stream((CamelDataWrapper *)conpart, stream1); camel_data_wrapper_write_to_stream((CamelDataWrapper *)outpart, stream2); buf = CAMEL_STREAM_MEM (stream1)->buffer; before = g_strndup (buf->data, buf->len); buf = CAMEL_STREAM_MEM (stream2)->buffer; after = g_strndup (buf->data, buf->len); check_msg (string_equal (before, after), "before = '%s', after = '%s'", before, after); g_free (before); g_free (after); camel_object_unref(stream1); camel_object_unref(stream2); camel_object_unref(conpart); camel_object_unref(encpart); camel_object_unref(outpart); camel_test_pull (); camel_object_unref (CAMEL_OBJECT (ctx)); camel_object_unref (CAMEL_OBJECT (session)); camel_test_end (); return 0; }
static void mail_attachment_handler_message_rfc822 (EAttachmentView *view, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selection_data, guint info, guint time, EAttachmentHandler *handler) { static GdkAtom atom = GDK_NONE; EAttachmentStore *store; EAttachment *attachment; CamelMimeMessage *message; CamelDataWrapper *wrapper; CamelStream *stream; const gchar *data; gboolean success = FALSE; gpointer parent; gint length; if (G_UNLIKELY (atom == GDK_NONE)) atom = gdk_atom_intern_static_string ("message/rfc822"); if (gtk_selection_data_get_target (selection_data) != atom) return; g_signal_stop_emission_by_name (view, "drag-data-received"); data = (const gchar *) gtk_selection_data_get_data (selection_data); length = gtk_selection_data_get_length (selection_data); stream = camel_stream_mem_new (); camel_stream_write (stream, data, length, NULL, NULL); g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL); message = camel_mime_message_new (); wrapper = CAMEL_DATA_WRAPPER (message); if (!camel_data_wrapper_construct_from_stream_sync ( wrapper, stream, NULL, NULL)) goto exit; store = e_attachment_view_get_store (view); parent = gtk_widget_get_toplevel (GTK_WIDGET (view)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; attachment = e_attachment_new_for_message (message); e_attachment_store_add_attachment (store, attachment); e_attachment_load_async ( attachment, (GAsyncReadyCallback) call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL); g_object_unref (attachment); success = TRUE; exit: g_object_unref (message); g_object_unref (stream); gtk_drag_finish (drag_context, success, FALSE, time); }
static gssize multipart_signed_write_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelMultipartSigned *mps = (CamelMultipartSigned *) data_wrapper; CamelMultipart *mp = (CamelMultipart *) mps; GByteArray *byte_array; const gchar *boundary; gssize total = 0; gssize count; gchar *content; byte_array = camel_data_wrapper_get_byte_array (data_wrapper); /* we have 3 basic cases: * 1. constructed, we write out the data wrapper stream we got * 2. signed content, we create and write out a new stream * 3. invalid */ /* 1 */ /* FIXME: locking? */ if (byte_array->len > 0) { return camel_stream_write ( stream, (gchar *) byte_array->data, byte_array->len, cancellable, error); } /* 3 */ if (mps->contentraw == NULL) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("No content available")); return -1; } /* 3 */ if (mps->signature == NULL) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("No signature available")); return -1; } /* 2 */ boundary = camel_multipart_get_boundary (mp); if (mp->preface) { count = camel_stream_write_string ( stream, mp->preface, cancellable, error); if (count == -1) return -1; total += count; } /* first boundary */ content = g_strdup_printf ("\n--%s\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* output content part */ /* XXX Both CamelGpgContext and CamelSMIMEContext set this * to a memory stream, so assume it's always seekable. */ g_seekable_seek ( G_SEEKABLE (mps->contentraw), 0, G_SEEK_SET, NULL, NULL); count = camel_stream_write_to_stream ( mps->contentraw, stream, cancellable, error); if (count == -1) return -1; total += count; /* boundary */ content = g_strdup_printf ("\n--%s\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* signature */ count = camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (mps->signature), stream, cancellable, error); if (count == -1) return -1; total += count; /* write the terminating boudary delimiter */ content = g_strdup_printf ("\n--%s--\n", boundary); count = camel_stream_write_string ( stream, content, cancellable, error); g_free (content); if (count == -1) return -1; total += count; /* and finally the postface */ if (mp->postface) { count = camel_stream_write_string ( stream, mp->postface, cancellable, error); if (count == -1) return -1; total += count; } return total; }
static gboolean mbox_folder_append_message_sync (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, gchar **appended_uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelStream *output_stream = NULL, *filter_stream = NULL; CamelMimeFilter *filter_from; CamelMboxSummary *mbs = (CamelMboxSummary *) folder->summary; CamelMessageInfo *mi; gchar *fromline = NULL; struct stat st; gint retval; gboolean has_attachment; #if 0 gchar *xev; #endif /* If we can't lock, dont do anything */ if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return FALSE; d (printf ("Appending message\n")); /* first, check the summary is correct (updates folder_size too) */ retval = camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error); if (retval == -1) goto fail; /* add it to the summary/assign the uid, etc */ mi = camel_local_summary_add ((CamelLocalSummary *) folder->summary, message, info, lf->changes, error); if (mi == NULL) goto fail; d (printf ("Appending message: uid is %s\n", camel_message_info_get_uid (mi))); has_attachment = camel_mime_message_has_attachment (message); if (((camel_message_info_get_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) || ((camel_message_info_get_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) { camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0); } output_stream = camel_stream_fs_new_with_name ( lf->folder_path, O_WRONLY | O_APPEND | O_LARGEFILE, 0666, error); if (output_stream == NULL) { g_prefix_error ( error, _("Cannot open mailbox: %s: "), lf->folder_path); goto fail; } /* and we need to set the frompos/XEV explicitly */ ((CamelMboxMessageInfo *) mi)->frompos = mbs->folder_size; #if 0 xev = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) folder->summary, mi); if (xev) { /* the x-ev header should match the 'current' flags, no problem, so store as much */ camel_medium_set_header ((CamelMedium *) message, "X-Evolution", xev); mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED; g_free (xev); } #endif /* we must write this to the non-filtered stream ... */ fromline = camel_mime_message_build_mbox_from (message); if (camel_stream_write (output_stream, fromline, strlen (fromline), cancellable, error) == -1) goto fail_write; /* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */ filter_stream = camel_stream_filter_new (output_stream); filter_from = camel_mime_filter_from_new (); camel_stream_filter_add ((CamelStreamFilter *) filter_stream, filter_from); g_object_unref (filter_from); if (camel_data_wrapper_write_to_stream_sync ( (CamelDataWrapper *) message, filter_stream, cancellable, error) == -1 || camel_stream_write (filter_stream, "\n", 1, cancellable, error) == -1 || camel_stream_flush (filter_stream, cancellable, error) == -1) goto fail_write; /* filter stream ref's the output stream itself, so we need to unref it too */ g_object_unref (filter_stream); g_object_unref (output_stream); g_free (fromline); if (!((CamelMessageInfoBase *) mi)->preview && camel_folder_summary_get_need_preview (folder->summary)) { if (camel_mime_message_build_preview ((CamelMimePart *) message, mi) && ((CamelMessageInfoBase *) mi)->preview) camel_folder_summary_add_preview (folder->summary, mi); } /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ /* the stat really shouldn't fail, we just wrote to it */ if (g_stat (lf->folder_path, &st) == 0) { ((CamelFolderSummary *) mbs)->time = st.st_mtime; mbs->folder_size = st.st_size; } /* unlock as soon as we can */ camel_local_folder_unlock (lf); if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } if (appended_uid) *appended_uid = g_strdup(camel_message_info_get_uid(mi)); return TRUE; fail_write: g_prefix_error ( error, _("Cannot append message to mbox file: %s: "), lf->folder_path); if (output_stream) { gint fd; fd = camel_stream_fs_get_fd (CAMEL_STREAM_FS (output_stream)); if (fd != -1) { /* reset the file to original size */ do { retval = ftruncate (fd, mbs->folder_size); } while (retval == -1 && errno == EINTR); } g_object_unref (output_stream); } if (filter_stream) g_object_unref (filter_stream); g_free (fromline); /* remove the summary info so we are not out-of-sync with the mbox */ camel_folder_summary_remove (CAMEL_FOLDER_SUMMARY (mbs), mi); /* and tell the summary it's up-to-date */ if (g_stat (lf->folder_path, &st) == 0) { ((CamelFolderSummary *) mbs)->time = st.st_mtime; mbs->folder_size = st.st_size; } fail: /* make sure we unlock the folder - before we start triggering events into appland */ camel_local_folder_unlock (lf); /* cascade the changes through, anyway, if there are any outstanding */ if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } return FALSE; }
static CamelAuthenticationResult smtp_transport_authenticate_sync (CamelService *service, const gchar *mechanism, GCancellable *cancellable, GError **error) { CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); CamelAuthenticationResult result; CamelSasl *sasl; gchar *cmdbuf, *respbuf = NULL, *challenge; gboolean auth_challenge = FALSE; GError *local_error = NULL; if (mechanism == NULL) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("No SASL mechanism was specified")); return CAMEL_AUTHENTICATION_ERROR; } sasl = camel_sasl_new ("smtp", mechanism, service); if (sasl == NULL) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("No support for %s authentication"), mechanism); return CAMEL_AUTHENTICATION_ERROR; } challenge = camel_sasl_challenge_base64_sync ( sasl, NULL, cancellable, &local_error); if (challenge) { auth_challenge = TRUE; cmdbuf = g_strdup_printf ( "AUTH %s %s\r\n", mechanism, challenge); g_free (challenge); } else if (local_error) { d (fprintf (stderr, "[SMTP] SASL challenge failed: %s", local_error->message)); g_propagate_error (error, local_error); g_object_unref (sasl); return CAMEL_AUTHENTICATION_ERROR; } else { cmdbuf = g_strdup_printf ( "AUTH %s\r\n", mechanism); } d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf)); if (camel_stream_write_string ( transport->ostream, cmdbuf, cancellable, error) == -1) { g_free (cmdbuf); g_prefix_error (error, _("AUTH command failed: ")); goto lose; } g_free (cmdbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); while (!camel_sasl_get_authenticated (sasl)) { if (!respbuf) { g_prefix_error (error, _("AUTH command failed: ")); transport->connected = FALSE; goto lose; } /* the server may have accepted our initial response */ if (strncmp (respbuf, "235", 3) == 0) break; /* the server challenge/response should follow a 334 code */ if (strncmp (respbuf, "334", 3) != 0) { smtp_set_error ( transport, respbuf, cancellable, error); g_prefix_error (error, _("AUTH command failed: ")); goto lose; } if (FALSE) { broken_smtp_server: d (fprintf ( stderr, "[SMTP] Your SMTP server's implementation " "of the %s SASL\nauthentication mechanism is " "broken. Please report this to the\n" "appropriate vendor and suggest that they " "re-read rfc2554 again\nfor the first time " "(specifically Section 4).\n", mechanism)); } /* eat whtspc */ for (challenge = respbuf + 4; isspace (*challenge); challenge++); challenge = camel_sasl_challenge_base64_sync ( sasl, challenge, cancellable, error); if (challenge == NULL) goto break_and_lose; g_free (respbuf); /* send our challenge */ cmdbuf = g_strdup_printf ("%s\r\n", challenge); g_free (challenge); d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf)); if (camel_stream_write_string ( transport->ostream, cmdbuf, cancellable, error) == -1) { g_free (cmdbuf); goto lose; } g_free (cmdbuf); /* get the server's response */ respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); } if (respbuf == NULL) goto lose; /* Work around broken SASL implementations. */ if (auth_challenge && strncmp (respbuf, "334", 3) == 0) goto broken_smtp_server; /* If our authentication data was rejected, destroy the * password so that the user gets prompted to try again. */ if (strncmp (respbuf, "535", 3) == 0) { result = CAMEL_AUTHENTICATION_REJECTED; /* Read the continuation, if the server returned it. */ while (respbuf && respbuf[3] == '-') { g_free (respbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); } } else if (strncmp (respbuf, "235", 3) == 0) result = CAMEL_AUTHENTICATION_ACCEPTED; /* Catch any other errors. */ else { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE, _("Bad authentication response from server.")); goto lose; } goto exit; break_and_lose: /* Get the server out of "waiting for continuation data" mode. */ d (fprintf (stderr, "[SMTP] sending: *\n")); camel_stream_write (transport->ostream, "*\r\n", 3, cancellable, NULL); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, NULL); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); lose: result = CAMEL_AUTHENTICATION_ERROR; exit: g_object_unref (sasl); g_free (respbuf); return result; }
gint main (gint argc, gchar **argv) { CamelSession *session; CamelSMimeContext *ctx; GError **error; CamelCipherValidity *valid; CamelStream *stream1, *stream2, *stream3; GPtrArray *recipients; GByteArray *buf; gchar *before, *after; camel_test_init (argc, argv); ex = camel_exception_new (); /* clear out any camel-test data */ system ("/bin/rm -rf /tmp/camel-test"); session = camel_test_session_new ("/tmp/camel-test"); ctx = camel_smime_context_new (session); camel_test_start ("Test of S/MIME PKCS7 functions"); stream1 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test stream.", 25); g_seekable_seek (G_SEEKABLE (stream1), 0, G_SEEK_SET, NULL, NULL); stream2 = camel_stream_mem_new (); camel_test_push ("PKCS7 signing"); camel_smime_sign (ctx, "*****@*****.**", CAMEL_CIPHER_HASH_SHA1, stream1, stream2, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); camel_test_pull (); camel_exception_clear (ex); camel_test_push ("PKCS7 verify"); g_seekable_seek (G_SEEKABLE (stream1), 0, G_SEEK_SET, NULL, NULL); g_seekable_seek (G_SEEKABLE (stream2), 0, G_SEEK_SET, NULL, NULL); valid = camel_smime_verify (ctx, CAMEL_CIPHER_HASH_SHA1, stream1, stream2, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); camel_cipher_validity_free (valid); camel_test_pull (); g_object_unref (stream1); g_object_unref (stream2); stream1 = camel_stream_mem_new (); stream2 = camel_stream_mem_new (); stream3 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44); g_seekable_seek (G_SEEKABLE (stream1), 0, G_SEEK_SET, NULL, NULL); camel_exception_clear (ex); camel_test_push ("PKCS7 encrypt"); recipients = g_ptr_array_new (); g_ptr_array_add (recipients, "*****@*****.**"); camel_smime_encrypt (ctx, FALSE, "*****@*****.**", recipients, stream1, stream2, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); g_ptr_array_free (recipients, TRUE); camel_test_pull (); g_seekable_seek (G_SEEKABLE (stream2), 0, G_SEEK_SET, NULL, NULL); camel_exception_clear (ex); camel_test_push ("PKCS7 decrypt"); camel_smime_decrypt (ctx, stream2, stream3, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); buf = CAMEL_STREAM_MEM (stream1)->buffer; before = g_strndup (buf->data, buf->len); buf = CAMEL_STREAM_MEM (stream3)->buffer; after = g_strndup (buf->data, buf->len); check_msg (string_equal (before, after), "before = '%s', after = '%s'", before, after); g_free (before); g_free (after); camel_test_pull (); g_object_unref (ctx); g_object_unref (session); camel_test_end (); return 0; }
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 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; }
/* used for decode content callback, for streaming decode */ static void sm_write_stream(void *arg, const char *buf, unsigned long len) { camel_stream_write((CamelStream *)arg, buf, len); }
static gboolean connect_to_server (CamelService *service, GCancellable *cancellable, GError **error) { CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); CamelNetworkSettings *network_settings; CamelNetworkSecurityMethod method; CamelSettings *settings; CamelStream *stream; GIOStream *base_stream; GIOStream *tls_stream; gchar *respbuf = NULL; gboolean success = TRUE; gchar *host; if (!CAMEL_SERVICE_CLASS (camel_smtp_transport_parent_class)-> connect_sync (service, cancellable, error)) return FALSE; /* set some smtp transport defaults */ transport->flags = 0; transport->authtypes = NULL; settings = camel_service_ref_settings (service); network_settings = CAMEL_NETWORK_SETTINGS (settings); host = camel_network_settings_dup_host (network_settings); method = camel_network_settings_get_security_method (network_settings); g_object_unref (settings); base_stream = camel_network_service_connect_sync ( CAMEL_NETWORK_SERVICE (service), cancellable, error); if (base_stream != NULL) { /* get the localaddr - needed later by smtp_helo */ transport->local_address = g_socket_connection_get_local_address ( G_SOCKET_CONNECTION (base_stream), NULL); stream = camel_stream_new (base_stream); g_object_unref (base_stream); } else { success = FALSE; goto exit; } transport->connected = TRUE; transport->ostream = stream; transport->istream = camel_stream_buffer_new ( stream, CAMEL_STREAM_BUFFER_READ); /* Read the greeting, note whether the server is ESMTP or not. */ do { /* Check for "220" */ g_free (respbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); if (respbuf == NULL) { g_prefix_error (error, _("Welcome response error: ")); transport->connected = FALSE; success = FALSE; goto exit; } if (strncmp (respbuf, "220", 3)) { smtp_set_error ( transport, respbuf, cancellable, error); g_prefix_error (error, _("Welcome response error: ")); g_free (respbuf); success = FALSE; goto exit; } } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ g_free (respbuf); /* Try sending EHLO */ transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP; if (!smtp_helo (transport, cancellable, error)) { if (!transport->connected) { success = FALSE; goto exit; } /* Fall back to HELO */ g_clear_error (error); transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP; if (!smtp_helo (transport, cancellable, error)) { success = FALSE; goto exit; } } /* Clear any EHLO/HELO exception and assume that * any SMTP errors encountered were non-fatal. */ g_clear_error (error); if (method != CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) goto exit; /* we're done */ if (!(transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to connect to SMTP server %s in secure mode: %s"), host, _("STARTTLS not supported")); success = FALSE; goto exit; } d (fprintf (stderr, "[SMTP] sending: STARTTLS\r\n")); if (camel_stream_write ( stream, "STARTTLS\r\n", 10, cancellable, error) == -1) { g_prefix_error (error, _("STARTTLS command failed: ")); success = FALSE; goto exit; } respbuf = NULL; do { /* Check for "220 Ready for TLS" */ g_free (respbuf); respbuf = camel_stream_buffer_read_line ( CAMEL_STREAM_BUFFER (transport->istream), cancellable, error); d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)")); if (respbuf == NULL) { g_prefix_error (error, _("STARTTLS command failed: ")); transport->connected = FALSE; success = FALSE; goto exit; } if (strncmp (respbuf, "220", 3) != 0) { smtp_set_error ( transport, respbuf, cancellable, error); g_prefix_error (error, _("STARTTLS command failed: ")); g_free (respbuf); success = FALSE; goto exit; } } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ /* Okay, now toggle SSL/TLS mode */ base_stream = camel_stream_ref_base_stream (stream); tls_stream = camel_network_service_starttls ( CAMEL_NETWORK_SERVICE (service), base_stream, error); g_object_unref (base_stream); if (tls_stream != NULL) { camel_stream_set_base_stream (stream, tls_stream); g_object_unref (tls_stream); } else { g_prefix_error ( error, _("Failed to connect to SMTP server %s in secure mode: "), host); success = FALSE; goto exit; } /* We are supposed to re-EHLO after a successful STARTTLS to * re-fetch any supported extensions. */ if (!smtp_helo (transport, cancellable, error)) { success = FALSE; } exit: g_free (host); if (!success) { transport->connected = FALSE; g_clear_object (&transport->istream); g_clear_object (&transport->ostream); } return success; }