#include "autofaces.h"
#include "spell_entry.h"
#include "headers.h"
+#ifdef USE_LDAP
+#include "password.h"
+#include "ldapserver.h"
+#endif
enum
{
static void activate_privacy_system (Compose *compose,
PrefsAccount *account,
gboolean warn);
-static void compose_use_signing(Compose *compose, gboolean use_signing);
-static void compose_use_encryption(Compose *compose, gboolean use_encryption);
static void compose_toggle_return_receipt_cb(GtkToggleAction *action,
gpointer data);
static void compose_toggle_remove_refs_cb(GtkToggleAction *action,
else
gtk_entry_set_text(GTK_ENTRY(compose->from_name), buf);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
g_free(tmp);
}
gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);
compose_attach_from_list(compose, quote_fmt_get_attachments_list(), FALSE);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
g_free(subject);
g_free(tmp);
for (curr = attach_files ; curr != NULL ; curr = curr->next) {
ainfo = (AttachInfo *) curr->data;
- compose_attach_append(compose, ainfo->file, ainfo->file,
+ if (ainfo->insert)
+ compose_insert_file(compose, ainfo->file);
+ else
+ compose_attach_append(compose, ainfo->file, ainfo->file,
ainfo->content_type, ainfo->charset);
}
}
if (privacy_avail && g_slist_length(privacy_avail)) {
privacy = (gchar *)(privacy_avail->data);
}
+ g_slist_free_full(privacy_avail, g_free);
}
if (privacy != NULL) {
if (system) {
else
gtk_entry_set_text(GTK_ENTRY(compose->from_name), buf);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
g_free(tmp);
}
else
gtk_entry_set_text(GTK_ENTRY(compose->from_name), buf);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
g_free(tmp);
procmsg_msginfo_free(&full_msginfo);
else
gtk_entry_set_text(GTK_ENTRY(compose->from_name), buf);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
g_free(tmp);
}
compose_check_all(NULL, compose);
break;
#endif
+ case A_PRIVACY_SIGN:
+ break;
+ case A_PRIVACY_ENCRYPT:
+ break;
default:
break;
}
if (msginfo->inreplyto && *msginfo->inreplyto)
compose->inreplyto = g_strdup(msginfo->inreplyto);
- if (msginfo->msgid && *msginfo->msgid)
+ if (msginfo->msgid && *msginfo->msgid &&
+ compose->folder != NULL &&
+ compose->folder->stype == F_DRAFT)
compose->msgid = g_strdup(msginfo->msgid);
} else {
if (msginfo->msgid && *msginfo->msgid)
quote_fmt_parse();
buf = quote_fmt_get_buffer();
+
if (buf == NULL)
alertpanel_error(_("The \"Quotation mark\" of the template is invalid."));
else
}
buf = quote_fmt_get_buffer();
+
if (buf == NULL) {
gint line = quote_fmt_get_line();
alertpanel_error(err_msg, line);
+
goto error;
}
+
} else
buf = "";
gint len;
FILE *fp;
gboolean prev_autowrap;
+#ifdef G_OS_WIN32
+ GFile *f;
+ GFileInfo *fi;
+ GError *error = NULL;
+#else
GStatBuf file_stat;
+#endif
int ret;
+ goffset size;
GString *file_contents = NULL;
ComposeInsertResult result = COMPOSE_INSERT_SUCCESS;
cm_return_val_if_fail(file != NULL, COMPOSE_INSERT_NO_FILE);
/* get the size of the file we are about to insert */
+#ifdef G_OS_WIN32
+ f = g_file_new_for_path(file);
+ fi = g_file_query_info(f, "standard::size",
+ G_FILE_QUERY_INFO_NONE, NULL, &error);
+ ret = 0;
+ if (error != NULL) {
+ g_warning(error->message);
+ ret = 1;
+ g_error_free(error);
+ g_object_unref(f);
+ }
+#else
ret = g_stat(file, &file_stat);
+#endif
if (ret != 0) {
gchar *shortfile = g_path_get_basename(file);
alertpanel_error(_("Could not get size of file '%s'."), shortfile);
g_free(shortfile);
return COMPOSE_INSERT_NO_FILE;
} else if (prefs_common.warn_large_insert == TRUE) {
+#ifdef G_OS_WIN32
+ size = g_file_info_get_size(fi);
+ g_object_unref(fi);
+ g_object_unref(f);
+#else
+ size = file_stat.st_size;
+#endif
/* ask user for confirmation if the file is large */
if (prefs_common.warn_large_insert_size < 0 ||
- file_stat.st_size > (prefs_common.warn_large_insert_size * 1024)) {
+ size > ((goffset) prefs_common.warn_large_insert_size * 1024)) {
AlertValue aval;
gchar *msg;
msg = g_strdup_printf(_("You are about to insert a file of %s "
"in the message body. Are you sure you want to do that?"),
- to_human_readable(file_stat.st_size));
+ to_human_readable(size));
aval = alertpanel_full(_("Are you sure?"), msg, GTK_STOCK_CANCEL,
g_strconcat("+", _("_Insert"), NULL), NULL, TRUE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
g_free(msg);
return TRUE;
}
-static void compose_use_signing(Compose *compose, gboolean use_signing)
+void compose_use_signing(Compose *compose, gboolean use_signing)
{
compose->use_signing = use_signing;
cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/Sign", use_signing);
}
-static void compose_use_encryption(Compose *compose, gboolean use_encryption)
+void compose_use_encryption(Compose *compose, gboolean use_encryption)
{
compose->use_encryption = use_encryption;
cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/Encrypt", use_encryption);
}
clen = g_unichar_to_utf8(wc, ch);
- if (clen != 1)
- return 0;
-
- if (!strchr("*-+", ch[0]))
+ if (!((clen == 1 && strchr("*-+", ch[0])) ||
+ (clen == 3 && (
+ wc == 0x2022 || /* BULLET */
+ wc == 0x2023 || /* TRIANGULAR BULLET */
+ wc == 0x2043 || /* HYPHEN BULLET */
+ wc == 0x204c || /* BLACK LEFTWARDS BULLET */
+ wc == 0x204d || /* BLACK RIGHTWARDS BULLET */
+ wc == 0x2219 || /* BULLET OPERATOR */
+ wc == 0x25d8 || /* INVERSE BULLET */
+ wc == 0x25e6 || /* WHITE BULLET */
+ wc == 0x2619 || /* REVERSED ROTATED FLORAL HEART BULLET */
+ wc == 0x2765 || /* ROTATED HEAVY BLACK HEART BULLET */
+ wc == 0x2767 || /* ROTATED FLORAL HEART BULLET */
+ wc == 0x29be || /* CIRCLED WHITE BULLET */
+ wc == 0x29bf /* CIRCLED BULLET */
+ ))))
return 0;
gtk_text_iter_forward_char(&iter);
GTK_STOCK_CANCEL, button_label, NULL, TRUE, NULL,
ALERT_QUESTION, G_ALERTDEFAULT);
g_free(message);
+ g_free(button_label);
if (aval & G_ALERTDISABLE) {
aval &= ~G_ALERTDISABLE;
prefs_common.warn_empty_subj = FALSE;
entry = gtk_editable_get_chars(GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
g_strstrip(header);
g_strstrip(entry);
- if ((entry[0] != '\0')
- && (strcmp(header, prefs_common_translated_header_name("To:"))
- || strcmp(header, prefs_common_translated_header_name("Cc:")))) {
+ if ((entry[0] != '\0') &&
+ (!strcmp(header, prefs_common_translated_header_name("To:")) ||
+ !strcmp(header, prefs_common_translated_header_name("Cc:")))) {
cnt++;
}
g_free(header);
g_free(message);
if (aval & G_ALERTDISABLE) {
aval &= ~G_ALERTDISABLE;
- prefs_common.warn_empty_subj = FALSE;
+ prefs_common.warn_sending_many_recipients_num = 0;
}
if (aval != G_ALERTALTERNATE)
return FALSE;
get_rfc822_date_hide_tz(date, sizeof(date));
else
get_rfc822_date(date, sizeof(date));
- err |= (fprintf(fp, "Resent-Date: %s\n", buf) < 0);
+ err |= (fprintf(fp, "Resent-Date: %s\n", date) < 0);
/* Resent-From */
if (compose->account->name && *compose->account->name) {
static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gboolean attach_parts)
{
GtkTextBuffer *buffer;
- GtkTextIter start, end;
+ GtkTextIter start, end, tmp;
gchar *chars, *tmp_enc_file, *content;
gchar *buf, *msg;
const gchar *out_codeset;
mimemsg->data.mem = compose_get_header(compose);
/* Create text part MimeInfo */
- /* get all composed text */
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(compose->text));
- gtk_text_buffer_get_start_iter(buffer, &start);
gtk_text_buffer_get_end_iter(buffer, &end);
+ tmp = end;
+
+ /* We make sure that there is a newline at the end. */
+ if (action == COMPOSE_WRITE_FOR_SEND && gtk_text_iter_backward_char(&tmp)) {
+ chars = gtk_text_buffer_get_text(buffer, &tmp, &end, FALSE);
+ if (*chars != '\n') {
+ gtk_text_buffer_insert(buffer, &end, "\n", 1);
+ }
+ g_free(chars);
+ }
+
+ /* get all composed text */
+ gtk_text_buffer_get_start_iter(buffer, &start);
chars = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
out_codeset = conv_get_charset_str(compose->out_encoding);
AttachInfo *ainfo;
GtkTreeView *tree_view = GTK_TREE_VIEW(compose->attach_clist);
MimeInfo *mimepart;
+#ifdef G_OS_WIN32
+ GFile *f;
+ GFileInfo *fi;
+ GError *error = NULL;
+#else
GStatBuf statbuf;
+#endif
+ goffset size;
gchar *type, *subtype;
GtkTreeModel *model;
GtkTreeIter iter;
}
continue;
}
+#ifdef G_OS_WIN32
+ f = g_file_new_for_path(ainfo->file);
+ fi = g_file_query_info(f, "standard::size",
+ G_FILE_QUERY_INFO_NONE, NULL, &error);
+ if (error != NULL) {
+ g_warning(error->message);
+ g_error_free(error);
+ g_object_unref(f);
+ return -1;
+ }
+ size = g_file_info_get_size(fi);
+ g_object_unref(fi);
+ g_object_unref(f);
+#else
if (g_stat(ainfo->file, &statbuf) < 0)
return -1;
+ size = statbuf.st_size;
+#endif
mimepart = procmime_mimeinfo_new();
mimepart->content = MIMECONTENT_FILE;
mimepart->data.filename = g_strdup(ainfo->file);
mimepart->tmp = FALSE; /* or we destroy our attachment */
mimepart->offset = 0;
- mimepart->length = statbuf.st_size;
+ mimepart->length = size;
type = g_strdup(ainfo->content_type);
{
/* return the untranslated header name, if header_name is a known
header name, in either its translated or untranslated form, with
- or without trailing colon. return NULL if no matching header name
- is found or if header_name is NULL. */
+ or without trailing colon. otherwise, returns header_name. */
gchar *translated_header_name;
gchar *translated_header_name_wcolon;
const gchar *untranslated_header_name;
}
}
debug_print("compose_untranslated_header_name: unknown header '%s'\n", header_name);
- return NULL;
+ return header_name;
}
static void compose_add_headerfield_from_headerlist(Compose *compose,
g_slist_foreach(extra_headers, (GFunc)compose_add_extra_header, (gpointer)model);
}
+#ifdef USE_LDAP
+static void _ldap_srv_func(gpointer data, gpointer user_data)
+{
+ LdapServer *server = (LdapServer *)data;
+ gboolean *enable = (gboolean *)user_data;
+
+ debug_print("%s server '%s'\n", (*enable == TRUE ? "enabling" : "disabling"), server->control->hostName);
+ server->searchFlag = *enable;
+}
+#endif
+
static void compose_create_header_entry(Compose *compose)
{
gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
g_signal_connect(G_OBJECT(entry), "populate-popup",
G_CALLBACK(compose_entry_popup_extend),
NULL);
-
+
+#ifdef USE_LDAP
+#ifndef PASSWORD_CRYPTO_OLD
+ GSList *pwd_servers = addrindex_get_password_protected_ldap_servers();
+ if (pwd_servers != NULL && master_passphrase() == NULL) {
+ gboolean enable = FALSE;
+ debug_print("Master passphrase not available, disabling password-protected LDAP servers for this compose window.\n");
+ /* Temporarily disable password-protected LDAP servers,
+ * because user did not provide a master passphrase.
+ * We can safely enable searchFlag on all servers in this list
+ * later, since addrindex_get_password_protected_ldap_servers()
+ * includes servers which have it enabled initially. */
+ g_slist_foreach(pwd_servers, _ldap_srv_func, &enable);
+ compose->passworded_ldap_servers = pwd_servers;
+ }
+#endif /* PASSWORD_CRYPTO_OLD */
+#endif /* USE_LDAP */
+
address_completion_register_entry(GTK_ENTRY(entry), TRUE);
headerentry->compose = compose;
FolderItem *dest;
gchar * path;
- dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL, FALSE);
+ dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL, FALSE,
+ _("Select folder to save message to"));
if (!dest) return;
path = folder_item_get_identifier(dest);
cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/Sign", can_sign);
cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/Encrypt", can_encrypt);
+ if (compose->toolbar->privacy_sign_btn != NULL) {
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(compose->toolbar->privacy_sign_btn),
+ can_sign);
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(compose->toolbar->privacy_sign_btn),
+ can_sign ? compose->use_signing : FALSE);
+ }
+ if (compose->toolbar->privacy_encrypt_btn != NULL) {
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(compose->toolbar->privacy_encrypt_btn),
+ can_encrypt);
+ gtk_toggle_tool_button_set_active(
+ GTK_TOGGLE_TOOL_BUTTON(compose->toolbar->privacy_encrypt_btn),
+ can_encrypt ? compose->use_encryption : FALSE);
+ }
}
static void compose_update_privacy_system_menu_item(Compose * compose, gboolean warn)
cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/Sign", can_sign);
cm_menu_set_sensitive_full(compose->ui_manager, "Menu/Options/Encrypt", can_encrypt);
-}
-
+ if (compose->toolbar->privacy_sign_btn != NULL) {
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(compose->toolbar->privacy_sign_btn),
+ can_sign);
+ }
+ if (compose->toolbar->privacy_encrypt_btn != NULL) {
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(compose->toolbar->privacy_encrypt_btn),
+ can_encrypt);
+ }
+}
+
static void compose_set_out_encoding(Compose *compose)
{
CharSet out_encoding;
compose_template_apply_fields(compose, tmpl);
compose_attach_from_list(compose, quote_fmt_get_attachments_list(), FALSE);
quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
+
compose_changed_cb(NULL, compose);
#ifdef USE_ENCHANT
tr = g_strdup(C_("'%s' stands for a header name",
"Template '%s' format error."));
text = g_strdup_printf(tr, prefs_common_translated_header_name(header));
- alertpanel_error(text);
+ alertpanel_error("%s", text);
g_free(text);
g_free(tr);
} else {
gtk_entry_set_text(GTK_ENTRY(compose->from_name), buf);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
if (tmpl->to && *tmpl->to != '\0') {
} else {
compose_entry_append(compose, buf, COMPOSE_TO, PREF_TEMPLATE);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
if (tmpl->cc && *tmpl->cc != '\0') {
} else {
compose_entry_append(compose, buf, COMPOSE_CC, PREF_TEMPLATE);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
if (tmpl->bcc && *tmpl->bcc != '\0') {
} else {
compose_entry_append(compose, buf, COMPOSE_BCC, PREF_TEMPLATE);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
if (tmpl->replyto && *tmpl->replyto != '\0') {
} else {
compose_entry_append(compose, buf, COMPOSE_REPLYTO, PREF_TEMPLATE);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
/* process the subject */
} else {
gtk_entry_set_text(GTK_ENTRY(compose->subject_entry), buf);
}
+
+ quote_fmt_reset_vartable();
+ quote_fmtlex_destroy();
}
procmsg_msginfo_free( &dummyinfo );
compose_list = g_list_remove(compose_list, compose);
+#ifdef USE_LDAP
+ gboolean enable = TRUE;
+ g_slist_foreach(compose->passworded_ldap_servers,
+ _ldap_srv_func, &enable);
+ g_slist_free(compose->passworded_ldap_servers);
+#endif
+
if (compose->updating) {
debug_print("danger, not destroying anything now\n");
compose->deferred_destroy = TRUE;
compose_close(compose);
return TRUE;
} else {
+#ifdef G_OS_WIN32
+ GFile *f;
+ GFileInfo *fi;
+ GTimeVal tv;
+ GError *error;
+#else
GStatBuf s;
+#endif
gchar *path;
+ goffset size, mtime;
path = folder_item_fetch_msg(draft, msgnum);
if (path == NULL) {
debug_print("can't fetch %s:%d\n", draft->path, msgnum);
goto unlock;
}
+#ifdef G_OS_WIN32
+ f = g_file_new_for_path(path);
+ fi = g_file_query_info(f, "standard::size,time::modified",
+ G_FILE_QUERY_INFO_NONE, NULL, &error);
+ if (error != NULL) {
+ debug_print("couldn't query file info for '%s': %s\n",
+ path, error->message);
+ g_error_free(error);
+ g_free(path);
+ g_object_unref(f);
+ goto unlock;
+ }
+ size = g_file_info_get_size(fi);
+ g_file_info_get_modification_time(fi, &tv);
+ mtime = tv.tv_sec;
+ g_object_unref(fi);
+ g_object_unref(f);
+ g_free(path);
+#else
if (g_stat(path, &s) < 0) {
FILE_OP_ERROR(path, "stat");
g_free(path);
goto unlock;
}
+ size = s.st_size;
+ mtime = s.st_mtime;
+#endif
g_free(path);
procmsg_msginfo_free(&(compose->targetinfo));
compose->targetinfo = procmsg_msginfo_new();
compose->targetinfo->msgnum = msgnum;
- compose->targetinfo->size = (goffset)s.st_size;
- compose->targetinfo->mtime = s.st_mtime;
+ compose->targetinfo->size = size;
+ compose->targetinfo->mtime = mtime;
compose->targetinfo->folder = draft;
if (target_locked)
procmsg_msginfo_set_flags(compose->targetinfo, MSG_LOCKED, 0);
Compose *compose = (Compose *)data;
compose->use_signing = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(compose->toolbar->privacy_sign_btn), compose->use_signing);
}
static void compose_toggle_encrypt_cb(GtkToggleAction *action, gpointer data)
Compose *compose = (Compose *)data;
compose->use_encryption = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(compose->toolbar->privacy_encrypt_btn), compose->use_encryption);
}
static void activate_privacy_system(Compose *compose, PrefsAccount *account, gboolean warn)
ComposeHeaderEntry *headerentry)
{
gtk_entry_set_text(GTK_ENTRY(headerentry->entry), "");
+ gtk_widget_modify_base(GTK_WIDGET(headerentry->entry), GTK_STATE_NORMAL, NULL);
+ gtk_widget_modify_text(GTK_WIDGET(headerentry->entry), GTK_STATE_NORMAL, NULL);
return FALSE;
}