static MimeInfo *tnef_dump_file(const gchar *filename, char *data, size_t size) { MimeInfo *sub_info = NULL; gchar *tmpfilename = NULL; FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename); GStatBuf statbuf; gchar *content_type = NULL; if (!fp) { g_free(tmpfilename); return NULL; } sub_info = procmime_mimeinfo_new(); sub_info->content = MIMECONTENT_FILE; sub_info->data.filename = tmpfilename; sub_info->type = MIMETYPE_APPLICATION; sub_info->subtype = g_strdup("octet-stream"); if (filename) { g_hash_table_insert(sub_info->typeparameters, g_strdup("filename"), g_strdup(filename)); content_type = procmime_get_mime_type(filename); if (content_type && strchr(content_type, '/')) { g_free(sub_info->subtype); sub_info->subtype = g_strdup(strchr(content_type, '/')+1); *(strchr(content_type, '/')) = '\0'; sub_info->type = procmime_get_media_type(content_type); g_free(content_type); } } if (claws_fwrite(data, 1, size, fp) < size) { FILE_OP_ERROR(tmpfilename, "claws_fwrite"); claws_fclose(fp); claws_unlink(tmpfilename); procmime_mimeinfo_free_all(&sub_info); return tnef_broken_mimeinfo(_("Failed to write the part data.")); } claws_fclose(fp); if (g_stat(tmpfilename, &statbuf) < 0) { claws_unlink(tmpfilename); procmime_mimeinfo_free_all(&sub_info); return tnef_broken_mimeinfo(_("Failed to write the part data.")); } else { sub_info->tmp = TRUE; sub_info->length = statbuf.st_size; sub_info->encoding_type = ENC_BINARY; } return sub_info; }
MimeInfo *tnef_parse_vcard(TNEFStruct tnef) { MimeInfo *sub_info = NULL; gchar *tmpfilename = NULL; FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename); struct stat statbuf; gboolean result = FALSE; if (!fp) { g_free(tmpfilename); return NULL; } sub_info = procmime_mimeinfo_new(); sub_info->content = MIMECONTENT_FILE; sub_info->data.filename = tmpfilename; sub_info->type = MIMETYPE_TEXT; sub_info->subtype = g_strdup("x-vcard"); g_hash_table_insert(sub_info->typeparameters, g_strdup("filename"), g_strdup("contact.vcf")); result = SaveVCard(fp, tnef); fclose(fp); g_stat(tmpfilename, &statbuf); sub_info->tmp = TRUE; sub_info->length = statbuf.st_size; sub_info->encoding_type = ENC_BINARY; if (!result) { claws_unlink(tmpfilename); procmime_mimeinfo_free_all(sub_info); return tnef_broken_mimeinfo(_("Failed to parse VCard data.")); } return sub_info; }
static gboolean mail_filtering_hook(gpointer source, gpointer data) { MailFilteringData *mail_filtering_data = (MailFilteringData *) source; MsgInfo *msginfo = mail_filtering_data->msginfo; MimeInfo *mimeinfo; struct clamd_result result; if (!config.clamav_enable) return FALSE; mimeinfo = procmime_scan_message(msginfo); if (!mimeinfo) return FALSE; debug_print("Scanning message %d for viruses\n", msginfo->msgnum); if (message_callback != NULL) message_callback(_("ClamAV: scanning message...")); g_node_traverse(mimeinfo->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, scan_func, &result); debug_print("status: %d\n", result.status); if (result.status == VIRUS) { if (config.clamav_recv_infected) { FolderItem *clamav_save_folder; if ((!config.clamav_save_folder) || (config.clamav_save_folder[0] == '\0') || ((clamav_save_folder = folder_find_item_from_identifier(config.clamav_save_folder)) == NULL)) clamav_save_folder = folder_get_default_trash(); procmsg_msginfo_unset_flags(msginfo, ~0, 0); msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = clamav_save_folder; } else { folder_item_remove_msg(msginfo->folder, msginfo->msgnum); } } procmime_mimeinfo_free_all(mimeinfo); return (result.status == OK) ? FALSE : TRUE; }
void mimeview_destroy(MimeView *mimeview) { GSList *cur; for (cur = mimeview->viewers; cur != NULL; cur = g_slist_next(cur)) { MimeViewer *viewer = (MimeViewer *) cur->data; gtk_container_remove(GTK_CONTAINER(mimeview->mime_notebook), GTK_WIDGET(viewer->get_widget(viewer))); viewer->destroy_viewer(viewer); } g_slist_free(mimeview->viewers); gtk_target_list_unref(mimeview->target_list); procmime_mimeinfo_free_all(mimeview->mimeinfo); g_free(mimeview->file); g_free(mimeview); mimeviews = g_slist_remove(mimeviews, mimeview); }
static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system) { MimeInfo *decryptedinfo, *parentinfo; gint childnumber; cm_return_val_if_fail(system->decrypt != NULL, -1); decryptedinfo = system->decrypt(mimeinfo); if (decryptedinfo == NULL) return -1; parentinfo = procmime_mimeinfo_parent(mimeinfo); childnumber = g_node_child_index(parentinfo->node, mimeinfo); procmime_mimeinfo_free_all(&mimeinfo); g_node_insert(parentinfo->node, childnumber, decryptedinfo->node); return 0; }
void mimeview_clear(MimeView *mimeview) { GtkCList *clist = GTK_CLIST(mimeview->ctree); noticeview_hide(mimeview->siginfoview); gtk_clist_clear(clist); textview_clear(mimeview->textview); if (mimeview->mimeviewer != NULL) mimeview->mimeviewer->clear_viewer(mimeview->mimeviewer); if (mimeview->mimeinfo != NULL) procmime_mimeinfo_free_all(mimeview->mimeinfo); mimeview->mimeinfo = NULL; mimeview->opened = NULL; g_free(mimeview->file); mimeview->file = NULL; icon_list_clear(mimeview); }
MimeInfo *tnef_parse_vtask(TNEFStruct *tnef) { MimeInfo *sub_info = NULL; gchar *tmpfilename = NULL; FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename); GStatBuf statbuf; gboolean result = FALSE; if (!fp) { g_free(tmpfilename); return NULL; } sub_info = procmime_mimeinfo_new(); sub_info->content = MIMECONTENT_FILE; sub_info->data.filename = tmpfilename; sub_info->type = MIMETYPE_TEXT; sub_info->subtype = g_strdup("calendar"); g_hash_table_insert(sub_info->typeparameters, g_strdup("filename"), g_strdup("task.ics")); result = SaveVTask(fp, tnef); claws_fclose(fp); if (g_stat(tmpfilename, &statbuf) < 0) { result = FALSE; } else { sub_info->tmp = TRUE; sub_info->length = statbuf.st_size; sub_info->encoding_type = ENC_BINARY; } if (!result) { claws_unlink(tmpfilename); procmime_mimeinfo_free_all(&sub_info); return tnef_broken_mimeinfo(_("Failed to parse VTask data.")); } return sub_info; }
static MimeInfo *tnef_broken_mimeinfo(const gchar *reason) { MimeInfo *sub_info = NULL; gchar *tmpfilename = NULL; FILE *fp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmpfilename); GStatBuf statbuf; if (!fp) { g_free(tmpfilename); return NULL; } sub_info = procmime_mimeinfo_new(); sub_info->content = MIMECONTENT_FILE; sub_info->data.filename = tmpfilename; sub_info->type = MIMETYPE_TEXT; sub_info->subtype = g_strdup("plain"); fprintf(fp, _("\n" "Claws Mail TNEF parser:\n\n" "%s\n"), reason?reason:_("Unknown error")); claws_fclose(fp); if (g_stat(tmpfilename, &statbuf) < 0) { claws_unlink(tmpfilename); procmime_mimeinfo_free_all(&sub_info); return NULL; } sub_info->tmp = TRUE; sub_info->length = statbuf.st_size; sub_info->encoding_type = ENC_BINARY; return sub_info; }
gint messageview_show(MessageView *messageview, MsgInfo *msginfo, gboolean all_headers) { gchar *file; MimeInfo *mimeinfo; g_return_val_if_fail(msginfo != NULL, -1); mimeinfo = procmime_scan_message(msginfo); if (!mimeinfo) { messageview_change_view_type(messageview, MVIEW_TEXT); textview_show_error(messageview->textview); return -1; } file = procmsg_get_message_file_path(msginfo); if (!file) { g_warning("can't get message file path.\n"); procmime_mimeinfo_free_all(mimeinfo); messageview_change_view_type(messageview, MVIEW_TEXT); textview_show_error(messageview->textview); return -1; } if (messageview->msginfo != msginfo) { procmsg_msginfo_free(messageview->msginfo); messageview->msginfo = procmsg_msginfo_get_full_info(msginfo); if (!messageview->msginfo) messageview->msginfo = procmsg_msginfo_copy(msginfo); } if (messageview->window && msginfo->subject) { gchar *title; title = g_strconcat(msginfo->subject, " - Sylpheed", NULL); gtk_window_set_title(GTK_WINDOW(messageview->window), title); g_free(title); } headerview_show(messageview->headerview, messageview->msginfo); textview_set_all_headers(messageview->textview, all_headers); textview_set_all_headers(messageview->mimeview->textview, all_headers); if (mimeinfo->mime_type != MIME_TEXT && (prefs_common.html_only_as_attach || mimeinfo->mime_type != MIME_TEXT_HTML)) { messageview_change_view_type(messageview, MVIEW_MIME); mimeview_show_message(messageview->mimeview, mimeinfo, file); } else { messageview_change_view_type(messageview, MVIEW_TEXT); textview_show_message(messageview->textview, mimeinfo, file); procmime_mimeinfo_free_all(mimeinfo); } if (messageview->new_window) messageview_set_menu_state(messageview); g_free(file); return 0; }
static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo) { MimeInfo *decinfo, *parseinfo; gpgme_data_t cipher, plain; FILE *dstfp; gchar *fname; gchar *textdata = NULL; static gint id = 0; const gchar *src_codeset = NULL; gpgme_verify_result_t sigstat = 0; PrivacyDataPGP *data = NULL; gpgme_ctx_t ctx; gchar *chars; size_t len; const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----"; const gchar *end_indicator = "-----END PGP MESSAGE-----"; gchar *pos; if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR) return NULL; gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); cm_return_val_if_fail(mimeinfo != NULL, NULL); cm_return_val_if_fail(pgpinline_is_encrypted(mimeinfo), NULL); if (procmime_mimeinfo_parent(mimeinfo) == NULL || mimeinfo->type != MIMETYPE_TEXT) { gpgme_release(ctx); privacy_set_error(_("Couldn't parse mime part.")); return NULL; } textdata = get_part_as_string(mimeinfo); if (!textdata) { gpgme_release(ctx); privacy_set_error(_("Couldn't get text data.")); return NULL; } debug_print("decrypting '%s'\n", textdata); gpgme_data_new_from_mem(&cipher, textdata, (size_t)strlen(textdata), 1); plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx); if (sigstat && !sigstat->signatures) sigstat = NULL; gpgme_data_release(cipher); if (plain == NULL) { gpgme_release(ctx); return NULL; } fname = g_strdup_printf("%s%cplaintext.%08x", get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); if ((dstfp = g_fopen(fname, "wb")) == NULL) { FILE_OP_ERROR(fname, "fopen"); privacy_set_error(_("Couldn't open decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; } src_codeset = procmime_mimeinfo_get_parameter(mimeinfo, "charset"); if (src_codeset == NULL) src_codeset = CS_ISO_8859_1; if (fprintf(dstfp, "MIME-Version: 1.0\r\n" "Content-Type: text/plain; charset=%s\r\n" "Content-Transfer-Encoding: 8bit\r\n" "\r\n", src_codeset) < 0) { FILE_OP_ERROR(fname, "fprintf"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } /* Store any part before encrypted text */ pos = pgp_locate_armor_header(textdata, begin_indicator); if (pos != NULL && (pos - textdata) > 0) { if (fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } if (fwrite(_("\n--- Start of PGP/Inline encrypted data ---\n"), 1, strlen(_("\n--- Start of PGP/Inline encrypted data ---\n")), dstfp) < strlen(_("\n--- Start of PGP/Inline encrypted data ---\n"))) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } chars = sgpgme_data_release_and_get_mem(plain, &len); if (len > 0) { if (fwrite(chars, 1, len, dstfp) < len) { FILE_OP_ERROR(fname, "fwrite"); g_free(chars); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } g_free(chars); /* Store any part after encrypted text */ if (fwrite(_("--- End of PGP/Inline encrypted data ---\n"), 1, strlen(_("--- End of PGP/Inline encrypted data ---\n")), dstfp) < strlen(_("--- End of PGP/Inline encrypted data ---\n"))) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } if (pos != NULL) { pos = pgp_locate_armor_header(pos, end_indicator); if (pos != NULL && *pos != '\0') { pos += strlen(end_indicator); if (fwrite(pos, 1, strlen(pos), dstfp) < strlen(pos)) { FILE_OP_ERROR(fname, "fwrite"); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); goto FILE_ERROR; } } } if (fclose(dstfp) == EOF) { FILE_OP_ERROR(fname, "fclose"); privacy_set_error(_("Couldn't close decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; } parseinfo = procmime_scan_file(fname); g_free(fname); if (parseinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't scan decrypted file.")); return NULL; } decinfo = g_node_first_child(parseinfo->node) != NULL ? g_node_first_child(parseinfo->node)->data : NULL; if (decinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't scan decrypted file parts.")); return NULL; } g_node_unlink(decinfo->node); procmime_mimeinfo_free_all(parseinfo); decinfo->tmp = TRUE; if (sigstat != GPGME_SIG_STAT_NONE) { if (decinfo->privacy != NULL) { data = (PrivacyDataPGP *) decinfo->privacy; } else { data = pgpinline_new_privacydata(); decinfo->privacy = (PrivacyData *) data; } if (data != NULL) { data->done_sigtest = TRUE; data->is_signed = TRUE; data->sigstatus = sigstat; if (data->ctx) gpgme_release(data->ctx); data->ctx = ctx; } } else gpgme_release(ctx); return decinfo; FILE_ERROR: fclose(dstfp); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); return NULL; }
gint procmsg_send_message_queue(const gchar *file) { static HeaderEntry qentry[] = {{"S:", NULL, FALSE}, {"SSV:", NULL, FALSE}, {"R:", NULL, FALSE}, {"NG:", NULL, FALSE}, {"MAID:", NULL, FALSE}, {"NAID:", NULL, FALSE}, {"SCF:", NULL, FALSE}, {"RMID:", NULL, FALSE}, {"FMID:", NULL, FALSE}, {"X-Sylpheed-Privacy-System:", NULL, FALSE}, {"X-Sylpheed-Encrypt:", NULL, FALSE}, {"X-Sylpheed-Encrypt-Data:", NULL, FALSE}, {NULL, NULL, FALSE}}; FILE *fp; gint filepos; gint mailval = 0, newsval = 0; gchar *from = NULL; gchar *smtpserver = NULL; GSList *to_list = NULL; GSList *newsgroup_list = NULL; gchar *savecopyfolder = NULL; gchar *replymessageid = NULL; gchar *fwdmessageid = NULL; gchar *privacy_system = NULL; gboolean encrypt = FALSE; gchar *encrypt_data = NULL; gchar buf[BUFFSIZE]; gint hnum; PrefsAccount *mailac = NULL, *newsac = NULL; gboolean save_clear_text = TRUE; gchar *tmp_enc_file = NULL; int local = 0; g_return_val_if_fail(file != NULL, -1); if ((fp = fopen(file, "rb")) == NULL) { FILE_OP_ERROR(file, "fopen"); return -1; } while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry)) != -1) { gchar *p = buf + strlen(qentry[hnum].name); switch (hnum) { case Q_SENDER: if (from == NULL) from = g_strdup(p); break; case Q_SMTPSERVER: if (smtpserver == NULL) smtpserver = g_strdup(p); break; case Q_RECIPIENTS: to_list = address_list_append(to_list, p); break; case Q_NEWSGROUPS: newsgroup_list = newsgroup_list_append(newsgroup_list, p); break; case Q_MAIL_ACCOUNT_ID: mailac = account_find_from_id(atoi(p)); break; case Q_NEWS_ACCOUNT_ID: newsac = account_find_from_id(atoi(p)); break; case Q_SAVE_COPY_FOLDER: if (savecopyfolder == NULL) savecopyfolder = g_strdup(p); break; case Q_REPLY_MESSAGE_ID: if (replymessageid == NULL) replymessageid = g_strdup(p); break; case Q_FWD_MESSAGE_ID: if (fwdmessageid == NULL) fwdmessageid = g_strdup(p); break; case Q_PRIVACY_SYSTEM: if (privacy_system == NULL) privacy_system = g_strdup(p); break; case Q_ENCRYPT: if (p[0] == '1') encrypt = TRUE; break; case Q_ENCRYPT_DATA: if (encrypt_data == NULL) encrypt_data = g_strdup(p); break; } } filepos = ftell(fp); if (encrypt) { MimeInfo *mimeinfo; save_clear_text = (mailac != NULL && mailac->save_encrypted_as_clear_text); fclose(fp); fp = NULL; mimeinfo = procmime_scan_queue_file(file); if (!privacy_encrypt(privacy_system, mimeinfo, encrypt_data) || (fp = my_tmpfile()) == NULL || procmime_write_mimeinfo(mimeinfo, fp) < 0) { if (fp) fclose(fp); procmime_mimeinfo_free_all(mimeinfo); g_free(from); g_free(smtpserver); slist_free_strings(to_list); g_slist_free(to_list); slist_free_strings(newsgroup_list); g_slist_free(newsgroup_list); g_free(savecopyfolder); g_free(replymessageid); g_free(fwdmessageid); g_free(privacy_system); g_free(encrypt_data); return -1; } rewind(fp); if (!save_clear_text) { gchar *content = NULL; FILE *tmpfp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmp_enc_file); if (tmpfp) { fclose(tmpfp); content = file_read_stream_to_str(fp); rewind(fp); str_write_to_file(content, tmp_enc_file); g_free(content); } else { g_warning("couldn't get tempfile\n"); } } procmime_mimeinfo_free_all(mimeinfo); filepos = 0; } if (to_list) { debug_print("Sending message by mail\n"); if (!from) { g_warning("Queued message header is broken.\n"); mailval = -1; } else if (mailac && mailac->use_mail_command && mailac->mail_command && (* mailac->mail_command)) { mailval = send_message_local(mailac->mail_command, fp); local = 1; } else { if (!mailac) { mailac = account_find_from_smtp_server(from, smtpserver); if (!mailac) { g_warning("Account not found. " "Using current account...\n"); mailac = cur_account; } } if (mailac) mailval = send_message_smtp(mailac, to_list, fp); else { PrefsAccount tmp_ac; g_warning("Account not found.\n"); memset(&tmp_ac, 0, sizeof(PrefsAccount)); tmp_ac.address = from; tmp_ac.smtp_server = smtpserver; tmp_ac.smtpport = SMTP_PORT; mailval = send_message_smtp(&tmp_ac, to_list, fp); } } } fseek(fp, filepos, SEEK_SET); if (newsgroup_list && (mailval == 0)) { Folder *folder; gchar *tmp = NULL; FILE *tmpfp; /* write to temporary file */ tmp = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(), G_DIR_SEPARATOR, (gint)file); if ((tmpfp = fopen(tmp, "wb")) == NULL) { FILE_OP_ERROR(tmp, "fopen"); newsval = -1; alertpanel_error(_("Could not create temporary file for news sending.")); } else { if (change_file_mode_rw(tmpfp, tmp) < 0) { FILE_OP_ERROR(tmp, "chmod"); g_warning("can't change file mode\n"); } while ((newsval == 0) && fgets(buf, sizeof(buf), fp) != NULL) { if (fputs(buf, tmpfp) == EOF) { FILE_OP_ERROR(tmp, "fputs"); newsval = -1; alertpanel_error(_("Error when writing temporary file for news sending.")); } } fclose(tmpfp); if (newsval == 0) { debug_print("Sending message by news\n"); folder = FOLDER(newsac->folder); newsval = news_post(folder, tmp); if (newsval < 0) { alertpanel_error(_("Error occurred while posting the message to %s ."), newsac->nntp_server); } } unlink(tmp); } g_free(tmp); } fclose(fp); /* save message to outbox */ if (mailval == 0 && newsval == 0 && savecopyfolder) { FolderItem *outbox; debug_print("saving sent message...\n"); outbox = folder_find_item_from_identifier(savecopyfolder); if (!outbox) outbox = folder_get_default_outbox(); if (save_clear_text || tmp_enc_file == NULL) { procmsg_save_to_outbox(outbox, file, TRUE); } else { procmsg_save_to_outbox(outbox, tmp_enc_file, FALSE); } } if (tmp_enc_file != NULL) { unlink(tmp_enc_file); free(tmp_enc_file); tmp_enc_file = NULL; } if (replymessageid != NULL || fwdmessageid != NULL) { gchar **tokens; FolderItem *item; if (replymessageid != NULL) tokens = g_strsplit(replymessageid, "\x7f", 0); else tokens = g_strsplit(fwdmessageid, "\x7f", 0); item = folder_find_item_from_identifier(tokens[0]); /* check if queued message has valid folder and message id */ if (item != NULL && tokens[2] != NULL) { MsgInfo *msginfo; msginfo = folder_item_get_msginfo(item, atoi(tokens[1])); /* check if referring message exists and has a message id */ if ((msginfo != NULL) && (msginfo->msgid != NULL) && (strcmp(msginfo->msgid, tokens[2]) != 0)) { procmsg_msginfo_free(msginfo); msginfo = NULL; } if (msginfo == NULL) { msginfo = folder_item_get_msginfo_by_msgid(item, tokens[2]); } if (msginfo != NULL) { if (replymessageid != NULL) { procmsg_msginfo_unset_flags(msginfo, MSG_FORWARDED, 0); procmsg_msginfo_set_flags(msginfo, MSG_REPLIED, 0); } else { procmsg_msginfo_unset_flags(msginfo, MSG_REPLIED, 0); procmsg_msginfo_set_flags(msginfo, MSG_FORWARDED, 0); } procmsg_msginfo_free(msginfo); } } g_strfreev(tokens); } g_free(from); g_free(smtpserver); slist_free_strings(to_list); g_slist_free(to_list); slist_free_strings(newsgroup_list); g_slist_free(newsgroup_list); g_free(savecopyfolder); g_free(replymessageid); g_free(fwdmessageid); g_free(privacy_system); g_free(encrypt_data); return (newsval != 0 ? newsval : mailval); }
gboolean pgpmime_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data) { MimeInfo *msgcontent, *encmultipart, *newinfo; FILE *fp; gchar *boundary, *enccontent; size_t len; gchar *textstr; gpgme_data_t gpgtext = NULL, gpgenc = NULL; gpgme_ctx_t ctx = NULL; gpgme_key_t *kset = NULL; gchar **fprs = g_strsplit(encrypt_data, " ", -1); gint i = 0; gpgme_error_t err; while (fprs[i] && strlen(fprs[i])) { i++; } kset = g_malloc(sizeof(gpgme_key_t)*(i+1)); memset(kset, 0, sizeof(gpgme_key_t)*(i+1)); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); g_free(kset); return FALSE; } i = 0; while (fprs[i] && strlen(fprs[i])) { gpgme_key_t key; err = gpgme_get_key(ctx, fprs[i], &key, 0); if (err) { debug_print("can't add key '%s'[%d] (%s)\n", fprs[i],i, gpgme_strerror(err)); privacy_set_error(_("Couldn't add GPG key %s, %s"), fprs[i], gpgme_strerror(err)); g_free(kset); return FALSE; } debug_print("found %s at %d\n", fprs[i], i); kset[i] = key; i++; } debug_print("Encrypting message content\n"); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ encmultipart = procmime_mimeinfo_new(); encmultipart->type = MIMETYPE_MULTIPART; encmultipart->subtype = g_strdup("encrypted"); boundary = generate_mime_boundary("Encrypt"); g_hash_table_insert(encmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(encmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-encrypted")); g_node_append(encmultipart->node, msgcontent->node); /* write message content to temporary file */ fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file, %s"), g_strerror(errno)); g_free(kset); return FALSE; } procmime_write_mimeinfo(encmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); /* encrypt data */ gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgenc); gpgme_set_armor(ctx, 1); cm_gpgme_data_rewind(gpgtext); err = gpgme_op_encrypt(ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, gpgtext, gpgenc); enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len); gpgme_data_release(gpgtext); g_free(textstr); g_free(kset); if (enccontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Encryption failed, %s"), gpgme_strerror(err)); gpgme_release(ctx); g_free(enccontent); return FALSE; } /* create encrypted multipart */ g_node_unlink(msgcontent->node); procmime_mimeinfo_free_all(&msgcontent); g_node_append(mimeinfo->node, encmultipart->node); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-encrypted"); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_strdup("Version: 1\n"); g_node_append(encmultipart->node, newinfo->node); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("octet-stream"); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, enccontent, len); newinfo->data.mem[len] = '\0'; g_node_append(encmultipart->node, newinfo->node); g_free(enccontent); gpgme_release(ctx); return TRUE; }
static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo) { MimeInfo *encinfo, *decinfo, *parseinfo; gpgme_data_t cipher = NULL, plain = NULL; static gint id = 0; FILE *dstfp; gchar *fname; gpgme_verify_result_t sigstat = NULL; PrivacyDataPGP *data = NULL; gpgme_ctx_t ctx; gchar *chars; size_t len; gpgme_error_t err; if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return NULL; } cm_return_val_if_fail(pgpmime_is_encrypted(mimeinfo), NULL); encinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 1)->data; cipher = sgpgme_data_from_mimeinfo(encinfo); plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx); gpgme_data_release(cipher); if (plain == NULL) { debug_print("plain is null!\n"); gpgme_release(ctx); return NULL; } fname = g_strdup_printf("%s%cplaintext.%08x", get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id); if ((dstfp = claws_fopen(fname, "wb")) == NULL) { FILE_OP_ERROR(fname, "claws_fopen"); privacy_set_error(_("Couldn't open decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } if (fprintf(dstfp, "MIME-Version: 1.0\n") < 0) { FILE_OP_ERROR(fname, "fprintf"); claws_fclose(dstfp); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } chars = sgpgme_data_release_and_get_mem(plain, &len); if (len > 0) { if (claws_fwrite(chars, 1, len, dstfp) < len) { FILE_OP_ERROR(fname, "claws_fwrite"); g_free(chars); claws_fclose(dstfp); privacy_set_error(_("Couldn't write to decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } } g_free(chars); if (claws_safe_fclose(dstfp) == EOF) { FILE_OP_ERROR(fname, "claws_fclose"); privacy_set_error(_("Couldn't close decrypted file %s"), fname); g_free(fname); gpgme_data_release(plain); gpgme_release(ctx); debug_print("can't open!\n"); return NULL; } parseinfo = procmime_scan_file(fname); g_free(fname); if (parseinfo == NULL) { gpgme_release(ctx); privacy_set_error(_("Couldn't parse decrypted file.")); return NULL; } decinfo = g_node_first_child(parseinfo->node) != NULL ? g_node_first_child(parseinfo->node)->data : NULL; if (decinfo == NULL) { privacy_set_error(_("Couldn't parse decrypted file parts.")); gpgme_release(ctx); return NULL; } g_node_unlink(decinfo->node); procmime_mimeinfo_free_all(&parseinfo); decinfo->tmp = TRUE; if (sigstat != NULL && sigstat->signatures != NULL) { if (decinfo->privacy != NULL) { data = (PrivacyDataPGP *) decinfo->privacy; } else { data = pgpmime_new_privacydata(); decinfo->privacy = (PrivacyData *) data; } if (data != NULL) { data->done_sigtest = TRUE; data->is_signed = TRUE; data->sigstatus = sigstat; if (data->ctx) gpgme_release(data->ctx); data->ctx = ctx; } } else gpgme_release(ctx); return decinfo; }