static Template *template_load(gchar *filename, guint tmplid) { Template *tmpl; FILE *fp; gchar buf[BUFFSIZE]; if ((fp = g_fopen(filename, "rb")) == NULL) { FILE_OP_ERROR(filename, "fopen"); return NULL; } tmpl = g_new(Template, 1); tmpl->tmplid = tmplid; tmpl->name = NULL; tmpl->to = NULL; tmpl->cc = NULL; tmpl->bcc = NULL; tmpl->replyto = NULL; tmpl->subject = NULL; tmpl->value = NULL; while (fgets(buf, sizeof(buf), fp) != NULL) { if (buf[0] == '\n') break; else if (!g_ascii_strncasecmp(buf, "Name:", 5)) tmpl->name = g_strdup(g_strstrip(buf + 5)); else if (!g_ascii_strncasecmp(buf, "To:", 3)) tmpl->to = g_strdup(g_strstrip(buf + 3)); else if (!g_ascii_strncasecmp(buf, "Cc:", 3)) tmpl->cc = g_strdup(g_strstrip(buf + 3)); else if (!g_ascii_strncasecmp(buf, "Bcc:", 3)) tmpl->bcc = g_strdup(g_strstrip(buf + 4)); else if (!g_ascii_strncasecmp(buf, "Reply-To:", 9)) tmpl->replyto = g_strdup(g_strstrip(buf + 9)); else if (!g_ascii_strncasecmp(buf, "Subject:", 8)) tmpl->subject = g_strdup(g_strstrip(buf + 8)); } if (!tmpl->name) { g_warning("wrong template format\n"); template_free(tmpl); return NULL; } tmpl->value = file_read_stream_to_str(fp); if (!tmpl->value) { g_warning("cannot read template body\n"); template_free(tmpl); return NULL; } fclose(fp); return tmpl; }
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_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent, *sigmultipart, *newinfo; gchar *textstr, *micalg = NULL; FILE *fp; gchar *boundary = NULL; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; gpgme_error_t err; size_t len; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; gchar *test_msg; fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(mimeinfo, fp); rewind(fp); /* read temporary file into memory */ test_msg = file_read_stream_to_str(fp); claws_fclose(fp); memset (&info, 0, sizeof info); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ sigmultipart = procmime_mimeinfo_new(); sigmultipart->type = MIMETYPE_MULTIPART; sigmultipart->subtype = g_strdup("signed"); do { g_free(boundary); boundary = generate_mime_boundary("Sig"); } while (strstr(test_msg, boundary) != NULL); g_free(test_msg); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-signature")); g_node_append(sigmultipart->node, msgcontent->node); g_node_append(mimeinfo->node, sigmultipart->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)); return FALSE; } procmime_write_mimeinfo(sigmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgsig); 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 FALSE; } gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); gpgme_signers_clear (ctx); if (!sgpgme_setup_signers(ctx, account, from_addr)) { gpgme_release(ctx); return FALSE; } prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (g_getenv("GPG_AGENT_INFO") && prefs_gpg_get_config()->use_gpg_agent) { debug_print("GPG_AGENT_INFO environment defined, running without passphrase callback\n"); } else { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_DETACH); if (err != GPG_ERR_NO_ERROR) { if (err == GPG_ERR_CANCELED) { /* ignore cancelled signing */ privacy_reset_error(); debug_print("gpgme_op_sign cancelled\n"); } else { privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err)); debug_print("gpgme_op_sign error : %x\n", err); } gpgme_release(ctx); return FALSE; } result = gpgme_op_sign_result(ctx); if (result && result->signatures) { gpgme_new_signature_t sig = result->signatures; if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { gchar *down_algo = g_ascii_strdown(gpgme_hash_algo_name( result->signatures->hash_algo), -1); micalg = g_strdup_printf("pgp-%s", down_algo); g_free(down_algo); } else { micalg = g_strdup(gpgme_hash_algo_name( result->signatures->hash_algo)); } while (sig) { debug_print("valid signature: %s\n", sig->fpr); sig = sig->next; } } else if (result && result->invalid_signers) { gpgme_invalid_key_t invalid = result->invalid_signers; while (invalid) { g_warning("invalid signer: %s (%s)", invalid->fpr, gpgme_strerror(invalid->reason)); privacy_set_error(_("Data signing failed due to invalid signer: %s"), gpgme_strerror(invalid->reason)); invalid = invalid->next; } gpgme_release(ctx); return FALSE; } else { /* can't get result (maybe no signing key?) */ debug_print("gpgme_op_sign_result error\n"); privacy_set_error(_("Data signing failed, no results.")); gpgme_release(ctx); return FALSE; } sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len); gpgme_data_release(gpgtext); g_free(textstr); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); g_free(micalg); g_free(sigcontent); return FALSE; } /* add signature */ g_hash_table_insert(sigmultipart->typeparameters, g_strdup("micalg"), micalg); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-signature"); newinfo->description = g_strdup(_("OpenPGP digital signature")); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, sigcontent, len); newinfo->data.mem[len] = '\0'; g_node_append(sigmultipart->node, newinfo->node); g_free(sigcontent); gpgme_release(ctx); return TRUE; }