static gint do_perf (gint argc, gchar **argv) { CamelIndex *idx; DIR *dir; const gchar *path = "/home/notzed/evolution/local/Inbox/mbox/cur"; struct dirent *d; CamelStream *null, *filter, *stream; CamelMimeFilter *filter_index; gchar *name; CamelIndexName *idn; dir = opendir (path); if (dir == NULL) { perror("open dir"); return 1; } idx = (CamelIndex *) camel_text_index_new ( "/tmp/index", O_TRUNC|O_CREAT|O_RDWR); if (idx == NULL) { perror("open index"); closedir (dir); return 1; } null = camel_stream_null_new (); filter = camel_stream_filter_new (null); g_object_unref (null); filter_index = camel_mime_filter_index_new (idx); camel_stream_filter_add ((CamelStreamFilter *)filter, filter_index); while ((d = readdir (dir))) { printf("indexing '%s'\n", d->d_name); idn = camel_index_add_name (idx, d->d_name); camel_mime_filter_index_set_name ( CAMEL_MIME_FILTER_INDEX (filter_index), idn); name = g_strdup_printf("%s/%s", path, d->d_name); stream = camel_stream_fs_new_with_name (name, O_RDONLY, 0, NULL); camel_stream_write_to_stream (stream, filter, NULL, NULL); g_object_unref (stream); g_free (name); camel_index_write_name (idx, idn); g_object_unref (idn); camel_mime_filter_index_set_name ( CAMEL_MIME_FILTER_INDEX (filter_index), NULL); } closedir (dir); camel_index_sync (idx); g_object_unref (idx); g_object_unref (filter); g_object_unref (filter_index); return 0; }
static gssize data_wrapper_decode_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { CamelMimeFilter *filter; CamelStream *fstream; gssize ret; fstream = camel_stream_filter_new (stream); switch (data_wrapper->encoding) { case CAMEL_TRANSFER_ENCODING_BASE64: filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_BASE64_DEC); camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter); g_object_unref (filter); break; case CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE: filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_QP_DEC); camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter); g_object_unref (filter); break; case CAMEL_TRANSFER_ENCODING_UUENCODE: filter = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC); camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter); g_object_unref (filter); break; default: break; } if (!(camel_content_type_is (data_wrapper->mime_type, "text", "pdf")) && camel_content_type_is (data_wrapper->mime_type, "text", "*")) { filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add (CAMEL_STREAM_FILTER (fstream), filter); g_object_unref (filter); } ret = camel_data_wrapper_write_to_stream_sync ( data_wrapper, fstream, cancellable, error); camel_stream_flush (fstream, NULL, NULL); g_object_unref (fstream); return ret; }
gint main (gint argc, gchar **argv) { CamelStream *source; CamelStream *correct; CamelStream *stream; CamelMimeFilter *sh; gchar *work; gint i; gssize comp_progress, comp_correct_chunk, comp_filter_chunk; gint comp_i; gchar comp_correct[CHUNK_SIZE], comp_filter[CHUNK_SIZE]; camel_test_init (argc, argv); for (i = 0; i < NUM_CASES; i++) { gint j; work = g_strdup_printf ("CRLF/DOT filter, test case %d", i); camel_test_start (work); g_free (work); for (j = CRLF_ENCODE; j < CRLF_DONE; j++) { CamelMimeFilterCRLFDirection direction; gchar *infile = NULL, *outfile = NULL; switch (j) { case CRLF_ENCODE: camel_test_push ("Test of the encoder"); direction = CAMEL_MIME_FILTER_CRLF_ENCODE; infile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1); outfile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1); break; case CRLF_DECODE: camel_test_push ("Test of the decoder"); direction = CAMEL_MIME_FILTER_CRLF_DECODE; infile = g_strdup_printf ("%s/crlf-%d.out", SOURCEDIR, i + 1); outfile = g_strdup_printf ("%s/crlf-%d.in", SOURCEDIR, i + 1); break; default: break; } camel_test_push ("Initializing objects"); source = camel_stream_fs_new_with_name (infile, 0, O_RDONLY, NULL); if (!source) { camel_test_fail ("Failed to open input case in \"%s\"", infile); g_free (infile); continue; } g_free (infile); correct = camel_stream_fs_new_with_name (outfile, 0, O_RDONLY, NULL); if (!correct) { camel_test_fail ("Failed to open correct output in \"%s\"", outfile); g_free (outfile); continue; } g_free (outfile); stream = camel_stream_filter_new (source); if (!stream) { camel_test_fail ("Couldn't create CamelStreamFilter??"); continue; } sh = camel_mime_filter_crlf_new (direction, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); if (!sh) { camel_test_fail ("Couldn't create CamelMimeFilterCrlf??"); continue; } camel_stream_filter_add ( CAMEL_STREAM_FILTER (stream), sh); camel_test_pull (); camel_test_push ("Running filter and comparing to correct result"); comp_progress = 0; while (1) { comp_correct_chunk = camel_stream_read ( correct, comp_correct, CHUNK_SIZE, NULL, NULL); comp_filter_chunk = 0; if (comp_correct_chunk == 0) break; while (comp_filter_chunk < comp_correct_chunk) { gssize delta; delta = camel_stream_read ( stream, comp_filter + comp_filter_chunk, CHUNK_SIZE - comp_filter_chunk, NULL, NULL); if (delta == 0) { camel_test_fail ("Chunks are different sizes: correct is %d, " "filter is %d, %d bytes into stream", comp_correct_chunk, comp_filter_chunk, comp_progress); } comp_filter_chunk += delta; } for (comp_i = 0; comp_i < comp_filter_chunk; comp_i++) { if (comp_correct[comp_i] != comp_filter[comp_i]) { camel_test_fail ("Difference: correct is %c, filter is %c, " "%d bytes into stream", comp_correct[comp_i], comp_filter[comp_i], comp_progress + comp_i); } } comp_progress += comp_filter_chunk; } camel_test_pull (); /* inefficient */ camel_test_push ("Cleaning up"); g_object_unref (stream); g_object_unref (correct); g_object_unref (source); g_object_unref (sh); camel_test_pull (); camel_test_pull (); } camel_test_end (); } return 0; }
static void create_mime_message_cb (ESoapMessage *msg, gpointer user_data) { struct _create_mime_msg_data *create_data = user_data; CamelStream *mem, *filtered; CamelMimeFilter *filter; CamelContentType *content_type; GByteArray *bytes; gchar *base64; gint msgflag; guint32 message_camel_flags = 0; if (create_data->info) message_camel_flags = camel_message_info_flags (create_data->info); e_soap_message_start_element (msg, "Message", NULL, NULL); e_soap_message_start_element (msg, "MimeContent", NULL, NULL); /* This is horrid. We really need to extend ESoapMessage to allow us * to stream this directly rather than storing it in RAM. Which right * now we are doing about four times: the GByteArray in the mem stream, * then the base64 version, then the xmlDoc, then the soup request. */ camel_mime_message_set_best_encoding ( create_data->message, CAMEL_BESTENC_GET_ENCODING, CAMEL_BESTENC_8BIT); mem = camel_stream_mem_new (); filtered = camel_stream_filter_new (mem); filter = camel_mime_filter_crlf_new ( CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered), filter); g_object_unref (filter); camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (create_data->message), filtered, NULL, NULL); camel_stream_flush (filtered, NULL, NULL); camel_stream_flush (mem, NULL, NULL); bytes = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem)); base64 = g_base64_encode (bytes->data, bytes->len); g_object_unref (mem); g_object_unref (filtered); e_soap_message_write_string (msg, base64); g_free (base64); e_soap_message_end_element (msg); /* MimeContent */ content_type = camel_mime_part_get_content_type (CAMEL_MIME_PART (create_data->message)); if (content_type && camel_content_type_is (content_type, "multipart", "report") && camel_content_type_param (content_type, "report-type") && g_ascii_strcasecmp (camel_content_type_param (content_type, "report-type"), "disposition-notification") == 0) { /* it's a disposition notification reply, set ItemClass too */ e_soap_message_start_element (msg, "ItemClass", NULL, NULL); e_soap_message_write_string (msg, "REPORT.IPM.NOTE.IPNRN"); e_soap_message_end_element (msg); /* ItemClass */ } e_ews_message_write_string_parameter_with_attribute ( msg, "Importance", NULL, (message_camel_flags & CAMEL_MESSAGE_FLAGGED) != 0 ? "High" : "Normal", NULL, NULL); /* more MAPI crap. You can't just set the IsDraft property * here you have to use the MAPI MSGFLAG_UNSENT extended * property Further crap is that Exchange 2007 assumes when it * sees this property that you're setting the value to 0 * ... it never checks */ msgflag = MAPI_MSGFLAG_READ; /* draft or sent is always read */ if ((message_camel_flags & CAMEL_MESSAGE_DRAFT) != 0) msgflag |= MAPI_MSGFLAG_UNSENT; e_ews_message_add_extended_property_tag_int (msg, 0x0e07, msgflag); if ((message_camel_flags & (CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_ANSWERED)) != 0) { gint icon; icon = (message_camel_flags & CAMEL_MESSAGE_ANSWERED) != 0 ? 0x105 : 0x106; e_ews_message_add_extended_property_tag_int (msg, 0x1080, icon); } if (create_data->info) { const gchar *followup, *completed, *dueby; time_t completed_tt = (time_t) 0 , dueby_tt = (time_t) 0; /* follow-up flags */ followup = camel_message_info_user_tag (create_data->info, "follow-up"); completed = camel_message_info_user_tag (create_data->info, "completed-on"); dueby = camel_message_info_user_tag (create_data->info, "due-by"); if (followup && !*followup) followup = NULL; if (completed && *completed) completed_tt = camel_header_decode_date (completed, NULL); if (dueby && *dueby) dueby_tt = camel_header_decode_date (dueby, NULL); /* PidTagFlagStatus */ e_ews_message_add_extended_property_tag_int (msg, 0x1090, followup ? (completed_tt != (time_t) 0 ? 0x01 /* followupComplete */: 0x02 /* followupFlagged */) : 0x0); if (followup) { /* PidLidFlagRequest */ e_ews_message_add_extended_property_distinguished_tag_string (msg, "Common", 0x8530, followup); /* PidTagToDoItemFlags */ e_ews_message_add_extended_property_tag_int (msg, 0x0e2b, 1); } if (followup && completed_tt != (time_t) 0) { /* minute precision */ completed_tt = completed_tt - (completed_tt % 60); /* PidTagFlagCompleteTime */ e_ews_message_add_extended_property_tag_time (msg, 0x1091, completed_tt); /* PidLidTaskDateCompleted */ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x810f, completed_tt); /* PidLidTaskStatus */ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 2); /* PidLidPercentComplete */ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 1.0); /* PidLidTaskComplete */ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, TRUE); } if (followup && dueby_tt != (time_t) 0 && completed_tt == (time_t) 0) { /* PidLidTaskStatus */ e_ews_message_add_extended_property_distinguished_tag_int (msg, "Task", 0x8101, 0); /* PidLidPercentComplete */ e_ews_message_add_extended_property_distinguished_tag_double (msg, "Task", 0x8102, 0.0); /* PidLidTaskDueDate */ e_ews_message_add_extended_property_distinguished_tag_time (msg, "Task", 0x8105, dueby_tt); /* PidLidTaskComplete */ e_ews_message_add_extended_property_distinguished_tag_boolean (msg, "Task", 0x811c, FALSE); } } if (create_data->recipients) { GHashTable *recip_to, *recip_cc, *recip_bcc; recip_to = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); recip_cc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); recip_bcc = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); filter_recipients (create_data->message, create_data->recipients, recip_to, recip_cc, recip_bcc); write_recipients (msg, "ToRecipients", recip_to); write_recipients (msg, "CcRecipients", recip_cc); write_recipients (msg, "BccRecipients", recip_bcc); g_hash_table_destroy (recip_to); g_hash_table_destroy (recip_cc); g_hash_table_destroy (recip_bcc); } e_ews_message_write_string_parameter_with_attribute ( msg, "IsRead", NULL, (message_camel_flags & CAMEL_MESSAGE_SEEN) != 0 ? "true" : "false", NULL, NULL); e_soap_message_end_element (msg); /* Message */ g_free (create_data); }
static gboolean sendmail_send_to_sync (CamelTransport *transport, CamelMimeMessage *message, CamelAddress *from, CamelAddress *recipients, gboolean *out_sent_message_saved, GCancellable *cancellable, GError **error) { CamelHeaderRaw *header, *savedbcc, *n, *tail; const gchar *from_addr, *addr; GPtrArray *argv_arr; gint i, len, fd[2], nullfd, wstat; CamelStream *filter; CamelMimeFilter *crlf; sigset_t mask, omask; CamelStream *out; CamelSendmailSettings *settings; const gchar *binary = SENDMAIL_PATH; gchar *custom_binary = NULL, *custom_args = NULL; gboolean success; pid_t pid; success = camel_internet_address_get ( CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr); if (!success) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to read From address")); return FALSE; } settings = CAMEL_SENDMAIL_SETTINGS (camel_service_ref_settings (CAMEL_SERVICE (transport))); if (!camel_sendmail_settings_get_send_in_offline (settings)) { CamelSession *session; gboolean is_online; session = camel_service_ref_session (CAMEL_SERVICE (transport)); is_online = session && camel_session_get_online (session); g_clear_object (&session); if (!is_online) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE, _("Message send in offline mode is disabled")); return FALSE; } } if (camel_sendmail_settings_get_use_custom_binary (settings)) { custom_binary = camel_sendmail_settings_dup_custom_binary (settings); if (custom_binary && *custom_binary) binary = custom_binary; } if (camel_sendmail_settings_get_use_custom_args (settings)) { custom_args = camel_sendmail_settings_dup_custom_args (settings); /* means no arguments used */ if (!custom_args) custom_args = g_strdup (""); } g_object_unref (settings); len = camel_address_length (recipients); for (i = 0; i < len; i++) { success = camel_internet_address_get ( CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr); if (!success) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not parse recipient list")); g_free (custom_binary); g_free (custom_args); return FALSE; } } argv_arr = parse_sendmail_args ( binary, custom_args ? custom_args : "-i -f %F -- %R", from_addr, recipients); if (!argv_arr) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not parse arguments")); g_free (custom_binary); g_free (custom_args); return FALSE; } /* unlink the bcc headers */ savedbcc = NULL; tail = (CamelHeaderRaw *) &savedbcc; header = (CamelHeaderRaw *) &CAMEL_MIME_PART (message)->headers; n = header->next; while (n != NULL) { if (!g_ascii_strcasecmp (n->name, "Bcc")) { header->next = n->next; tail->next = n; n->next = NULL; tail = n; } else { header = n; } n = header->next; } if (pipe (fd) == -1) { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Could not create pipe to '%s': %s: " "mail not sent"), binary, g_strerror (errno)); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); g_ptr_array_free (argv_arr, TRUE); return FALSE; } /* Block SIGCHLD so the calling application doesn't notice * sendmail exiting before we do. */ sigemptyset (&mask); sigaddset (&mask, SIGCHLD); sigprocmask (SIG_BLOCK, &mask, &omask); pid = fork (); switch (pid) { case -1: g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Could not fork '%s': %s: " "mail not sent"), binary, g_strerror (errno)); close (fd[0]); close (fd[1]); sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); g_ptr_array_free (argv_arr, TRUE); return FALSE; case 0: /* Child process */ nullfd = open ("/dev/null", O_RDWR); dup2 (fd[0], STDIN_FILENO); if (nullfd != -1) { /*dup2 (nullfd, STDOUT_FILENO); dup2 (nullfd, STDERR_FILENO);*/ close (nullfd); } close (fd[1]); execv (binary, (gchar **) argv_arr->pdata); _exit (255); } g_ptr_array_free (argv_arr, TRUE); /* Parent process. Write the message out. */ close (fd[0]); out = camel_stream_fs_new_with_fd (fd[1]); /* XXX Workaround for lame sendmail implementations * that can't handle CRLF eoln sequences. */ filter = camel_stream_filter_new (out); crlf = camel_mime_filter_crlf_new ( CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), crlf); g_object_unref (crlf); g_object_unref (out); out = (CamelStream *) filter; if (camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), out, cancellable, error) == -1 || camel_stream_close (out, cancellable, error) == -1) { g_object_unref (out); g_prefix_error (error, _("Could not send message: ")); /* Wait for sendmail to exit. */ while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) ; sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; g_free (custom_binary); g_free (custom_args); return FALSE; } g_object_unref (out); /* Wait for sendmail to exit. */ while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) ; sigprocmask (SIG_SETMASK, &omask, NULL); /* restore the bcc headers */ header->next = savedbcc; if (!WIFEXITED (wstat)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("'%s' exited with signal %s: mail not sent."), binary, g_strsignal (WTERMSIG (wstat))); g_free (custom_binary); g_free (custom_args); return FALSE; } else if (WEXITSTATUS (wstat) != 0) { if (WEXITSTATUS (wstat) == 255) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Could not execute '%s': mail not sent."), binary); } else { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("'%s' exited with status %d: " "mail not sent."), binary, WEXITSTATUS (wstat)); } g_free (custom_binary); g_free (custom_args); return FALSE; } g_free (custom_binary); g_free (custom_args); return TRUE; }
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 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 gboolean empe_inlinepgp_signed_parse (EMailParserExtension *extension, EMailParser *parser, CamelMimePart *part, GString *part_id, GCancellable *cancellable, GQueue *out_mail_parts) { CamelStream *filtered_stream; CamelMimeFilterPgp *pgp_filter; CamelContentType *content_type; CamelCipherContext *cipher; CamelCipherValidity *valid; CamelDataWrapper *dw; CamelMimePart *opart; CamelStream *ostream; GQueue work_queue = G_QUEUE_INIT; GList *head, *link; gchar *type; gint len; GError *local_error = NULL; GByteArray *ba; if (g_cancellable_is_cancelled (cancellable) || /* avoid recursion */ (part_id->str && part_id->len > 17 && g_str_has_suffix (part_id->str, ".inlinepgp_signed"))) return FALSE; cipher = camel_gpg_context_new (e_mail_parser_get_session (parser)); /* Verify the signature of the message */ valid = camel_cipher_context_verify_sync ( cipher, part, cancellable, &local_error); if (local_error != NULL) { e_mail_parser_error ( parser, out_mail_parts, _("Error verifying signature: %s"), local_error->message); g_error_free (local_error); e_mail_parser_parse_part_as ( parser, part, part_id, "application/vnd.evolution.source", cancellable, out_mail_parts); g_object_unref (cipher); return TRUE; } /* Setup output stream */ ostream = camel_stream_mem_new (); filtered_stream = camel_stream_filter_new (ostream); /* Add PGP header / footer filter */ pgp_filter = (CamelMimeFilterPgp *) camel_mime_filter_pgp_new (); camel_stream_filter_add ( CAMEL_STREAM_FILTER (filtered_stream), CAMEL_MIME_FILTER (pgp_filter)); g_object_unref (pgp_filter); /* Pass through the filters that have been setup */ dw = camel_medium_get_content ((CamelMedium *) part); camel_data_wrapper_decode_to_stream_sync ( dw, (CamelStream *) filtered_stream, cancellable, NULL); camel_stream_flush ((CamelStream *) filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); /* Create a new text/plain MIME part containing the signed * content preserving the original part's Content-Type params. */ content_type = camel_mime_part_get_content_type (part); type = camel_content_type_format (content_type); content_type = camel_content_type_decode (type); g_free (type); g_free (content_type->type); content_type->type = g_strdup ("text"); g_free (content_type->subtype); content_type->subtype = g_strdup ("plain"); type = camel_content_type_format (content_type); camel_content_type_unref (content_type); ba = camel_stream_mem_get_byte_array ((CamelStreamMem *) ostream); opart = camel_mime_part_new (); camel_mime_part_set_content (opart, (gchar *) ba->data, ba->len, type); g_free (type); len = part_id->len; g_string_append (part_id, ".inlinepgp_signed"); e_mail_parser_parse_part ( parser, opart, part_id, cancellable, &work_queue); head = g_queue_peek_head_link (&work_queue); for (link = head; link != NULL; link = g_list_next (link)) { EMailPart *mail_part = link->data; e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_SIGNED | E_MAIL_PART_VALIDITY_PGP); } e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); /* Add a widget with details about the encryption, but only when * the encrypted isn't itself secured, in that case it has created * the button itself */ if (!e_mail_part_is_secured (opart)) { EMailPart *mail_part; g_string_append (part_id, ".inlinepgp_signed.button"); e_mail_parser_parse_part_as ( parser, part, part_id, "application/vnd.evolution.widget.secure-button", cancellable, &work_queue); mail_part = g_queue_peek_head (&work_queue); if (mail_part != NULL) e_mail_part_update_validity ( mail_part, valid, E_MAIL_PART_VALIDITY_SIGNED | E_MAIL_PART_VALIDITY_PGP); e_queue_transfer (&work_queue, out_mail_parts); g_string_truncate (part_id, len); } /* Clean Up */ camel_cipher_validity_free (valid); g_object_unref (opart); g_object_unref (ostream); g_object_unref (cipher); return TRUE; }