2004-09-15 Pawel Salek * libbalsa/mailbox_mbox.c: rollback on write errors (#590). 2004-09-12 Pawel Salek * libbalsa/mailbox_imap.c: display infoprint for large messages. * src/balsa-mblist.c: assure minimal size of the destination selection dialog for message move action. * libbalsa/imap-server.c: do not pass null strings to g_strdup_printf(). 2004-09-10 Pawel Salek * libbalsa/address-entry.[hc]: make fill_input() public. * src/sendmsg-window.c: use it. * libbalsa/send.c: remove x-balsa-fcc from sent messages. 2004-09-08 Pawel Salek * src/message-window.c: change defaults for touch-ui build. * libbalsa/address-book-gpe.c: armour against persons with multiple addresses (#533) 2004-09-07 Pawel Salek * src/message-window.c: add close toolbar button (#504). * libbalsa/send.c: attempt to address #555. * src/sendmsg-window.[hc]: unregister identities listener. * src/folder-conf.c: bug workaround disabled by default. 2004-09-04 Pawel Salek * libbalsa/imap-server.c: set timeout to 30s. * libbalsa/mailbox_imap.c: handle missing envelopes gracefully. * src/balsa-index.c: ditto. Do not overwrite error msg. * libbalsa/send.c: fix mispelling. * libbalsa/imap/imap-handle.[hc], imap_private.h: timeout setup. * libinit_balsa/balsa-druid-page-finish.c: fix regression introduced yesterday. 2004-09-03 Pawel Salek * libbalsa/address-book-gpe.c: more consistent behaviour (perhaps needs to be discussed). * libbalsa/mailbox_imap.c: detect and work around Exchange bugs explicitely (#333). * libbalsa/imap/imap-{commands,handle}.c: set ::can_fetch_body. * libbalsa/imap/imap-handle.h: add ImapMboxHandle::can_fetch_body. * libinit_balsa/balsa-initdruid.c: quit on destroy signal (#484). * src/expand-alias.c: expand addresses differently (#479). 2004-09-02 Pawel Salek Handle parts' content-id for imap mailboxes. * libbalsa/body.[hc]: add content-id field and use it. * libbalsa/mailbox_imap.c: set it. * libbalsa/imap/imap-handle.c: store received content id. * libbalsa/imap/libimap.h: ... in ImapBody field. * src/balsa-index.c: gtk-2.4.9 has FIXED_HEIGHT bugs fixed. Uff. 2004-08-31 Pawel Salek * libbalsa/message.h, send.h: order sending related declarations. * libbalsa/misc.c: do not get wrapping confused by '\r'. * libbalsa/send.c: move messages to sentbox AFTER relaying. * src/balsa-app.[hc]: define balsa_find_sentbox_by_url(). * src/balsa-mblist.c: GValue MUST be initialized. * src/balsa-message.c: avoid double-spacing for nonwrapped text. * src/main-window.c: changed sending API. * src/sendmsg-window.c: ditto. 2004-08-30 Pawel Salek * libbalsa/imap-server.[hc]: some infrastructure for server bugs workarounds (I do not really want to go there...) * libbalsa/mailbox{,_local}.c: move _release_message() from LibBalsaMailboxLocal to LibBalsaMailbox * libbalsa/mailbox_imap.c: reuse full message cache better. * src/{mailbox,folder}-conf.c: configure server bug workarounds. 2004-08-29 Pawel Salek * libbalsa/address-book-gpe.c: port minor fixes from HEAD. * libbalsa/imap/imap-handle.c: remove debugging printf()s. * src/balsa-message.c: ditto. * libbalsa/send.c: fix calls to smtp_set_header_option(). 2004-08-27 Pawel Salek * libbalsa/mailbox_imap.c: connect get-password once. * libbalsa/server.c: ditto. * libbalsa/mailbox_mbox.c: be a little more careful when parsing (PB, perhaps 212). * src/balsa-app.c: ref properly. * src/mailbox-node.c: disconnect the signals. * src/save-restore.c: connect the signals properly. * src/toolbar-factory.c: #408: nickh meant "Send/Check". 2004-08-26 Pawel Salek * libbalsa/mailbox_imap.c: decrease chunk length from 40 to 20. * libbalsa/imap-server.h: remove dependency on libimap.h * libbalsa/mailbox_{imap,pop3}.[hc]: simplify API slightly. * libbalsa/send.c: send via smtp service by default. * libbalsa/address-book-gpe.c: fix #434. * libinit_balsa/balsa-druid-page-{directory,finish,user,welcome}.[hc]: new wizard (#245). * libinit_balsa/balsa-initdruid.c: reduce number of pages in the wizard. * libinit_balsa/helper.[hc]: implement add_table_option and checkbox. * src/main-window.c: change "Check" toolbar button to "Send/Receive" (#8) * src/pref-manager.c: remove apply by nickh's request. attempt to fix #408. * src/toolbar-factory.c: chang string "Exchange" to "Send/Receive". 2004-08-24 Pawel Salek * src/address-book-config.c: fix GPE _modify_. * libbalsa/address-book-gpe.c: follows tags as gpe-contacts does not what doc says. * src/print.c: work around #343. 2004-08-23 Pawel Salek * libalsa/mailbox.c: take sort_type() into account when inserting new msg. * src/address-book-config.c: fix bugs in GPE configuration. * libbalsa/address-book-gpe.c: fix completion support. * libbalsa/address-book-gpe.h: compilation fixes. * src/address-book-config.c: ditto. * src/main-window.c: menu mispellings fixed. * src/sendmsg-window.c: ditto. 2004-08-22 Pawel Salek * src/balsa-app.h: change default widths and printing fonts. * src/balsa-mblist.c: shorten column names. * src/save-restore.c: widths again. * libbalsa/mailbox_pop3.c: update progess more frequently. 2004-08-21 Pawel Salek * configure.in: add SQLite configuration. * libbalsa/address-book.c: expand aliases by default. * libbalsa/address-book-gpe.[hc]: implement. * libbalsa/address-book-ldap.c: attr are local. * libbalsa/libbalsa.c: register GPE address book. * libbalsa/mailbox.c: change default sort order. * libbalsa/Makefile.am: add GPE. * libinit_balsa/balsa-druid-page-finish.c: make GPE address book default. * src/ab-main.c: register GPE. * src/balsa-bonobo.c: fixed getStats. * src/Balsa.idl: add getStats. * src/main.c: make -s work for unitialized balsa. * src/main-window.c: sorting changes as Nick requested. * src/pref-manager.c: add gpe config. 2004-08-16 Pawel Salek * libbalsa/send.c: set default mail sending dialog size, remove SMTP codes from messages. * src/main-window.c: set default mail checking dialog size. src/sendmsg-window.c: change entries order: [From], To, CC, Subject, [FCC] + modal dialogs (older). diff -ur --exclude-from=exclude-files --new-file balsa-ref/configure.in balsa/codiff -ur --exclude-from=exclude-files --new-file balsa-ref/configure.in balsa/configure.in --- balsa-ref/configure.in 2004-08-08 14:55:33.000000000 +0200 +++ balsa/configure.in 2004-08-21 23:20:24.000000000 +0200 @@ -338,6 +338,30 @@ AC_MSG_RESULT([no]) fi +dnl ######################################################################### +dnl Check for SQLite/GPE +dnl ######################################################################### + +AC_ARG_WITH([sqlite], + AC_HELP_STRING([--with-sqlite=DIR], + [Use SQLite for GPE address books (default=no)]),[ + with_sqlite=$withval +],[ + with_sqlite=no +]) +AC_MSG_CHECKING(whether to use SQLite) +if test x$with_sqlite != xno ; then + AC_MSG_RESULT([yes]) + PKG_CHECK_MODULES(SQLITE, [ + sqlite >= 2.8 + ]) + AC_DEFINE(HAVE_SQLITE,1,[If defined, enable GPE address book support.]) + BALSA_CFLAGS="$BALSA_CFLAGS $SQLITE_CFLAGS" + BALSA_LIBS="$BALSA_LIBS $SQLITE_LIBS" +else + AC_MSG_RESULT([no]) +fi + dnl ########################################################################## dnl Have ESMTP ? dnl ########################################################################## diff -ur --exclude-from=exclude-files --new-file balsa-ref/imap-server-patch balsa/imap-server-patch --- balsa-ref/imap-server-patch 1970-01-01 01:00:00.000000000 +0100 +++ balsa/imap-server-patch 2004-09-12 23:44:09.000000000 +0200 @@ -0,0 +1,25 @@ +--- libbalsa/imap-server.c.orig 2004-09-12 23:40:40.511733893 +0200 ++++ libbalsa/imap-server.c 2004-09-12 23:43:51.570710696 +0200 +@@ -125,13 +125,15 @@ + static void libbalsa_imap_server_set_host(LibBalsaServer * server, + const gchar * host, gboolean use_ssl) + { +- LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); +- G_LOCK(imap_servers); +- g_hash_table_steal(imap_servers, imap_server->key); +- g_free(imap_server->key); +- imap_server->key = g_strdup_printf("%s@%s", server->user, host); +- g_hash_table_insert(imap_servers, imap_server->key, imap_server); +- G_UNLOCK(imap_servers); ++ if(server->user && host) { /* we have been initialized... */ ++ LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); ++ G_LOCK(imap_servers); ++ g_hash_table_steal(imap_servers, imap_server->key); ++ g_free(imap_server->key); ++ imap_server->key = g_strdup_printf("%s@%s", server->user, host); ++ g_hash_table_insert(imap_servers, imap_server->key, imap_server); ++ G_UNLOCK(imap_servers); ++ } + (parent_class)->set_host(server, host, use_ssl); + } + static void diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-book.c balsa/libbalsa/address-book.c --- balsa-ref/libbalsa/address-book.c 2003-08-31 00:51:39.000000000 +0200 +++ balsa/libbalsa/address-book.c 2004-08-21 23:20:19.000000000 +0200 @@ -177,7 +177,7 @@ ab->config_prefix = NULL; ab->name = NULL; - ab->expand_aliases = FALSE; + ab->expand_aliases = TRUE; ab->dist_list_mode = FALSE; ab->is_expensive = FALSE; } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-book-gpe.c balsa/libbalsa/address-book-gpe.c --- balsa-ref/libbalsa/address-book-gpe.c 1970-01-01 01:00:00.000000000 +0100 +++ balsa/libbalsa/address-book-gpe.c 2004-09-09 00:41:10.000000000 +0200 @@ -0,0 +1,614 @@ +/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ +/* Balsa E-Mail Client + * + * Copyright (C) 1997-2003 Stuart Parmenter and others, + * See the file AUTHORS for a list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* + * GPE address book + * NOTES: + See + http://cvs.handhelds.org/cgi-bin/viewcvs.cgi/gpe/base/gpe-contacts + Tags must be UPPERCASE. + */ +#include "config.h" + +#if defined(HAVE_SQLITE) + +#include +#include +#include +#include +#include +#include + +#include "address-book.h" +#include "address-book-gpe.h" +#include "information.h" + +#define ASSURE_GPE_DIR\ + do {gchar* dir = g_strconcat(g_get_home_dir(), "/.gpe", NULL);\ + mkdir(dir, S_IRUSR|S_IWUSR|S_IXUSR); g_free(dir);}while(0) + +static LibBalsaAddressBookClass *parent_class = NULL; + +static void +libbalsa_address_book_gpe_class_init(LibBalsaAddressBookGpeClass * + klass); +static void libbalsa_address_book_gpe_init(LibBalsaAddressBookGpe * ab); +static void libbalsa_address_book_gpe_finalize(GObject * object); + +static LibBalsaABErr libbalsa_address_book_gpe_load(LibBalsaAddressBook * ab, + const gchar *filter, + LibBalsaAddressBookLoadFunc callback, + gpointer closure); + +static void +libbalsa_address_book_gpe_close_db(LibBalsaAddressBookGpe *ab); +static LibBalsaABErr +libbalsa_address_book_gpe_add_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address); +static LibBalsaABErr +libbalsa_address_book_gpe_remove_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address); +static LibBalsaABErr +libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address, + LibBalsaAddress *newval); + + +static GList *libbalsa_address_book_gpe_alias_complete(LibBalsaAddressBook *ab, + const gchar *prefix, + gchar **new_prefix); + +GType libbalsa_address_book_gpe_get_type(void) +{ + static GType address_book_gpe_type = 0; + + if (!address_book_gpe_type) { + static const GTypeInfo address_book_gpe_info = { + sizeof(LibBalsaAddressBookGpeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) libbalsa_address_book_gpe_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(LibBalsaAddressBookGpe), + 0, /* n_preallocs */ + (GInstanceInitFunc) libbalsa_address_book_gpe_init + }; + + address_book_gpe_type = + g_type_register_static(LIBBALSA_TYPE_ADDRESS_BOOK, + "LibBalsaAddressBookGpe", + &address_book_gpe_info, 0); + } + + return address_book_gpe_type; +} + +static void +libbalsa_address_book_gpe_class_init(LibBalsaAddressBookGpeClass * klass) +{ + LibBalsaAddressBookClass *address_book_class; + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent(klass); + + object_class = G_OBJECT_CLASS(klass); + address_book_class = LIBBALSA_ADDRESS_BOOK_CLASS(klass); + + object_class->finalize = libbalsa_address_book_gpe_finalize; + + address_book_class->load = libbalsa_address_book_gpe_load; + address_book_class->add_address = libbalsa_address_book_gpe_add_address; + address_book_class->remove_address = + libbalsa_address_book_gpe_remove_address; + address_book_class->modify_address = + libbalsa_address_book_gpe_modify_address; + + address_book_class->alias_complete = + libbalsa_address_book_gpe_alias_complete; +} + +static void +libbalsa_address_book_gpe_init(LibBalsaAddressBookGpe * ab) +{ + ab->db = NULL; + LIBBALSA_ADDRESS_BOOK(ab)->is_expensive = FALSE; +} + +static void +libbalsa_address_book_gpe_finalize(GObject * object) +{ + libbalsa_address_book_gpe_close_db(LIBBALSA_ADDRESS_BOOK_GPE(object)); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +LibBalsaAddressBook * +libbalsa_address_book_gpe_new(const gchar *name) +{ + LibBalsaAddressBookGpe *gpe; + LibBalsaAddressBook *ab; + + gpe = LIBBALSA_ADDRESS_BOOK_GPE(g_object_new + (LIBBALSA_TYPE_ADDRESS_BOOK_GPE, + NULL)); + ab = LIBBALSA_ADDRESS_BOOK(gpe); + + ab->name = g_strdup(name); + /* We open on demand... */ + gpe->db = NULL; + return ab; +} + +/* + * Close the SQLite db.... + */ +static void +libbalsa_address_book_gpe_close_db(LibBalsaAddressBookGpe * ab) +{ + if (ab->db) { + sqlite_close(ab->db); + ab->db = NULL; + } +} + +/* + * Opens the SQLite db + */ +#define DB_NAME "/.gpe/contacts" +static const char *schema_str = +"create table contacts (urn INTEGER NOT NULL, tag TEXT NOT NULL, " +"value TEXT NOT NULL)"; + +static const char *schema2_str = +"create table contacts_urn (urn INTEGER PRIMARY KEY)"; + +static int +libbalsa_address_book_gpe_open_db(LibBalsaAddressBookGpe * ab) +{ + gchar *name, *errmsg = NULL; + + ASSURE_GPE_DIR; + name = g_strconcat(g_get_home_dir(), DB_NAME, NULL); + ab->db = sqlite_open(name, 0, &errmsg); + g_free(name); + if(ab->db == NULL) { + printf("Cannot open: %s\n", errmsg); + free(errmsg); + return 0; + } + sqlite_exec (ab->db, schema_str, NULL, NULL, NULL); + sqlite_exec (ab->db, schema2_str, NULL, NULL, NULL); + + return 1; +} + + +/* libbalsa_address_book_gpe_get_address: + * a callback to fill in the LibBalsaAddress object. + * see http://www.handhelds.org:8080/wiki/WellKnownDBTags for tag list + * We only use limited subset. + * + given_name # how to handle "J. Edgar Hoover"? + middle_initial + family_name # nb family name is written first in many cultures + nickname + home_email # multiple addresses, separated by commas + work_organization + work_email # multiple addresses, separated by commas +*/ + + +static int +gpe_read_attr(void *arg, int argc, char **argv, char **names) +{ + LibBalsaAddress * a= arg; + + /* follow read_entry_data/db_set_multi_data */ + if(g_ascii_strcasecmp(argv[0], "NAME") == 0 && + !a->full_name) a->full_name = g_strdup(argv[1]); + else if(g_ascii_strcasecmp(argv[0], "GIVEN_NAME") == 0 && + !a->first_name) a->first_name = g_strdup(argv[1]); + else if(g_ascii_strcasecmp(argv[0], "FAMILY_NAME") == 0 && + !a->last_name) a->last_name = g_strdup(argv[1]); + else if(g_ascii_strcasecmp(argv[0], "NICKNAME") == 0 && + !a->nick_name) a->nick_name = g_strdup(argv[1]); + else if(g_ascii_strcasecmp(argv[0], "WORK.ORGANIZATION") == 0 && + !a->organization) a->organization = g_strdup(argv[1]); + else if(g_ascii_strcasecmp(argv[0], "HOME.EMAIL") == 0) + a->address_list = g_list_prepend(a->address_list, g_strdup(argv[1])); + else if(g_ascii_strcasecmp(argv[0], "WORK.EMAIL") == 0) + a->address_list = g_list_prepend(a->address_list, g_strdup(argv[1])); + return 0; +} + +/* + * create_name() + * + * Creates a full name from a given first name and surname. + * + * Returns: + * gchar * a full name + * NULL on failure (both first and last names invalid. + */ +static gchar * +create_name(gchar * first, gchar * last) +{ + if ((first == NULL) && (last == NULL)) + return NULL; + else if (first == NULL) + return g_strdup(last); + else if (last == NULL) + return g_strdup(first); + else + return g_strdup_printf("%s %s", first, last); +} + +struct gpe_closure { + LibBalsaAddressBookLoadFunc callback; + gpointer closure; + LibBalsaAddressBookGpe *gpe; +}; + +static int +gpe_read_address(void *arg, int argc, char **argv, char **names) +{ + struct gpe_closure *gc = arg; + LibBalsaAddress * a= libbalsa_address_new(); + guint uid = atoi(argv[0]); + + /* follow read_entry_data. FIXME: error reporting */ + sqlite_exec_printf (gc->gpe->db, + "select tag,value from contacts where urn=%d", + gpe_read_attr, a, NULL, uid); + if(!a->address_list) { /* entry without address: ignore! */ + g_object_unref(a); + return 0; + } + if(!a->full_name) + a->full_name = create_name(a->first_name, a->last_name); + g_object_set_data(G_OBJECT(a), "urn", GUINT_TO_POINTER(uid)); + gc->callback(LIBBALSA_ADDRESS_BOOK(gc->gpe), a, gc->closure); + return 0; +} + + +/* + * gpe_load: + * opens the db only if needed. + */ +static LibBalsaABErr +libbalsa_address_book_gpe_load(LibBalsaAddressBook * ab, + const gchar *filter, + LibBalsaAddressBookLoadFunc callback, + gpointer closure) +{ + LibBalsaAddressBookGpe *gpe_ab; + gchar *err = NULL; + struct gpe_closure gc; + int r; + LibBalsaABErr ret; + + g_return_val_if_fail ( LIBBALSA_IS_ADDRESS_BOOK_GPE(ab), LBABERR_OK); + + if (callback == NULL) + return LBABERR_OK; + + gpe_ab = LIBBALSA_ADDRESS_BOOK_GPE(ab); + + if (gpe_ab->db == NULL) + if (!libbalsa_address_book_gpe_open_db(gpe_ab)) + return LBABERR_CANNOT_CONNECT; + + gc.callback = callback; + gc.closure = closure; + gc.gpe = gpe_ab; + /* FIXME: error reporting */ + if(filter && *filter) { + r = sqlite_exec_printf + (gpe_ab->db, + "select distinct urn from contacts where " + "(upper(tag)='FAMILY_NAME' or upper(tag)='GIVEN_NAME' or " + "upper(tag)='NAME' or " + "upper(tag)='WORK.EMAIL' or upper(tag)='HOME.EMAIL') " + "and value LIKE '%q%%'", + gpe_read_address, &gc, &err, filter); + } else { + r = sqlite_exec(gpe_ab->db, "select distinct urn from contacts_urn", + gpe_read_address, &gc, &err); + } + + if(r != SQLITE_OK) { + printf("r=%d err=%s\n", r, err); + libbalsa_address_book_set_status(ab, err); + free(err); + ret = LBABERR_CANNOT_READ; + } else { + libbalsa_address_book_set_status(ab, NULL); + ret = LBABERR_OK; + } + + callback(ab, NULL, closure); + return ret; +} + +#define INSERT_ATTR(db,id,attr,val) \ + do { if( (val) && *(val)) {\ + sqlite_exec_printf((db), "insert into contacts values ('%d', '%q', '%q')",\ + NULL, NULL, NULL, (id), (attr), (val));}} while(0); + +static LibBalsaABErr +libbalsa_address_book_gpe_add_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address) +{ + LibBalsaAddressBookGpe *gpe_ab = LIBBALSA_ADDRESS_BOOK_GPE(ab); + int r; + guint id; + char *err = NULL; + + g_return_val_if_fail(address, LBABERR_CANNOT_WRITE); + g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE); + + if (gpe_ab->db == NULL) { + if(!libbalsa_address_book_gpe_open_db(gpe_ab)) + return LBABERR_CANNOT_CONNECT; + } + r = sqlite_exec(gpe_ab->db, "insert into contacts_urn values (NULL)", + NULL, NULL, &err); + if (r != SQLITE_OK) { + libbalsa_address_book_set_status(ab, err); + free(err); + return LBABERR_CANNOT_WRITE; + } + /* FIXME: duplicate detection! */ + + id = sqlite_last_insert_rowid(gpe_ab->db); + INSERT_ATTR(gpe_ab->db,id, "NAME", address->full_name); + INSERT_ATTR(gpe_ab->db,id, "GIVEN_NAME", address->first_name); + INSERT_ATTR(gpe_ab->db,id, "FAMILY_NAME", address->last_name); + INSERT_ATTR(gpe_ab->db,id, "NICKNAME", address->nick_name); + INSERT_ATTR(gpe_ab->db,id, "WORK.ORGANIZATION", address->organization); + INSERT_ATTR(gpe_ab->db,id, "WORK.EMAIL", + (char*)address->address_list->data); + sqlite_exec_printf(gpe_ab->db, "insert into contacts values " + "('%d', 'MODIFIED', %d)", NULL, NULL, NULL, + id, time(NULL)); + return LBABERR_OK; +} +static gchar* +db_delete_by_uid(sqlite *db, guint uid) +{ + int r; + gchar *err; + + if( (r=sqlite_exec(db, "begin transaction", + NULL, NULL, &err)) == SQLITE_OK) + return err; + + if( (r=sqlite_exec_printf(db, "delete from contacts where urn='%d'", + NULL, NULL, &err, uid)) == SQLITE_OK && + (r=sqlite_exec_printf(db, "delete from contacts_urn where urn='%d'", + NULL, NULL, &err, uid)) == SQLITE_OK && + (r=sqlite_exec(db, "commit transaction", NULL, + NULL, &err)) == SQLITE_OK) return NULL; + + sqlite_exec(db, "rollback transaction", NULL, NULL, NULL); + return err; +} + +static LibBalsaABErr +libbalsa_address_book_gpe_remove_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address) +{ + LibBalsaAddressBookGpe *gpe_ab = LIBBALSA_ADDRESS_BOOK_GPE(ab); + guint uid; + char *err; + g_return_val_if_fail(address, LBABERR_CANNOT_WRITE); + g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE); + + if (gpe_ab->db == NULL) { + if( !libbalsa_address_book_gpe_open_db(gpe_ab)) + return LBABERR_CANNOT_CONNECT; + } + uid = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(address), "urn")); + if(!uid)/* safety check, perhaps unnecessary */ + return LBABERR_CANNOT_WRITE; + + err = db_delete_by_uid(gpe_ab->db, uid); + if(err) { + libbalsa_address_book_set_status(ab, err); + free(err); + return LBABERR_CANNOT_WRITE; + } else return LBABERR_OK; +} + + +/** libbalsa_address_book_gpe_modify_address: + modify given address. +*/ +#define INSERT_ATTR_R(db,id,attr,val) \ + if( (val) && *(val)) {\ + if( (r=sqlite_exec_printf \ + ((db), "insert into contacts values ('%d', '%q', '%q')",\ + NULL, NULL, &err, (id), (attr), (val))) != SQLITE_OK)\ + goto rollback;} + +static LibBalsaABErr +libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab, + LibBalsaAddress *address, + LibBalsaAddress *newval) +{ + LibBalsaAddressBookGpe *gpe_ab = LIBBALSA_ADDRESS_BOOK_GPE(ab); + guint uid; + int r; + char *err; + + g_return_val_if_fail(address, LBABERR_CANNOT_WRITE); + g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE); + g_return_val_if_fail(newval->address_list, LBABERR_CANNOT_WRITE); + + if (gpe_ab->db == NULL) { + if( !libbalsa_address_book_gpe_open_db(gpe_ab)) + return LBABERR_CANNOT_CONNECT; + } + uid = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(address), "urn")); + /* safety check, perhaps unnecessary */ + g_return_val_if_fail(uid, LBABERR_CANNOT_WRITE); + + /* do the real work here */ + if( (r=sqlite_exec(gpe_ab->db, "begin transaction", + NULL, NULL, &err)) != SQLITE_OK) { + libbalsa_address_book_set_status(ab, err); + free(err); /* failed, so soon!? */ + return LBABERR_CANNOT_WRITE; + } + + if( (r=sqlite_exec_printf(gpe_ab->db, + "delete from contacts where urn='%d'", + NULL, NULL, &err, uid)) != SQLITE_OK) + goto rollback; + printf("newval: given_name: %s\n", newval->first_name); + INSERT_ATTR_R(gpe_ab->db,uid, "NAME", newval->full_name); + INSERT_ATTR_R(gpe_ab->db,uid, "GIVEN_NAME", newval->first_name); + INSERT_ATTR_R(gpe_ab->db,uid, "FAMILY_NAME", newval->last_name); + INSERT_ATTR_R(gpe_ab->db,uid, "NICKNAME", newval->nick_name); + INSERT_ATTR_R(gpe_ab->db,uid, "WORK.ORGANIZATION", newval->organization); + INSERT_ATTR_R(gpe_ab->db,uid, "WORK.EMAIL", + (char*)newval->address_list->data); + if( (r=sqlite_exec_printf(gpe_ab->db, "insert into contacts values " + "('%d', 'MODIFIED', %d)", NULL, NULL, &err, + uid, time(NULL))) != SQLITE_OK) + goto rollback; + + if( (r=sqlite_exec(gpe_ab->db, "commit transaction", NULL, + NULL, &err)) == SQLITE_OK) return LBABERR_OK; + + rollback: + libbalsa_address_book_set_status(ab, err); + free(err); + sqlite_exec(gpe_ab->db, "rollback transaction", NULL, NULL, NULL); + + return LBABERR_CANNOT_WRITE; +} + +struct gpe_completion_closure { + sqlite *db; + const gchar *prefix; + gchar **new_prefix; + GList *res; +}; +static void +strip_superflous_addresses(LibBalsaAddress *a) +{ + if(a->address_list) { + /* a person has several matching addresses of the same kind! */ + GList *l, *tmp; + for(l=a->address_list->next; l; l = tmp){ + tmp = l->next; + g_free(l->data); + a->address_list = g_list_delete_link(a->address_list, l); + } + } +} + +static int +gpe_read_completion(void *arg, int argc, char **argv, char **names) +{ + struct gpe_completion_closure *gc = arg; + LibBalsaAddress * a= libbalsa_address_new(); + guint uid = atoi(argv[0]); + gchar *tag = argv[1]; + + /* follow read_entry_data. FIXME: error reporting */ + if(strstr(tag, "EMAIL") != NULL) { /* be extra cautious - return just one address */ + sqlite_exec_printf + (gc->db, + "select tag,value from contacts where urn=%d" + " and (upper(tag)='FAMILY_NAME' or upper(tag)='GIVEN_NAME' or " + "upper(tag)='NAME' or " + "(upper(tag)='%q' and value LIKE '%q%%'))", + gpe_read_attr, a, NULL, uid, tag, gc->prefix); + } else { + sqlite_exec_printf(gc->db, + "select tag,value from contacts where urn=%d", + gpe_read_attr, a, NULL, uid); + } + if(!a->address_list) { /* entry without address: ignore! */ + g_object_unref(a); + return 0; + } + strip_superflous_addresses(a); + if(!a->full_name) + a->full_name = create_name(a->first_name, a->last_name); + g_object_set_data(G_OBJECT(a), "urn", GUINT_TO_POINTER(uid)); + if(!*gc->new_prefix) + *gc->new_prefix = libbalsa_address_to_gchar(a, 0); + gc->res = g_list_prepend(gc->res, a); + + return 0; +} + +static GList * +libbalsa_address_book_gpe_alias_complete(LibBalsaAddressBook * ab, + const gchar * prefix, + gchar ** new_prefix) +{ + static const char *query = + "select distinct urn,tag from contacts where " + "(upper(tag)='FAMILY_NAME' or upper(tag)='GIVEN_NAME' or " + "upper(tag)='NAME' or " + "upper(tag)='WORK.EMAIL' or upper(tag)='HOME.EMAIL') " + "and upper(value) LIKE '%q%%'"; + struct gpe_completion_closure gcc; + LibBalsaAddressBookGpe *gpe_ab; + char *err = NULL; + int r; + + g_return_val_if_fail ( LIBBALSA_ADDRESS_BOOK_GPE(ab), NULL); + + gpe_ab = LIBBALSA_ADDRESS_BOOK_GPE(ab); + + if (!ab->expand_aliases) return NULL; + if (gpe_ab->db == NULL) { + if( !libbalsa_address_book_gpe_open_db(gpe_ab)) + return NULL; + } + + *new_prefix = NULL; + gcc.db = gpe_ab->db; + gcc.prefix = prefix; + gcc.new_prefix = new_prefix; + gcc.res = NULL; + if(prefix) + r = sqlite_exec_printf(gpe_ab->db, query, + gpe_read_completion, &gcc, &err, + prefix); + else + r = sqlite_exec(gpe_ab->db, "select distinct urn from contacts_urn", + gpe_read_completion, &gcc, &err); + if(err) { + printf("r=%d err=%s\n", r, err); + free(err); + } + return gcc.res; +} +#endif /* WITH_SQLITE */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-book-gpe.h balsa/libbalsa/address-book-gpe.h --- balsa-ref/libbalsa/address-book-gpe.h 1970-01-01 01:00:00.000000000 +0100 +++ balsa/libbalsa/address-book-gpe.h 2004-08-23 10:12:17.000000000 +0200 @@ -0,0 +1,59 @@ +/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- */ +/* Balsa E-Mail Client + * + * Copyright (C) 1997-2003 Stuart Parmenter and others, + * See the file AUTHORS for a list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* + * The GPE address book ... + */ + +#ifndef __LIBBALSA_ADDRESS_BOOK_GPE_H__ +#define __LIBBALSA_ADDRESS_BOOK_GPE_H__ + +#ifdef HAVE_SQLITE + +#include + +#include "address-book.h" + +#define LIBBALSA_TYPE_ADDRESS_BOOK_GPE (libbalsa_address_book_gpe_get_type()) +#define LIBBALSA_ADDRESS_BOOK_GPE(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, LIBBALSA_TYPE_ADDRESS_BOOK_GPE, LibBalsaAddressBookGpe)) +#define LIBBALSA_ADDRESS_BOOK_GPE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (klass, LIBBALSA_TYPE_ADDRESS_BOOK_GPE, LibBalsaAddressBookGpeClass)) +#define LIBBALSA_IS_ADDRESS_BOOK_GPE(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, LIBBALSA_TYPE_ADDRESS_BOOK_GPE)) +#define LIBBALSA_IS_ADDRESS_BOOK_GPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE (klass, LIBBALSA_TYPE_ADDRESS_BOOK_GPE)) + +typedef struct _LibBalsaAddressBookGpe LibBalsaAddressBookGpe; +typedef struct _LibBalsaAddressBookGpeClass LibBalsaAddressBookGpeClass; + +struct _LibBalsaAddressBookGpe { + LibBalsaAddressBook parent; + sqlite *db; +}; + +struct _LibBalsaAddressBookGpeClass { + LibBalsaAddressBookClass parent_class; +}; + +GType libbalsa_address_book_gpe_get_type(void); + +LibBalsaAddressBook *libbalsa_address_book_gpe_new(const gchar *name); + +#endif /* HAVE_SQLITE */ +#endif /* __LIBBALSA_ADDRESS_BOOK_GPE_H__ */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-book-ldap.c balsa/libbalsa/address-book-ldap.c --- balsa-ref/libbalsa/address-book-ldap.c 2003-08-22 09:20:24.000000000 +0200 +++ balsa/libbalsa/address-book-ldap.c 2004-08-21 23:20:24.000000000 +0200 @@ -45,7 +45,7 @@ /* don't search when prefix has length shorter than LDAP_MIN_LEN */ static const unsigned LDAP_MIN_LEN=2; /* Which parameters do we want back? */ -char* attrs[] = { +static char* attrs[] = { "cn", /* maps to displayed name */ "mail", /* maps to itself */ "sn", /* maps to last name */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-entry.c balsa/libbalsa/address-entry.c --- balsa-ref/libbalsa/address-entry.c 2004-02-01 16:06:42.000000000 +0100 +++ balsa/libbalsa/address-entry.c 2004-09-11 00:20:01.000000000 +0200 @@ -26,7 +26,8 @@ #include "config.h" -#include +#include +#include #include /* @@ -609,7 +610,8 @@ * results: * Sets list and active fields of the LibBalsaAddressEntry *************************************************************/ -static void +#define libbalsa_fill_input libbalsa_address_entry_fill_input +void libbalsa_fill_input(LibBalsaAddressEntry *address_entry) { gint cursor, size = 0, prev; diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/address-entry.h balsa/libbalsa/address-entry.h --- balsa-ref/libbalsa/address-entry.h 2004-02-01 16:06:43.000000000 +0100 +++ balsa/libbalsa/address-entry.h 2004-09-11 00:20:01.000000000 +0200 @@ -104,6 +104,7 @@ void libbalsa_address_entry_set_domain(LibBalsaAddressEntry *, void *); void libbalsa_address_entry_clear_to_send(LibBalsaAddressEntry * address_entry); +void libbalsa_address_entry_fill_input(LibBalsaAddressEntry *address_entry); gboolean libbalsa_address_entry_matching(LibBalsaAddressEntry * address_entry); diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/body.c balsa/libbalsa/body.c --- balsa-ref/libbalsa/body.c 2004-08-07 19:39:48.000000000 +0200 +++ balsa/libbalsa/body.c 2004-09-02 23:19:56.000000000 +0200 @@ -500,6 +500,9 @@ if (bodyid && strcmp(id, bodyid) == 0) return body; + } else { + if(body->content_id && strcmp(id, body->content_id) == 0) + return body; } if ((res = libbalsa_message_body_get_by_id(body->parts, id)) != NULL) diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/body.h balsa/libbalsa/body.h --- balsa-ref/libbalsa/body.h 2004-08-07 19:39:48.000000000 +0200 +++ balsa/libbalsa/body.h 2004-09-02 23:19:56.000000000 +0200 @@ -59,6 +59,7 @@ * the body including mime type with * optional parameters. NULL, if text/plain. */ const gchar *content_dsp; /* content-disposition */ + const gchar *content_id; /* content-id */ gchar *filename; /* holds filename for attachments and such (used mostly for sending) */ gboolean attach_as_extbody; /* if an attachment shall be appended as external-body (sending) */ gchar *temp_filename; /* Holds the filename of a the temporary file where this part is saved */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/identity.c balsa/libbalsa/identity.c --- balsa-ref/libbalsa/identity.c 2004-08-02 23:28:23.000000000 +0200 +++ balsa/libbalsa/identity.c 2004-08-21 23:20:24.000000000 +0200 @@ -361,6 +361,7 @@ sdi->idle_handler_id = 0; sdi->dialog = dialog = gtk_dialog_new_with_buttons(prompt, parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, @@ -1147,6 +1148,7 @@ default_id = g_object_get_data(G_OBJECT(tree), "default-id"); g_return_if_fail(ident != *default_id); confirm = gtk_message_dialog_new(GTK_WINDOW(dialog), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/imap-commands.c balsa/libbalsa/imap/imap-commands.c --- balsa-ref/libbalsa/imap/imap-commands.c 2004-08-04 14:06:14.000000000 +0200 +++ balsa/libbalsa/imap/imap-commands.c 2004-09-03 20:22:37.000000000 +0200 @@ -194,6 +194,9 @@ int imap_mbox_handle_can_do(ImapMboxHandle* handle, ImapCapability cap) { + if(cap == IMCAP_FETCHBODY) + return handle->can_fetch_body; + /* perhaps it already has capabilities? */ if(!handle->has_capabilities) imap_check_capability(handle); @@ -260,8 +263,10 @@ rc= imap_cmd_exec(handle, cmd); g_free(cmd); if(rc == IMR_OK) { - g_free(handle->mbox); - handle->mbox = g_strdup(mbox); + if(handle->mbox != mbox) { /* we do not "reselect" */ + g_free(handle->mbox); + handle->mbox = g_strdup(mbox); + } handle->state = IMHS_SELECTED; if(readonly_mbox) *readonly_mbox = handle->readonly_mbox; diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/imap-handle.c balsa/libbalsa/imap/imap-handle.c --- balsa-ref/libbalsa/imap/imap-handle.c 2004-07-27 11:11:59.000000000 +0200 +++ balsa/libbalsa/imap/imap-handle.c 2004-09-04 19:27:04.000000000 +0200 @@ -125,6 +125,7 @@ { handle->host = NULL; handle->mbox = NULL; + handle->timeout = -1; handle->state = IMHS_DISCONNECTED; handle->has_capabilities = FALSE; handle->exists = 0; @@ -230,6 +231,14 @@ h->flags_arg = arg; } +void +imap_handle_set_timeout(ImapMboxHandle *h, int milliseconds) +{ + h->timeout = milliseconds; + if(h->sio) + sio_set_timeout(h->sio, milliseconds); +} + int imap_mbox_is_disconnected (ImapMboxHandle *h) { return IMAP_MBOX_IS_DISCONNECTED(h); } int imap_mbox_is_connected (ImapMboxHandle *h) @@ -384,6 +393,7 @@ /* reset some handle status */ handle->has_capabilities = FALSE; + handle->can_fetch_body = TRUE; if(handle->sio) { sio_detach(handle->sio); handle->sio = NULL; @@ -403,6 +413,8 @@ close(handle->sd); return IMAP_NOMEM; } + if(handle->timeout>0) + sio_set_timeout(handle->sio, handle->timeout); #ifdef USE_TLS if(handle->over_ssl) { SSL *ssl = imap_create_ssl(); @@ -428,7 +440,8 @@ handle->state = IMHS_DISCONNECTED; return IMAP_PROTOCOL_ERROR; } - + handle->can_fetch_body = + (strncmp(handle->last_msg, "Microsoft Exchange", 18) != 0); #if defined(USE_TLS) if(handle->over_ssl) resp = IMR_OK; /* secured already with SSL */ @@ -835,6 +848,7 @@ g_free(body->media_basic_name); g_free(body->media_subtype); g_free(body->desc); + g_free(body->content_id); g_free(body->content_dsp_other); g_free(body->content_uri); g_hash_table_destroy(body->params); @@ -995,7 +1009,7 @@ imap_body_set_id(ImapBody *body, char *id) { if(id) printf("part ID='%s'\n", id); - g_free(id); + body->content_id = id; } /* ================ END OF BODY STRUCTURE FUNCTIONS ==================== */ @@ -1098,8 +1112,7 @@ if(rc == IMR_BYE) { return handle->doing_logout ? IMR_UNTAGGED : IMR_BYE; } - if( rc!=IMR_OK) - puts("cmd_step protocol error"); + p = g_hash_table_lookup(handle->cmd_queue, GUINT_TO_POINTER(lastcmd)); if(p==NULL) /* True for initial response only: no command has been @@ -1417,7 +1430,7 @@ ir_no(ImapMboxHandle *h) { char line[LONG_STRING]; - puts("ir_no"); + sio_gets(h->sio, line, sizeof(line)); /* look for information response codes here: section 7.1 of the draft */ if( strlen(line)>2) { @@ -1461,8 +1474,10 @@ static ImapResponse ir_bye(ImapMboxHandle *h) { - int c; while( (c=sio_getc(h->sio))!=EOF && c != 0x0a); + char line[LONG_STRING]; + sio_gets(h->sio, line, sizeof(line)); if(!h->doing_logout) {/* it is not we, so it must be the server */ + imap_mbox_handle_set_msg(h, line); imap_mbox_handle_set_state(h, IMHS_DISCONNECTED); /* we close the connection here unless we are doing logout. */ if(h->sio) { sio_detach(h->sio); h->sio = NULL; } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/imap-handle.h balsa/libbalsa/imap/imap-handle.h --- balsa-ref/libbalsa/imap/imap-handle.h 2004-07-19 22:15:19.000000000 +0200 +++ balsa/libbalsa/imap/imap-handle.h 2004-09-04 19:27:04.000000000 +0200 @@ -74,6 +74,9 @@ IMCAP_CHILDREN, /* RFC 3348 */ IMCAP_LITERAL, /* RFC 2088 */ IMCAP_SASLIR, /* imap-sasl-initial-response: SASL-IR */ + IMCAP_FETCHBODY, /* basic imap implemented correctly by + * most imap servers but not all. We + * have to detect that. */ IMCAP_MAX } ImapCapability; @@ -106,6 +109,7 @@ void imap_handle_set_infocb(ImapMboxHandle* h, ImapInfoCb cb, void*); void imap_handle_set_usercb(ImapMboxHandle* h, ImapUserCb cb, void*); void imap_handle_set_flagscb(ImapMboxHandle* h, ImapFlagsCb cb, void*); +void imap_handle_set_timeout(ImapMboxHandle *, int milliseconds); ImapResult imap_mbox_handle_connect(ImapMboxHandle* r, const char *hst, int over_ssl); diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/imap_private.h balsa/libbalsa/imap/imap_private.h --- balsa-ref/libbalsa/imap/imap_private.h 2004-07-14 00:54:46.000000000 +0200 +++ balsa/libbalsa/imap/imap_private.h 2004-09-04 19:27:04.000000000 +0200 @@ -38,6 +38,7 @@ struct siobuf * sio; char *host; char* mbox; /* currently selected mailbox, if any */ + int timeout; /* timeout in milliseconds */ ImapConnectionState state; gboolean has_capabilities; @@ -82,6 +83,9 @@ unsigned using_tls:1; #endif unsigned readonly_mbox:1; + unsigned can_fetch_body:1; /* set for servers that always respond + * correctly to FETCH x BODY[y] + * requests. */ }; #define IMAP_MBOX_IS_DISCONNECTED(h) ((h)->state == IMHS_DISCONNECTED) diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/imap-tls.c balsa/libbalsa/imap/imap-tls.c --- balsa-ref/libbalsa/imap/imap-tls.c 2004-06-19 23:51:17.000000000 +0200 +++ balsa/libbalsa/imap/imap-tls.c 2004-08-21 23:20:24.000000000 +0200 @@ -46,6 +46,8 @@ #ifdef USE_TLS +/* OE build fails with pthread.h if _BSD_SOURCE is not defined */ +# define _BSD_SOURCE 1 #include #include #include diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap/libimap.h balsa/libbalsa/imap/libimap.h --- balsa-ref/libbalsa/imap/libimap.h 2004-07-19 22:15:19.000000000 +0200 +++ balsa/libbalsa/imap/libimap.h 2004-09-02 23:19:57.000000000 +0200 @@ -188,6 +188,7 @@ GHashTable *params; unsigned octets; unsigned lines; + char *content_id; char *desc; ImapEnvelope *envelope;/* used only if media/basic == MESSAGE */ ImapBodyDisposition content_dsp; diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap-server.c balsa/libbalsa/imap-server.c --- balsa-ref/libbalsa/imap-server.c 2004-08-07 19:09:43.000000000 +0200 +++ balsa/libbalsa/imap-server.c 2004-09-12 23:43:51.000000000 +0200 @@ -31,15 +31,16 @@ gchar *key; guint max_connections; gboolean offline_mode; - gboolean persistent_cache; /* if TRUE, messages will be cached in - $HOME and preserved between - sessions. If FALSE, messages will be - kept in /tmp and cleaned on exit. */ GMutex *lock; /* protects the following members */ guint used_connections; GList *used_handles; GList *free_handles; + unsigned persistent_cache:1; /* if TRUE, messages will be cached in + $HOME and preserved between + sessions. If FALSE, messages will be + kept in /tmp and cleaned on exit. */ + unsigned has_fetch_bug:1; }; typedef struct LibBalsaImapServerClass_ { @@ -109,25 +110,30 @@ static void libbalsa_imap_server_set_username(LibBalsaServer * server, const gchar * name) { - LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); - G_LOCK(imap_servers); - g_hash_table_steal(imap_servers, imap_server->key); - g_free(imap_server->key); - imap_server->key = g_strdup_printf("%s@%s", name, server->host); - g_hash_table_insert(imap_servers, imap_server->key, imap_server); - G_UNLOCK(imap_servers); + if(server->host && name) { /* we have been initialized... */ + LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); + + G_LOCK(imap_servers); + g_hash_table_steal(imap_servers, imap_server->key); + g_free(imap_server->key); + imap_server->key = g_strdup_printf("%s@%s", name, server->host); + g_hash_table_insert(imap_servers, imap_server->key, imap_server); + G_UNLOCK(imap_servers); + } (parent_class)->set_username(server, name); } static void libbalsa_imap_server_set_host(LibBalsaServer * server, const gchar * host, gboolean use_ssl) { - LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); - G_LOCK(imap_servers); - g_hash_table_steal(imap_servers, imap_server->key); - g_free(imap_server->key); - imap_server->key = g_strdup_printf("%s@%s", server->user, host); - g_hash_table_insert(imap_servers, imap_server->key, imap_server); - G_UNLOCK(imap_servers); + if(server->user && host) { /* we have been initialized... */ + LibBalsaImapServer *imap_server = LIBBALSA_IMAP_SERVER(server); + G_LOCK(imap_servers); + g_hash_table_steal(imap_servers, imap_server->key); + g_free(imap_server->key); + imap_server->key = g_strdup_printf("%s@%s", server->user, host); + g_hash_table_insert(imap_servers, imap_server->key, imap_server); + G_UNLOCK(imap_servers); + } (parent_class)->set_host(server, host, use_ssl); } static void @@ -280,6 +286,7 @@ * libbalsa_server_user_cb(). */ handle = imap_mbox_handle_new(); + imap_handle_set_timeout(handle, 30000); /* wait 30 seconds for packets */ info = g_new0(struct handle_info, 1); info->handle = handle; imap_handle_set_monitorcb(handle, monitor_cb, info); @@ -340,11 +347,11 @@ struct handle_info *info = list->data; if (info->last_used < idle_marker) { - if (imap_mbox_handle_noop(info->handle) != IMR_OK) - libbalsa_information(LIBBALSA_INFORMATION_WARNING, - _("Could not send \"%s\" to \"%s\""), - "NOOP", - LIBBALSA_SERVER(imap_server)->host); + /* ignore errors here - the point is to keep the + connection alive and if there is no connection, noop + will be, well, no-op. Other operations may possibly + reconnect. */ + imap_mbox_handle_noop(info->handle); } } @@ -454,7 +461,9 @@ conn_limit = gnome_config_get_int_with_default("ConnectionLimit", &d); if(!d) imap_server->max_connections = conn_limit; d1 = gnome_config_get_bool_with_default("PersistentCache", &d); - if(!d) imap_server->persistent_cache = d1; + if(!d) imap_server->persistent_cache = !!d1; + d1 = gnome_config_get_bool_with_default("HasFetchBug", &d); + if(!d) imap_server->has_fetch_bug = !!d1; if (!server->passwd) { server->remember_passwd = gnome_config_get_bool("RememberPasswd=false"); if(server->remember_passwd) @@ -479,6 +488,29 @@ libbalsa_server_save_config(LIBBALSA_SERVER(server)); gnome_config_set_int("ConnectionLimit", server->max_connections); gnome_config_set_bool("PersistentCache", server->persistent_cache); + gnome_config_set_bool("HasFetchBug", server->has_fetch_bug); +} + +/* handle_connection_error() releases handle_info data, clears password + and sets err apriopriately */ +static void +handle_connection_error(int rc, struct handle_info *info, + LibBalsaServer *server, GError **err) +{ + gchar *msg = imap_mbox_handle_get_last_msg(info->handle); + if(rc == IMAP_AUTH_FAILURE) + libbalsa_server_set_password(server, NULL); + if(rc != IMAP_CONNECT_FAILED) { + g_set_error(err, LIBBALSA_MAILBOX_ERROR, + LIBBALSA_MAILBOX_AUTH_ERROR, + _("Cannot connect to the server: %s"), msg); + } else + g_set_error(err, LIBBALSA_MAILBOX_ERROR, + LIBBALSA_MAILBOX_NETWORK_ERROR, + _("Cannot connect to the server")); + + g_free(msg); + lb_imap_server_info_free(info); } /** @@ -537,16 +569,7 @@ rc=imap_mbox_handle_connect(info->handle, server->host, REQ_SSL(server)); if(rc != IMAP_SUCCESS) { - gchar *msg = imap_mbox_handle_get_last_msg(info->handle); - if(rc == IMAP_AUTH_FAILURE) - libbalsa_server_set_password(server, NULL); - g_set_error(err, LIBBALSA_MAILBOX_ERROR, - rc != IMAP_CONNECT_FAILED - ? LIBBALSA_MAILBOX_AUTH_ERROR : - LIBBALSA_MAILBOX_NETWORK_ERROR, - _("Cannot connect to the server: %s"), msg); - g_free(msg); - lb_imap_server_info_free(info); + handle_connection_error(rc, info, server, err); g_mutex_unlock(imap_server->lock); return NULL; } @@ -642,14 +665,7 @@ rc=imap_mbox_handle_connect(info->handle, server->host, REQ_SSL(server)); if(rc != IMAP_SUCCESS) { - gchar *msg = imap_mbox_handle_get_last_msg(info->handle); - if(rc == IMAP_AUTH_FAILURE) - libbalsa_server_set_password(server, NULL); - g_set_error(err, LIBBALSA_MAILBOX_ERROR, - LIBBALSA_MAILBOX_OPEN_ERROR, - _("Cannot connect to the server: %s"), msg); - g_free(msg); - lb_imap_server_info_free(info); + handle_connection_error(rc, info, server, err); g_mutex_unlock(imap_server->lock); return NULL; } @@ -725,7 +741,7 @@ libbalsa_imap_server_enable_persistent_cache(LibBalsaImapServer *server, gboolean enable) { - server->persistent_cache = enable; + server->persistent_cache = !!enable; } gboolean libbalsa_imap_server_has_persistent_cache(LibBalsaImapServer *srv) @@ -824,3 +840,17 @@ if (offline) libbalsa_imap_server_force_disconnect(server); } + +void +libbalsa_imap_server_set_bug(LibBalsaImapServer *server, + LibBalsaImapServerBug bug, gboolean hasp) +{ + server->has_fetch_bug = !! hasp; +} + +gboolean +libbalsa_imap_server_has_bug(LibBalsaImapServer *server, + LibBalsaImapServerBug bug) +{ + return server->has_fetch_bug; +} diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/imap-server.h balsa/libbalsa/imap-server.h --- balsa-ref/libbalsa/imap-server.h 2004-07-28 21:54:47.000000000 +0200 +++ balsa/libbalsa/imap-server.h 2004-08-29 23:25:14.000000000 +0200 @@ -42,13 +42,13 @@ const gchar *host); LibBalsaImapServer* libbalsa_imap_server_new_from_config(void); void libbalsa_imap_server_save_config(LibBalsaImapServer *server); -ImapMboxHandle* libbalsa_imap_server_get_handle(LibBalsaImapServer *server, - GError **err); -ImapMboxHandle* libbalsa_imap_server_get_handle_with_user( - LibBalsaImapServer *imap_server, - gpointer user, GError **err); +struct _ImapMboxHandle* libbalsa_imap_server_get_handle + (LibBalsaImapServer *server, GError **err); +struct _ImapMboxHandle* libbalsa_imap_server_get_handle_with_user + (LibBalsaImapServer *imap_server, + gpointer user, GError **err); void libbalsa_imap_server_release_handle(LibBalsaImapServer *server, - ImapMboxHandle* handle); + struct _ImapMboxHandle* handle); void libbalsa_imap_server_set_max_connections(LibBalsaImapServer *server, int max); int libbalsa_imap_server_get_max_connections(LibBalsaImapServer *server); @@ -62,5 +62,15 @@ void libbalsa_imap_server_set_offline_mode(LibBalsaImapServer *server, gboolean offline); +typedef enum { + ISBUG_FETCH /* Some servers cannot fetch message parts properly + * we will fetch entire messages instead. */ +} LibBalsaImapServerBug; + +void libbalsa_imap_server_set_bug(LibBalsaImapServer *server, + LibBalsaImapServerBug bug, gboolean hasp); + +gboolean libbalsa_imap_server_has_bug(LibBalsaImapServer *server, + LibBalsaImapServerBug bug); extern gint ImapDebug; #endif /* __IMAP_SERVER_H__ */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/libbalsa.c balsa/libbalsa/libbalsa.c --- balsa-ref/libbalsa/libbalsa.c 2004-08-07 19:09:43.000000000 +0200 +++ balsa/libbalsa/libbalsa.c 2004-08-21 23:20:24.000000000 +0200 @@ -37,6 +37,7 @@ #include #endif +#include "address-book-gpe.h" #include "libbalsa.h" #include "misc.h" @@ -96,6 +97,9 @@ #if ENABLE_LDAP LIBBALSA_TYPE_ADDRESS_BOOK_LDAP; #endif +#if HAVE_SQLITE + LIBBALSA_TYPE_ADDRESS_BOOK_GPE; +#endif } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox.c balsa/libbalsa/mailbox.c --- balsa-ref/libbalsa/mailbox.c 2004-08-05 06:17:52.000000000 +0200 +++ balsa/libbalsa/mailbox.c 2004-08-29 23:25:14.000000000 +0200 @@ -387,6 +387,8 @@ mailbox->name = NULL; g_free(mailbox->url); mailbox->url = NULL; + libbalsa_condition_free(mailbox->view_filter); + mailbox->view_filter = NULL; /* The LibBalsaMailboxView is owned by balsa_app.mailbox_views. */ mailbox->view = NULL; @@ -767,7 +769,10 @@ libbalsa_mailbox_real_release_message(LibBalsaMailbox * mailbox, LibBalsaMessage * message) { - /* Default is noop. */ + if (message->mime_msg) { + g_object_unref(message->mime_msg); + message->mime_msg = NULL; + } } /* libbalsa_mailbox_real_change_msgs_flags() default implementation uses @@ -1114,7 +1119,11 @@ /* Insert node into the message tree before getting path. */ iter.user_data = g_node_new(GUINT_TO_POINTER(seqno)); iter.stamp = mailbox->stamp; - g_node_append(mailbox->msg_tree, iter.user_data); + if(libbalsa_mailbox_get_sort_type(mailbox) == LB_MAILBOX_SORT_TYPE_ASC) + g_node_append(mailbox->msg_tree, iter.user_data); + else + g_node_prepend(mailbox->msg_tree, iter.user_data); + path = gtk_tree_model_get_path(GTK_TREE_MODEL(mailbox), &iter); g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_INSERTED], 0, @@ -1846,8 +1855,13 @@ NULL, /* identity_name */ LB_MAILBOX_THREADING_FLAT, /* threading_type */ 0, /* filter */ +#if defined(ENABLE_TOUCH_UI) + LB_MAILBOX_SORT_TYPE_DESC, /* sort_type */ + LB_MAILBOX_SORT_NO, /* sort_field */ +#else LB_MAILBOX_SORT_TYPE_ASC, /* sort_type */ LB_MAILBOX_SORT_DATE, /* sort_field */ +#endif /* ENABLE_TOUCH_UI */ LB_MAILBOX_SHOW_UNSET, /* show */ 0, /* exposed */ 0, /* open */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_imap.c balsa/libbalsa/mailbox_imap.c --- balsa-ref/libbalsa/mailbox_imap.c 2004-08-06 17:02:26.000000000 +0200 +++ balsa/libbalsa/mailbox_imap.c 2004-09-12 23:08:46.000000000 +0200 @@ -35,6 +35,10 @@ #include #include +/* for open() */ +#include +#include + #ifdef BALSA_USE_THREADS #include #endif @@ -78,6 +82,8 @@ static off_t ImapCacheSize = 15*1024*1024; /* 15MB */ + /* issue message if downloaded part has more than this size */ +static unsigned SizeMsgThreshold = 50*1024; static void libbalsa_mailbox_imap_finalize(GObject * object); static void libbalsa_mailbox_imap_class_init(LibBalsaMailboxImapClass * klass); @@ -286,6 +292,10 @@ g_free(mailbox->path); mailbox->path = NULL; if(remote->server) { + g_signal_handlers_disconnect_matched(remote->server, + G_SIGNAL_MATCH_DATA, 0, + (GQuark) 0, NULL, NULL, + remote); g_object_unref(G_OBJECT(remote->server)); remote->server = NULL; } @@ -294,13 +304,13 @@ G_OBJECT_CLASS(parent_class)->finalize(object); } -GObject * +LibBalsaMailboxImap* libbalsa_mailbox_imap_new(void) { - LibBalsaMailbox *mailbox; + LibBalsaMailboxImap *mailbox; mailbox = g_object_new(LIBBALSA_TYPE_MAILBOX_IMAP, NULL); - return G_OBJECT(mailbox); + return mailbox; } /* libbalsa_mailbox_imap_update_url: @@ -473,10 +483,17 @@ LIBBALSA_INFORMATION_MMESSAGE here but it would be overwritten by login information... */ #define II(rc,h,line) \ - {int trials=2;do{rc=line; if(rc!= IMR_SEVERED) break;\ + {int trials=2;do{\ + if(imap_mbox_is_disconnected(h)) imap_mbox_handle_reconnect(h, NULL);\ + rc=line; \ + if(rc==IMR_SEVERED) \ + libbalsa_information(LIBBALSA_INFORMATION_WARNING, \ + _("IMAP connection has been severed. Reconnecting...")); \ + else if(rc==IMR_BYE) {char *msg = imap_mbox_handle_get_last_msg(h); \ libbalsa_information(LIBBALSA_INFORMATION_WARNING, \ - _("IMAP connection has been severed. Reconnecting..."));\ - imap_mbox_handle_reconnect(h, NULL);}while(trials-->0);} + _("IMAP server has shut the connection: %s Reconnecting..."), msg); \ + g_free(msg);}\ + else break;}while(trials-->0);} static ImapMboxHandle * libbalsa_mailbox_imap_get_handle(LibBalsaMailboxImap *mimap, GError **err) @@ -530,7 +547,7 @@ unsigned has_it; }; -static const unsigned MAX_CHUNK_LENGTH = 40; +static const unsigned MAX_CHUNK_LENGTH = 20; static gboolean collect_seq_cb(GNode *node, gpointer data) { @@ -562,8 +579,11 @@ struct collect_seq_data csd; ImapResponse rc; + /* This test too weak: I can imagine unsolicited ENVELOPE + * responses sent from server that wil create the ImapMessage + * structure but message size or UID etc will not be available. */ if( (imsg = imap_mbox_handle_get_msg(mimap->handle, msgno)) - != NULL) return imsg; + != NULL && imsg->envelope) return imsg; csd.needed_msgno = msgno; csd.msgno_arr = g_malloc(MAX_CHUNK_LENGTH*sizeof(csd.msgno_arr[0])); csd.cnt = 0; @@ -616,12 +636,15 @@ struct message_info *msg_info = message_info_from_msgno(mimap, seqno[i]); if(msg_info->message) { - /* we still should make sure the info is there since the - * libimap connection might have been severed. */ - ImapMessage *imsg = mi_get_imsg(mimap, seqno[i]); + /* since we are talking here about updating just received, + usually unsolicited flags from the server, we do not + need to go to great lengths to assure that the + connection is up. */ + ImapMessage *imsg = + imap_mbox_handle_get_msg(mimap->handle, seqno[i]); LibBalsaMessageFlag old_flags = msg_info->message->flags; GList *list; - + if(!imsg) continue; lbimap_update_flags(msg_info->message, imsg); libbalsa_mailbox_index_set_flags(mailbox, seqno[i], msg_info->message->flags); @@ -916,15 +939,14 @@ } static FILE* -get_cache_stream(LibBalsaMailbox *mailbox, unsigned uid) +get_cache_stream(LibBalsaMailbox *mailbox, LibBalsaMessage *msg) { + unsigned uid = IMAP_MESSAGE_UID(msg); LibBalsaMailboxImap *mimap = LIBBALSA_MAILBOX_IMAP(mailbox); FILE *stream; gchar **pair, *path; - unsigned uidval; g_assert(mimap->handle); - uidval = imap_mbox_handle_get_validity(mimap->handle); pair = get_cache_name_pair(mimap, "body", uid); path = g_strconcat(pair[0], "/", pair[1], NULL); stream = fopen(path, "rb"); @@ -934,7 +956,10 @@ libbalsa_assure_balsa_dir(); mkdir(pair[0], S_IRUSR|S_IWUSR|S_IXUSR); /* ignore errors */ - /* printf("%s path: %s\n", __FUNCTION__, path); */ + if(msg->length>(signed)SizeMsgThreshold) + libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, + _("Downloading %ld kB"), + msg->length/1024); cache = fopen(path, "wb"); II(rc,mimap->handle, imap_mbox_handle_fetch_rfc822_uid(mimap->handle, uid, cache)); @@ -969,7 +994,7 @@ return NULL; } - stream = get_cache_stream(mailbox, IMAP_MESSAGE_UID(message)); + stream = get_cache_stream(mailbox, message); libbalsa_unlock_mailbox(mailbox); return g_mime_stream_file_new(stream); @@ -1621,8 +1646,10 @@ g_return_val_if_fail(mimap->opened, FALSE); imsg = mi_get_imsg(mimap, message->msgno); - g_return_val_if_fail(imsg, FALSE); - g_return_val_if_fail(imsg->envelope, FALSE); + if(!imsg || !imsg->envelope) /* Connection severed and and restore + * failed - deal with it! */ + return FALSE; + lbimap_update_flags(message, imsg); lb_set_headers(message->headers, imsg->envelope, FALSE); @@ -1713,6 +1740,7 @@ case IMBDISP_OTHER: lbbody->content_dsp = imap_body->content_dsp_other; break; } + lbbody->content_id = imap_body->content_id; lbbody->content_type = imap_body_get_content_type(imap_body); /* get the name in the same way as g_mime_part_get_filename() does */ str = imap_body_get_dsp_param(imap_body, "filename"); @@ -1738,6 +1766,52 @@ } } +static gboolean +get_struct_from_cache(LibBalsaMailbox *mailbox, LibBalsaMessage *message, + LibBalsaFetchFlag flags) +{ + gchar **pair, *filename; + int fd; + GMimeStream *stream = NULL; + GMimeParser *mime_parser; + + g_return_val_if_fail(message->mime_msg == NULL, FALSE); + + pair = get_cache_name_pair(LIBBALSA_MAILBOX_IMAP(mailbox), "body", + IMAP_MESSAGE_UID(message)); + + filename = g_build_filename(pair[0], pair[1], NULL); + g_strfreev(pair); + fd = open(filename, O_RDONLY); + g_free(filename); + if(fd == -1) return FALSE; + + stream = g_mime_stream_fs_new(fd); + + mime_parser = g_mime_parser_new_with_stream(stream); + g_mime_parser_set_scan_from(mime_parser, FALSE); + message->mime_msg = g_mime_parser_construct_message(mime_parser); + g_object_unref(mime_parser); + g_mime_stream_unref(stream); + + /* follow libbalsa_mailbox_local_fetch_structure here; + * perhaps create common helper */ + if(flags & LB_FETCH_STRUCTURE) { + LibBalsaMessageBody *body = libbalsa_message_body_new(message); + libbalsa_message_body_set_mime_body(body, + message->mime_msg->mime_part); + libbalsa_message_append_part(message, body); + libbalsa_message_headers_from_gmime(message->headers, + message->mime_msg); + } + if(flags & LB_FETCH_RFC822_HEADERS) { + message->headers->user_hdrs = + libbalsa_message_user_hdrs_from_gmime(message->mime_msg); + message->has_all_headers = 1; + } + return TRUE; +} + static void libbalsa_mailbox_imap_fetch_structure(LibBalsaMailbox *mailbox, LibBalsaMessage *message, @@ -1745,8 +1819,26 @@ { ImapResponse rc; LibBalsaMailboxImap *mimap = LIBBALSA_MAILBOX_IMAP(mailbox); + LibBalsaServer *server; ImapFetchType ift = 0; g_return_if_fail(mimap->opened); + + /* work around some server bugs... */ + server = LIBBALSA_MAILBOX_REMOTE_SERVER(mailbox); + if(!imap_mbox_handle_can_do(mimap->handle, IMCAP_FETCHBODY) || + libbalsa_imap_server_has_bug(LIBBALSA_IMAP_SERVER(server), + ISBUG_FETCH)){ + /* we could optimize this part a little bit: we do not need to + * keep reopening the stream. */ + GMimeStream *stream = + libbalsa_mailbox_imap_get_message_stream(mailbox, message); + if(stream) + g_object_unref(stream); + } + + if(get_struct_from_cache(mailbox, message, flags)) + return; + if(flags & LB_FETCH_RFC822_HEADERS) ift |= IMFETCH_RFC822HEADERS_SELECTED; if(flags & LB_FETCH_STRUCTURE) ift |= IMFETCH_BODYSTRUCT; @@ -1856,100 +1948,105 @@ { GMimeStream *partstream = NULL; - if(!part->mime_part) { /* !part->mime_part */ - gchar **pair, *part_name; - LibBalsaMailboxImap *mimap = LIBBALSA_MAILBOX_IMAP(msg->mailbox); - FILE *fp; - gchar *section = get_section_for(msg, part); - - pair = get_cache_name_pair(mimap, "part", IMAP_MESSAGE_UID(msg)); - part_name = g_strconcat(pair[0], "/", pair[1], "-", section, NULL); - fp = fopen(part_name,"rb+"); - - if(!fp) { /* no cache element */ - struct part_data dt; - GMimePart *prefilt; - GMimeStream *gms; - GMimePartEncodingType gmt; - LibBalsaMailboxImap* mimap; - ImapMessage *im; - ImapResponse rc; - - libbalsa_lock_mailbox(msg->mailbox); - mimap = LIBBALSA_MAILBOX_IMAP(msg->mailbox); - im = mi_get_imsg(mimap, msg->msgno); - - dt.body = imap_message_get_body_from_section(im, section); - dt.block = g_malloc(dt.body->octets+1); - dt.pos = 0; - II(rc,mimap->handle, - imap_mbox_handle_fetch_body(mimap->handle, msg->msgno, - section, append_str, &dt)); - if(rc != IMR_OK) - g_error("FIXME: error handling here!\n"); - - libbalsa_unlock_mailbox(msg->mailbox); - - prefilt = g_mime_part_new_with_type (dt.body->media_basic_name, - dt.body->media_subtype); - gmt = dt.body->encoding == IMBENC_OTHER ? - GMIME_PART_ENCODING_DEFAULT : dt.body->encoding; - g_mime_part_set_pre_encoded_content ( prefilt, - dt.block, - dt.body->octets, - gmt ); - g_free(dt.block); - - libbalsa_assure_balsa_dir(); - mkdir(pair[0], S_IRUSR|S_IWUSR|S_IXUSR); /* ignore errors */ - /* printf("%s path: %s\n", __FUNCTION__, part_name); */ - fp = fopen(part_name, "wb+"); - if(!fp) { - g_free(section); - g_strfreev(pair); - g_free(part_name); - return NULL; /* something better ? */ - } - if( (dt.body->media_basic == IMBMEDIA_TEXT) && - !g_ascii_strcasecmp( "plain", dt.body->media_subtype ) ) { - GMimeFilter *crlffilter; - - gms = g_mime_stream_file_new (fp); - crlffilter = - g_mime_filter_crlf_new ( GMIME_FILTER_CRLF_DECODE, - GMIME_FILTER_CRLF_MODE_CRLF_ONLY ); - partstream = g_mime_stream_filter_new_with_stream (gms); - g_mime_stream_filter_add (GMIME_STREAM_FILTER(partstream) -, crlffilter); - g_object_unref (gms); - g_object_unref (crlffilter); - } else - partstream = g_mime_stream_file_new (fp); - - g_mime_part_set_encoding (prefilt, GMIME_PART_ENCODING_8BIT ); - g_mime_part_write_to_stream (prefilt, partstream ); - g_mime_stream_flush (partstream); - - g_object_unref (prefilt); - /* aparently the parser doesn't like the stream_filters .. */ - g_object_unref (partstream); - fp = fopen(part_name, "r"); - partstream = g_mime_stream_file_new (fp); - } else - partstream = g_mime_stream_file_new (fp); + gchar **pair, *part_name; + LibBalsaMailboxImap *mimap = LIBBALSA_MAILBOX_IMAP(msg->mailbox); + FILE *fp; + gchar *section; + + if(part->mime_part) + return g_mime_part_get_content(GMIME_PART(part->mime_part), sz); + + /* look for a part cache */ + section = get_section_for(msg, part); + pair = get_cache_name_pair(mimap, "part", IMAP_MESSAGE_UID(msg)); + part_name = g_strconcat(pair[0], "/", pair[1], "-", section, NULL); + fp = fopen(part_name,"rb+"); - { - GMimeParser *parser = - g_mime_parser_new_with_stream (partstream); - part->mime_part = g_mime_parser_construct_part (parser); - g_object_unref (parser); - } - g_object_unref (partstream); - g_free(section); - g_strfreev(pair); - g_free(part_name); - } + if(!fp) { /* no cache element */ + struct part_data dt; + GMimePart *prefilt; + GMimeStream *gms; + GMimePartEncodingType gmt; + LibBalsaMailboxImap* mimap; + ImapMessage *im; + ImapResponse rc; + + libbalsa_lock_mailbox(msg->mailbox); + mimap = LIBBALSA_MAILBOX_IMAP(msg->mailbox); + im = mi_get_imsg(mimap, msg->msgno); + + dt.body = imap_message_get_body_from_section(im, section); + dt.block = g_malloc(dt.body->octets+1); + dt.pos = 0; + if(dt.body->octets>SizeMsgThreshold) + libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, + _("Downloading %ld kB"), + dt.body->octets/1024); + II(rc,mimap->handle, + imap_mbox_handle_fetch_body(mimap->handle, msg->msgno, + section, append_str, &dt)); + if(rc != IMR_OK) + g_error("FIXME: error handling here!\n"); + + libbalsa_unlock_mailbox(msg->mailbox); + + prefilt = g_mime_part_new_with_type (dt.body->media_basic_name, + dt.body->media_subtype); + gmt = dt.body->encoding == IMBENC_OTHER ? + GMIME_PART_ENCODING_DEFAULT : dt.body->encoding; + g_mime_part_set_pre_encoded_content ( prefilt, + dt.block, + dt.body->octets, + gmt ); + g_free(dt.block); + + libbalsa_assure_balsa_dir(); + mkdir(pair[0], S_IRUSR|S_IWUSR|S_IXUSR); /* ignore errors */ + /* printf("%s path: %s\n", __FUNCTION__, part_name); */ + fp = fopen(part_name, "wb+"); + if(!fp) { + g_free(section); + g_strfreev(pair); + g_free(part_name); + return FALSE; /* something better ? */ + } + if( (dt.body->media_basic == IMBMEDIA_TEXT) && + !g_ascii_strcasecmp( "plain", dt.body->media_subtype ) ) { + GMimeFilter *crlffilter; + + gms = g_mime_stream_file_new (fp); + crlffilter = + g_mime_filter_crlf_new ( GMIME_FILTER_CRLF_DECODE, + GMIME_FILTER_CRLF_MODE_CRLF_ONLY ); + partstream = g_mime_stream_filter_new_with_stream (gms); + g_mime_stream_filter_add (GMIME_STREAM_FILTER(partstream) + , crlffilter); + g_object_unref (gms); + g_object_unref (crlffilter); + } else + partstream = g_mime_stream_file_new (fp); + g_mime_part_set_encoding (prefilt, GMIME_PART_ENCODING_8BIT ); + g_mime_part_write_to_stream (prefilt, partstream ); + g_mime_stream_flush (partstream); + + g_object_unref (prefilt); + /* aparently the parser doesn't like the stream_filters .. */ + g_object_unref (partstream); + fp = fopen(part_name, "r"); + } + partstream = g_mime_stream_file_new (fp); + + { + GMimeParser *parser = + g_mime_parser_new_with_stream (partstream); + part->mime_part = g_mime_parser_construct_part (parser); + g_object_unref (parser); + } + g_object_unref (partstream); + g_free(section); + g_strfreev(pair); + g_free(part_name); if (GMIME_IS_PART(part->mime_part)) return g_mime_part_get_content(GMIME_PART(part->mime_part), sz); @@ -2027,6 +2124,10 @@ len = g_mime_stream_tell(outstream); g_mime_stream_reset(outstream); + if(len>(signed)SizeMsgThreshold) + libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, + _("Uploading %ld kB"), + (long)len/1024); handle = libbalsa_mailbox_imap_get_handle(LIBBALSA_MAILBOX_IMAP(mailbox), NULL); rc = imap_mbox_append_stream(handle, @@ -2158,7 +2259,7 @@ LibBalsaMailboxThreadingType thread_type) { LibBalsaMailboxImap *mimap = LIBBALSA_MAILBOX_IMAP(mailbox); - GNode * new_tree; + GNode * new_tree = NULL; guint msgno; ImapSearchKey *filter = lbmi_build_imap_query(mailbox->view_filter, NULL); ImapResponse rc; @@ -2185,9 +2286,12 @@ mailbox->view->sort_type == LB_MAILBOX_SORT_TYPE_ASC, filter)); - new_tree = - g_node_copy(imap_mbox_handle_get_thread_root(mimap->handle)); - } else { + if(rc == IMR_OK) + new_tree = + g_node_copy + (imap_mbox_handle_get_thread_root(mimap->handle)); + } + if(!new_tree) { /* fall back */ new_tree = g_node_new(NULL); for(msgno = 1; msgno <= mimap->messages_info->len; msgno++) g_node_append_data(new_tree, GUINT_TO_POINTER(msgno)); diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_imap.h balsa/libbalsa/mailbox_imap.h --- balsa-ref/libbalsa/mailbox_imap.h 2004-08-06 17:02:26.000000000 +0200 +++ balsa/libbalsa/mailbox_imap.h 2004-08-26 18:15:30.000000000 +0200 @@ -43,7 +43,7 @@ #define POINTER_TO_UID(p) GPOINTER_TO_UINT(p) #define UID_TO_POINTER(p) GUINT_TO_POINTER(p) -GObject *libbalsa_mailbox_imap_new(void); +LibBalsaMailboxImap *libbalsa_mailbox_imap_new(void); void libbalsa_mailbox_imap_update_url(LibBalsaMailboxImap* mailbox); void libbalsa_mailbox_imap_set_path(LibBalsaMailboxImap * mailbox, diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_local.c balsa/libbalsa/mailbox_local.c --- balsa-ref/libbalsa/mailbox_local.c 2004-08-05 16:01:32.000000000 +0200 +++ balsa/libbalsa/mailbox_local.c 2004-08-29 23:25:14.000000000 +0200 @@ -74,10 +74,6 @@ LibBalsaFetchFlag flags); static void libbalsa_mailbox_local_fetch_headers(LibBalsaMailbox *mailbox, LibBalsaMessage *message); -static void libbalsa_mailbox_local_release_message(LibBalsaMailbox * - mailbox, - LibBalsaMessage * - message); static const gchar* libbalsa_mailbox_local_get_msg_part(LibBalsaMessage *msg, LibBalsaMessageBody *, @@ -151,8 +147,6 @@ libbalsa_mailbox_local_fetch_structure; libbalsa_mailbox_class->fetch_headers = libbalsa_mailbox_local_fetch_headers; - libbalsa_mailbox_class->release_message = - libbalsa_mailbox_local_release_message; libbalsa_mailbox_class->get_message_part = libbalsa_mailbox_local_get_msg_part; klass->load_message = NULL; @@ -550,8 +544,8 @@ static void libbalsa_mailbox_local_fetch_structure(LibBalsaMailbox *mailbox, - LibBalsaMessage *message, - LibBalsaFetchFlag flags) + LibBalsaMessage *message, + LibBalsaFetchFlag flags) { GMimeMessage *mime_message = message->mime_msg; g_assert(mime_message != NULL); @@ -572,16 +566,6 @@ } static void -libbalsa_mailbox_local_release_message(LibBalsaMailbox * mailbox, - LibBalsaMessage * message) -{ - if (message->mime_msg) { - g_object_unref(message->mime_msg); - message->mime_msg = NULL; - } -} - -static void libbalsa_mailbox_local_fetch_headers(LibBalsaMailbox * mailbox, LibBalsaMessage * message) { @@ -593,7 +577,7 @@ else { libbalsa_mailbox_fetch_message_structure(mailbox, message, LB_FETCH_RFC822_HEADERS); - libbalsa_mailbox_local_release_message(mailbox, message); + libbalsa_mailbox_release_message(mailbox, message); } } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_maildir.c balsa/libbalsa/mailbox_maildir.c --- balsa-ref/libbalsa/mailbox_maildir.c 2004-08-05 16:01:32.000000000 +0200 +++ balsa/libbalsa/mailbox_maildir.c 2004-08-21 23:20:19.000000000 +0200 @@ -525,17 +525,26 @@ if (stat(mdir->tmpdir, &st) == -1) return; - if (st.st_mtime > mdir->mtime) + if (mdir->mtime == 0) + /* First check--just cache the mtime. */ + mdir->mtime = st.st_mtime; + else if (st.st_mtime > mdir->mtime) modified = 1; if (stat(mdir->curdir, &st_cur) == -1) return; - if (st_cur.st_mtime > mdir->mtime_cur) + if (mdir->mtime_cur == 0) + /* First check--just cache the mtime. */ + mdir->mtime_cur = st_cur.st_mtime; + else if (st_cur.st_mtime > mdir->mtime_cur) modified = 1; if (stat(mdir->newdir, &st_new) == -1) return; - if (st_new.st_mtime > mdir->mtime_new) + if (mdir->mtime_new == 0) + /* First check--just cache the mtime. */ + mdir->mtime_new = st_new.st_mtime; + else if (st_new.st_mtime > mdir->mtime_new) modified = 1; if (!modified) @@ -842,9 +851,11 @@ char *tmp; int fd; GMimeStream *out_stream; + GMimeStream *tmp_stream; + GMimeStream *in_stream; + GMimeFilter *crlffilter; char *new_filename; struct message_info *msg_info; - GMimeStream *in_stream; gint retval; /* open tempfile */ @@ -853,24 +864,34 @@ if (fd == -1) return -1; out_stream = g_mime_stream_fs_new(fd); - { - GMimeStream *tmp = libbalsa_mailbox_get_message_stream( message->mailbox, message ); - GMimeFilter *crlffilter = - g_mime_filter_crlf_new ( GMIME_FILTER_CRLF_DECODE, - GMIME_FILTER_CRLF_MODE_CRLF_ONLY ); - in_stream = g_mime_stream_filter_new_with_stream (tmp); - g_mime_stream_filter_add ( GMIME_STREAM_FILTER (in_stream), crlffilter ); - g_object_unref (crlffilter); - g_mime_stream_unref (tmp); - } + + tmp_stream = + libbalsa_mailbox_get_message_stream(message->mailbox, message); + if (!tmp_stream) { + g_object_unref(out_stream); + unlink(tmp); + g_free(tmp); + return -1; + } + in_stream = g_mime_stream_filter_new_with_stream(tmp_stream); + g_object_unref(tmp_stream); + + crlffilter = + g_mime_filter_crlf_new(GMIME_FILTER_CRLF_DECODE, + GMIME_FILTER_CRLF_MODE_CRLF_ONLY); + g_mime_stream_filter_add(GMIME_STREAM_FILTER(in_stream), crlffilter); + g_object_unref(crlffilter); + if (g_mime_stream_write_to_stream( in_stream, out_stream) == -1) { - g_mime_stream_unref(out_stream); + g_object_unref(in_stream); + g_object_unref(out_stream); unlink (tmp); g_free(tmp); return -1; } - g_mime_stream_unref(out_stream); + g_object_unref(in_stream); + g_object_unref(out_stream); new_filename = strrchr(tmp, '/'); if (new_filename) diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_mbox.c balsa/libbalsa/mailbox_mbox.c --- balsa-ref/libbalsa/mailbox_mbox.c 2004-08-03 17:47:14.000000000 +0200 +++ balsa/libbalsa/mailbox_mbox.c 2004-09-15 22:30:10.927012947 +0200 @@ -303,7 +303,6 @@ GMimeParser *gmime_parser; struct message_info msg_info; struct message_info * msg_info_p = &msg_info; - GMimeMessage *mime_message; unsigned msgno = 0; gmime_parser = g_mime_parser_new_with_stream(mbox->gmime_stream); @@ -314,31 +313,38 @@ (GMimeParserHeaderRegexFunc) lbm_mbox_header_cb, &msg_info_p); + msg_info.message = NULL; while (!g_mime_stream_eos(mbox->gmime_stream)) { - msg_info.status = -1; - msg_info.x_status = -1; - mime_message = g_mime_parser_construct_message(gmime_parser); - msg_info.start = g_mime_parser_get_from_offset(gmime_parser); - msg_info.end = g_mime_parser_tell(gmime_parser); - if (msg_info.end > msg_info.start) { - LibBalsaMessage *msg; - msg_info.from = g_mime_parser_get_from(gmime_parser); - msg = lbm_mbox_message_new(mime_message, &msg_info); - msg_info.flags = msg_info.orig_flags; - if (msg) { - LibBalsaMailboxIndexEntry *entry; - msg->flags = msg_info.orig_flags; - msg->length = msg_info.end - msg_info.start; - msg->mailbox = LIBBALSA_MAILBOX(mbox); - msg->msgno = ++msgno; - entry = libbalsa_mailbox_index_entry_new_from_msg(msg); - g_object_unref(msg); - g_ptr_array_add(LIBBALSA_MAILBOX(mbox)->mindex, entry); - msg_info.message = NULL; - g_array_append_val(mbox->messages_info, msg_info); - } + GMimeMessage *mime_message; + LibBalsaMessage *msg; + + msg_info.status = msg_info.x_status = -1; + mime_message = g_mime_parser_construct_message(gmime_parser); + msg_info.start = g_mime_parser_get_from_offset(gmime_parser); + msg_info.end = g_mime_parser_tell(gmime_parser); + if (msg_info.end <= msg_info.start + || !(msg_info.from = g_mime_parser_get_from(gmime_parser))) { + g_object_unref(mime_message); + continue; } - g_mime_object_unref(GMIME_OBJECT(mime_message)); + + msg = lbm_mbox_message_new(mime_message, &msg_info); + g_object_unref(mime_message); + if (!msg) { + g_free(msg_info.from); + continue; + } + + msg_info.flags = msg_info.orig_flags; + g_array_append_val(mbox->messages_info, msg_info); + + msg->flags = msg_info.orig_flags; + msg->length = msg_info.end - msg_info.start; + msg->mailbox = LIBBALSA_MAILBOX(mbox); + msg->msgno = ++msgno; + g_ptr_array_add(LIBBALSA_MAILBOX(mbox)->mindex, + libbalsa_mailbox_index_entry_new_from_msg(msg)); + g_object_unref(msg); } g_object_unref(G_OBJECT(gmime_parser)); @@ -541,6 +547,12 @@ return; } + if (mbox->mtime == 0) { + /* First check--just cache the mtime and size. */ + mbox->mtime = st.st_mtime; + mbox->size = st.st_size; + return; + } if (st.st_mtime == mbox->mtime && st.st_size == mbox->size) return; @@ -587,6 +599,7 @@ g_array_remove_index(mbox->messages_info, msgno - 1); } g_mime_stream_reset(mbox->gmime_stream); + mailbox->unread_messages = 0; } last_msgno = mbox->messages_info->len; parse_mailbox(mbox); @@ -1115,6 +1128,8 @@ (msg_info->flags & LIBBALSA_MESSAGE_FLAG_DELETED)) { free_message_info(msg_info); g_array_remove_index(mbox->messages_info, j); + libbalsa_mailbox_index_entry_free(g_ptr_array_index + (mailbox->mindex, j)); g_ptr_array_remove_index(mailbox->mindex, j); } else j++; @@ -1453,6 +1468,7 @@ GMimeStream *orig; GMimeStream *dest; gint retval = 1; + off_t orig_length; ctime_r(&(message->headers->date), date_string); @@ -1481,7 +1497,7 @@ return -1; } - lseek (fd, 0, SEEK_END); + orig_length = lseek (fd, 0, SEEK_END); dest = g_mime_stream_fs_new (fd); if (!dest) { libbalsa_information(LIBBALSA_INFORMATION_WARNING, @@ -1510,8 +1526,7 @@ if (g_mime_stream_write_string(dest, from) < (gint) strlen(from) || g_mime_stream_write_to_stream (orig, dest) < 0) { libbalsa_information ( LIBBALSA_INFORMATION_ERROR, - _("Error copying message to mailbox %s!\n" - "Mailbox might have been corrupted!"), + _("Error copying message to mailbox %s!"), mailbox->name ); retval = -1; } @@ -1520,6 +1535,8 @@ retval = lbm_mbox_newline(dest); g_mime_stream_unref(orig); + if(retval<0) + truncate(path, orig_length); mbox_unlock (mailbox, dest); g_mime_stream_unref(dest); g_free(from); diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_mh.c balsa/libbalsa/mailbox_mh.c --- balsa-ref/libbalsa/mailbox_mh.c 2004-08-03 17:47:14.000000000 +0200 +++ balsa/libbalsa/mailbox_mh.c 2004-08-21 23:20:18.000000000 +0200 @@ -603,10 +603,16 @@ modified = 1; } - if (st.st_mtime > mh->mtime) + if (mh->mtime == 0) + /* First check--just cache the mtime. */ + mh->mtime = st.st_mtime; + else if (st.st_mtime > mh->mtime) modified = 1; - if (st_sequences.st_mtime > mh->mtime_sequences) + if (mh->mtime_sequences == 0) + /* First check--just cache the mtime. */ + mh->mtime_sequences = st_sequences.st_mtime; + else if (st_sequences.st_mtime > mh->mtime_sequences) modified = 1; if (!modified) diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_pop3.c balsa/libbalsa/mailbox_pop3.c --- balsa-ref/libbalsa/mailbox_pop3.c 2004-07-31 21:16:04.000000000 +0200 +++ balsa/libbalsa/mailbox_pop3.c 2004-08-26 18:15:30.000000000 +0200 @@ -149,14 +149,14 @@ G_OBJECT_CLASS(parent_class)->finalize(object); } -GObject * +LibBalsaMailboxPop3* libbalsa_mailbox_pop3_new(void) { - LibBalsaMailbox *mailbox; + LibBalsaMailboxPop3 *mailbox; mailbox = g_object_new(LIBBALSA_TYPE_MAILBOX_POP3, NULL); - return G_OBJECT(mailbox); + return mailbox; } @@ -355,7 +355,7 @@ case POP_REQ_DATA: {unsigned len = va_arg(alist, unsigned); char *buf = va_arg(alist, char*); - if( (batch_cnt++ & 0x1f) && + if( (batch_cnt++ & 0x04) && last_update != (current_time = time(NULL))) { snprintf(threadbuf, sizeof(threadbuf), _("Received %ld kB of %ld"), diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/mailbox_pop3.h balsa/libbalsa/mailbox_pop3.h --- balsa-ref/libbalsa/mailbox_pop3.h 2004-07-27 11:11:59.000000000 +0200 +++ balsa/libbalsa/mailbox_pop3.h 2004-08-26 18:15:30.000000000 +0200 @@ -60,7 +60,7 @@ void (*config_changed) (LibBalsaMailboxPop3* mailbox); }; -GObject *libbalsa_mailbox_pop3_new(void); +LibBalsaMailboxPop3 *libbalsa_mailbox_pop3_new(void); void libbalsa_mailbox_pop3_set_inbox(LibBalsaMailbox *mailbox, LibBalsaMailbox *inbox); void libbalsa_mailbox_pop3_set_msg_size_limit(LibBalsaMailboxPop3 *mailbox, diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/Makefile.am balsa/libbalsa/Makefile.am --- balsa-ref/libbalsa/Makefile.am 2004-08-03 17:47:13.000000000 +0200 +++ balsa/libbalsa/Makefile.am 2004-08-21 23:20:24.000000000 +0200 @@ -29,6 +29,8 @@ abook-completion.h \ address-book-extern.c \ address-book-extern.h \ + address-book-gpe.c \ + address-book-gpe.h \ address-book-ldap.c \ address-book-ldap.h \ address-book-ldif.c \ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/message.c balsa/libbalsa/message.c --- balsa-ref/libbalsa/message.c 2004-08-08 14:55:33.000000000 +0200 +++ balsa/libbalsa/message.c 2004-08-21 23:20:18.000000000 +0200 @@ -1239,8 +1239,7 @@ if (all) message->headers->user_hdrs = g_list_append(message->headers->user_hdrs, - libbalsa_create_hdr_pair(g_strdup(name), - g_strdup(value))); + libbalsa_create_hdr_pair(name, g_strdup(value))); return TRUE; } @@ -1315,8 +1314,7 @@ } line->data[line->len-1]='\0'; /* terminate line by overwriting '\n' */ if (!lb_message_set_headers_from_string(message, line->data, FALSE)) { - ret = FALSE; - break; + /* Ignore error return caused by malformed header. */ } if (lookahead == '\n') {/* end of headers */ ret = TRUE; diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/message.h balsa/libbalsa/message.h --- balsa-ref/libbalsa/message.h 2004-08-02 18:17:54.000000000 +0200 +++ balsa/libbalsa/message.h 2004-08-31 22:47:21.000000000 +0200 @@ -53,7 +53,6 @@ typedef struct _LibBalsaMessageClass LibBalsaMessageClass; typedef enum _LibBalsaMessageFlag LibBalsaMessageFlag; -typedef enum _LibBalsaMsgCreateResult LibBalsaMsgCreateResult; enum _LibBalsaMessageFlag { LIBBALSA_MESSAGE_FLAG_NEW = 1 << 0, @@ -63,17 +62,6 @@ LIBBALSA_MESSAGE_FLAG_RECENT = 1 << 4 }; -enum _LibBalsaMsgCreateResult { - LIBBALSA_MESSAGE_CREATE_OK, -#ifdef HAVE_GPGME - LIBBALSA_MESSAGE_SIGN_ERROR, - LIBBALSA_MESSAGE_ENCRYPT_ERROR, -#endif - LIBBALSA_MESSAGE_CREATE_ERROR, - LIBBALSA_MESSAGE_QUEUE_ERROR, - LIBBALSA_MESSAGE_SAVE_ERROR, - LIBBALSA_MESSAGE_SEND_ERROR -}; typedef enum _LibBalsaMessageStatus LibBalsaMessageStatus; enum _LibBalsaMessageStatus { @@ -306,24 +294,6 @@ gboolean fetch_all_headers); void libbalsa_message_body_unref(LibBalsaMessage * message); -LibBalsaMsgCreateResult libbalsa_message_queue(LibBalsaMessage* message, - LibBalsaMailbox* outbox, LibBalsaMailbox* fccbox, - gint encoding, gboolean flow); -#if ENABLE_ESMTP -LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage* message, - LibBalsaMailbox* outbox, - LibBalsaMailbox* fccbox, - gint encoding, gchar* smtp_server, - auth_context_t smtp_authctx, - gint tls_mode, gboolean flow, - gboolean debug); -#else -LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage* message, - LibBalsaMailbox* outbox, - LibBalsaMailbox* fccbox, - gint encoding, gboolean flow, - gboolean debug); -#endif gboolean libbalsa_message_postpone(LibBalsaMessage * message, LibBalsaMailbox * draftbox, LibBalsaMessage * reply_message, diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/misc.c balsa/libbalsa/misc.c --- balsa-ref/libbalsa/misc.c 2004-07-06 00:24:02.000000000 +0200 +++ balsa/libbalsa/misc.c 2004-08-31 22:47:21.000000000 +0200 @@ -484,6 +484,8 @@ if (*str) str++; + if(len>0 && p[len-1] == '\r') + len--; /* take care of '\r\n' line endings */ flowed = (len > 0 && p[len - 1] == ' ' && !sig_sep); if (flowed && delsp) /* Don't include the last space. */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/rfc3156.c balsa/libbalsa/rfc3156.c --- balsa-ref/libbalsa/rfc3156.c 2004-08-07 19:39:48.000000000 +0200 +++ balsa/libbalsa/rfc3156.c 2004-08-21 23:20:24.000000000 +0200 @@ -1098,6 +1098,7 @@ if (WEXITSTATUS(status) > 0) dialog = gtk_message_dialog_new(spawned_gpg->parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _ @@ -1106,6 +1107,7 @@ else dialog = gtk_message_dialog_new(spawned_gpg->parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, _("Running gpg successful:\n%s"), @@ -1249,6 +1251,7 @@ /* FIXME: create dialog according to the Gnome HIG */ dialog = gtk_dialog_new_with_buttons(_("Select key"), parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, @@ -1359,6 +1362,7 @@ /* FIXME: create dialog according to the Gnome HIG */ dialog = gtk_dialog_new_with_buttons(title, parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/send.c balsa/libbalsa/send.c --- balsa-ref/libbalsa/send.c 2004-07-31 21:17:12.000000000 +0200 +++ balsa/libbalsa/send.c 2004-09-11 00:20:01.000000000 +0200 @@ -54,13 +54,12 @@ typedef struct _MessageQueueItem MessageQueueItem; struct _MessageQueueItem { + char tempfile[_POSIX_PATH_MAX]; LibBalsaMessage *orig; GMimeStream *stream; + LibBalsaFccboxFinder finder; #if !ENABLE_ESMTP MessageQueueItem *next_message; -#endif - char tempfile[_POSIX_PATH_MAX]; -#if !ENABLE_ESMTP enum {MQI_WAITING, MQI_FAILED,MQI_SENT} status; #else long message_size; @@ -80,6 +79,8 @@ needed to transfer the message to the SMTP server. This structure is opaque to the application. */ smtp_session_t session; +#else + LibBalsaFccboxFinder finder; #endif gboolean debug; }; @@ -122,11 +123,12 @@ static MessageQueueItem * -msg_queue_item_new(void) +msg_queue_item_new(LibBalsaFccboxFinder finder) { MessageQueueItem *mqi; mqi = g_new(MessageQueueItem, 1); + mqi->finder = finder; #if !ENABLE_ESMTP mqi->next_message = NULL; mqi->status = MQI_WAITING; @@ -164,12 +166,14 @@ } #else static SendMessageInfo * -send_message_info_new(LibBalsaMailbox* outbox, gboolean debug) +send_message_info_new(LibBalsaMailbox* outbox, + LibBalsaFccboxFinder finder, gboolean debug) { SendMessageInfo *smi; smi=g_new(SendMessageInfo,1); smi->outbox = outbox; + smi->finder = finder; smi->debug = debug; return smi; @@ -198,7 +202,7 @@ gint encoding, gboolean flow); static LibBalsaMsgCreateResult libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage * message, - MessageQueueItem *mqi); + MessageQueueItem *mqi); #ifdef BALSA_USE_THREADS void balsa_send_thread(MessageQueueItem * first_message); @@ -248,7 +252,7 @@ send_dialog_bar = gtk_progress_bar_new(); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(send_dialog)->vbox), send_dialog_bar, FALSE, FALSE, 0); - + gtk_window_set_default_size(GTK_WINDOW(send_dialog), 250, 100); gtk_widget_show_all(send_dialog); g_signal_connect(G_OBJECT(send_dialog), "response", G_CALLBACK(send_dialog_response_cb), NULL); @@ -367,27 +371,16 @@ g_return_val_if_fail(message, LIBBALSA_MESSAGE_CREATE_ERROR); - if ((result = libbalsa_create_msg(message, encoding, flow)) == - LIBBALSA_MESSAGE_CREATE_OK) { - if(libbalsa_mailbox_copy_message( message, outbox ) < 0) - return LIBBALSA_MESSAGE_QUEUE_ERROR; - - if (fccbox) { - if (LIBBALSA_IS_MAILBOX_LOCAL(fccbox) || - LIBBALSA_IS_MAILBOX_IMAP(fccbox)) { - if(libbalsa_mailbox_copy_message(message, fccbox)<0) - return LIBBALSA_MESSAGE_SAVE_ERROR; - /* fcc perhaps does not know about this message yet! - * later check will discover it and thread. - libbalsa_mailbox_set_threading(fccbox, - fccbox->view-> - threading_type); - */ - } - } - } + if ((result = libbalsa_create_msg(message, encoding, flow)) != + LIBBALSA_MESSAGE_CREATE_OK) + return result; - return result; + if (fccbox) + g_mime_message_set_header(message->mime_msg, "X-Balsa-Fcc", + fccbox->url); + if(libbalsa_mailbox_copy_message( message, outbox ) < 0) + return LIBBALSA_MESSAGE_QUEUE_ERROR; + return LIBBALSA_MESSAGE_CREATE_OK; } /* libbalsa_message_send: @@ -397,7 +390,8 @@ #if ENABLE_ESMTP LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage * message, LibBalsaMailbox * outbox, - LibBalsaMailbox * fccbox, gint encoding, + LibBalsaMailbox *fccbox, gint encoding, + LibBalsaFccboxFinder finder, gchar * smtp_server, auth_context_t smtp_authctx, gint tls_mode, gboolean flow, gboolean debug) { @@ -407,7 +401,7 @@ result = libbalsa_message_queue(message, outbox, fccbox, encoding, flow); if (result == LIBBALSA_MESSAGE_CREATE_OK) - if (!libbalsa_process_queue(outbox, smtp_server, + if (!libbalsa_process_queue(outbox, finder, smtp_server, smtp_authctx, tls_mode, debug)) return LIBBALSA_MESSAGE_SEND_ERROR; @@ -416,16 +410,16 @@ #else LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage* message, LibBalsaMailbox* outbox, - LibBalsaMailbox* fccbox, gint encoding, - gboolean flow, gboolean debug) + LibBalsaMailbox* fccbox, LibBalsaFccboxFinder finder, + gint encoding, gboolean flow, gboolean debug) { LibBalsaMsgCreateResult result = LIBBALSA_MESSAGE_CREATE_OK; if (message != NULL) - result = libbalsa_message_queue(message, outbox, fccbox, encoding, - flow); + result = libbalsa_message_queue(message, outbox, fccbox, + encoding, flow); if (result == LIBBALSA_MESSAGE_CREATE_OK) - if (!libbalsa_process_queue(outbox, debug)) + if (!libbalsa_process_queue(outbox, finder, debug)) return LIBBALSA_MESSAGE_SEND_ERROR; return result; @@ -496,7 +490,8 @@ sendmail version so don't get fooled by similar variable names. */ gboolean -libbalsa_process_queue(LibBalsaMailbox * outbox, gchar * smtp_server, +libbalsa_process_queue(LibBalsaMailbox * outbox, LibBalsaFccboxFinder finder, + gchar * smtp_server, auth_context_t smtp_authctx, gint tls_mode, gboolean debug) { @@ -509,7 +504,7 @@ const gchar *phrase, *mailbox, *subject; long estimate; guint msgno; - + gchar *host_with_port; send_lock(); if (!libbalsa_mailbox_open(outbox, NULL)) { @@ -529,9 +524,11 @@ messages to the session. */ /* FIXME - check for failure returns in the smtp_xxx() calls */ - + host_with_port = strchr(smtp_server, ':') + ? g_strdup(smtp_server) : g_strconcat(smtp_server, ":smtp", NULL); session = smtp_create_session (); - smtp_set_server (session, smtp_server); + smtp_set_server (session, host_with_port); + g_free(host_with_port); /* Tell libESMTP how to use the SMTP STARTTLS extension. */ smtp_starttls_enable (session, tls_mode); @@ -558,7 +555,7 @@ libbalsa_message_body_ref(msg, TRUE, TRUE); /* FIXME: do we need * all headers? */ - new_message = msg_queue_item_new(); + new_message = msg_queue_item_new(finder); created = libbalsa_fill_msg_queue_item_from_queu(msg, new_message); libbalsa_message_body_unref(msg); @@ -624,7 +621,7 @@ /* Add this after the Bcc: copy. */ message = smtp_add_message (session); if (bcc_message) - smtp_set_header_option (message, "Bcc", Hdr_PROHIBIT); + smtp_set_header_option (message, "Bcc", Hdr_PROHIBIT, 1); smtp_message_set_application_data (message, new_message); smtp_set_messagecb (message, libbalsa_message_cb, new_message); @@ -697,8 +694,10 @@ add_recipients(bcc_message, NULL, bcc_recip, "Cc"); /* Prohibit status headers. */ - smtp_set_header_option(message, "Status", Hdr_PROHIBIT); - smtp_set_header_option(message, "X-Status", Hdr_PROHIBIT); + smtp_set_header_option(message, "Status", Hdr_PROHIBIT, 1); + smtp_set_header_option(message, "X-Status", Hdr_PROHIBIT, 1); + /* ... and FCC header. */ + smtp_set_header_option(message, "X-Balsa-Fcc", Hdr_PROHIBIT, 1); /* Estimate the size of the message. This need not be exact @@ -784,22 +783,31 @@ if (mqi != NULL) mqi->refcount--; + messages = g_list_prepend(NULL, mqi->orig); + libbalsa_messages_change_flag(messages, LIBBALSA_MESSAGE_FLAG_FLAGGED, + FALSE); + g_list_free(messages); status = smtp_message_transfer_status (message); if (status->code / 100 == 2) { - if (mqi != NULL && mqi->orig != NULL && mqi->refcount <= 0) { - if (mqi->orig->mailbox) { - messages = g_list_prepend(NULL, mqi->orig); - libbalsa_messages_change_flag(messages, - LIBBALSA_MESSAGE_FLAG_DELETED, - TRUE); - g_list_free(messages); + if (mqi != NULL && mqi->orig != NULL && mqi->refcount <= 0 && + mqi->orig->mailbox) { + gboolean remove = TRUE; + GList* fcclist = + libbalsa_message_find_user_hdr(mqi->orig, "X-Balsa-Fcc"); + const gchar **fccurl = fcclist ? fcclist->data : NULL; + + if (mqi->orig->mailbox && fccurl) { + LibBalsaMailbox *fccbox = mqi->finder(fccurl[1]); + remove = libbalsa_mailbox_copy_message(mqi->orig, fccbox)>=0; + } + if(remove) { + messages = g_list_prepend(NULL, mqi->orig); + libbalsa_messages_change_flag + (messages, LIBBALSA_MESSAGE_FLAG_DELETED, TRUE); + g_list_free(messages); } } } else { - messages = g_list_prepend(NULL, mqi->orig); - libbalsa_messages_change_flag(messages, LIBBALSA_MESSAGE_FLAG_FLAGGED, - FALSE); - g_list_free(messages); /* XXX - Show the poor user the status codes and message. */ if(*(gboolean*)be_verbose) { int cnt = 0; @@ -854,11 +862,11 @@ mailbox = va_arg (ap, const char *); message = va_arg (ap, smtp_message_t); status = smtp_reverse_path_status (message); - snprintf (buf, sizeof buf, "%s %d <%s>", _("From:"), status->code, mailbox); + snprintf (buf, sizeof buf, "%s <%s>", _("From:"), mailbox); MSGSENDTHREAD(threadmsg, MSGSENDTHREADPROGRESS, buf, NULL, NULL, 0); - snprintf (buf, sizeof buf, "%s %s: %d %s", _("From"), - mailbox, status->code, status->text); + snprintf (buf, sizeof buf, "%s %s: %s", _("From"), + mailbox, status->text); g_strchomp(buf); libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, buf); break; @@ -866,11 +874,11 @@ mailbox = va_arg (ap, const char *); recipient = va_arg (ap, smtp_recipient_t); status = smtp_recipient_status (recipient); - snprintf (buf, sizeof buf, "%s %d <%s>", _("To:"), status->code, mailbox); + snprintf (buf, sizeof buf, "%s <%s>", _("To:"), mailbox); MSGSENDTHREAD(threadmsg, MSGSENDTHREADPROGRESS, buf, NULL, NULL, 0); - snprintf (buf, sizeof buf, "%s %s: %d %s", _("To"), - mailbox, status->code, status->text); + snprintf (buf, sizeof buf, "%s %s: %s", _("To"), + mailbox, status->text); g_strchomp(buf); libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, buf); break; @@ -894,7 +902,7 @@ case SMTP_EV_MESSAGESENT: message = va_arg (ap, smtp_message_t); status = smtp_message_transfer_status (message); - snprintf (buf, sizeof buf, "%d %s", status->code, status->text); + snprintf (buf, sizeof buf, "%s", status->text); g_strchomp(buf); MSGSENDTHREAD(threadmsg, MSGSENDTHREADPROGRESS, buf, NULL, NULL, 0); libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, buf); @@ -959,7 +967,8 @@ handler does that. */ gboolean -libbalsa_process_queue(LibBalsaMailbox* outbox, gboolean debug) +libbalsa_process_queue(LibBalsaMailbox* outbox, LibBalsaFccboxFinder finder, + gboolean debug) { MessageQueueItem *mqi = NULL, *new_message; SendMessageInfo *send_message_info; @@ -997,7 +1006,7 @@ libbalsa_message_body_ref(msg, TRUE, TRUE); /* FIXME: do we need * all headers? */ - new_message = msg_queue_item_new(); + new_message = msg_queue_item_new(finder); created = libbalsa_fill_msg_queue_item_from_queu(msg, new_message); libbalsa_message_body_unref(msg); @@ -1018,7 +1027,7 @@ } } - send_message_info=send_message_info_new(outbox, debug); + send_message_info=send_message_info_new(outbox, finder, debug); #ifdef BALSA_USE_THREADS @@ -1039,14 +1048,25 @@ } static void -handle_successful_send(MessageQueueItem *mqi) +handle_successful_send(MessageQueueItem *mqi, LibBalsaFccboxFinder finder) { if (mqi->orig->mailbox) { + gboolean remove = TRUE; GList * messages = g_list_prepend(NULL, mqi->orig); - - libbalsa_messages_change_flag(messages, - LIBBALSA_MESSAGE_FLAG_DELETED, - TRUE); + libbalsa_messages_change_flag(messages, LIBBALSA_MESSAGE_FLAG_FLAGGED, + FALSE); + GList* fcclist = + libbalsa_message_find_user_hdr(mqi->orig, "X-Balsa-Fcc"); + const gchar **fccurl = fcclist ? fcclist->data : NULL; + + if (mqi->orig->mailbox && fccurl) { + LibBalsaMailbox *fccbox = mqi->finder(fccurl[1]); + remove = libbalsa_mailbox_copy_message(mqi->orig, fccbox)>=0; + } + if(remove) + libbalsa_messages_change_flag(messages, + LIBBALSA_MESSAGE_FLAG_DELETED, + TRUE); g_list_free(messages); } mqi->status = MQI_SENT; @@ -1126,13 +1146,21 @@ libbalsa_information (LIBBALSA_INFORMATION_ERROR, _("SMTP server refused connection.\n" - "Balsa by default uses submission service (587).\n" - "If you want to submit mail using relay service (25)," - "specify it explicitly via: \"host:smtp\".\n" - "Message is left in outbox.")); + "Check your internet connection.")); + case -EHOSTUNREACH: + libbalsa_information + (LIBBALSA_INFORMATION_ERROR, + _("SMTP server cannot be reached.\n" + "Check your internet connection.")); break; case SMTP_ERR_NOTHING_TO_DO: /* silence this one? */ break; + case SMTP_ERR_EAI_AGAIN: + /* this is really problem with DNS but it is nowadays + caused by general connection problems. */ + libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, + _("Message left in Outbox (try again later)")); + break; default: libbalsa_information (LIBBALSA_INFORMATION_ERROR, _("SMTP server problem (%d): %s\n" @@ -1154,7 +1182,7 @@ */ smtp_enumerate_messages (info->session, handle_successful_send, &session_started); - + libbalsa_mailbox_sync_storage(info->outbox, TRUE); libbalsa_mailbox_close(info->outbox, TRUE); /* * gdk_flush(); @@ -1264,13 +1292,14 @@ while (mqi != NULL) { if (mqi->status == MQI_SENT) - handle_successful_send(mqi); + handle_successful_send(mqi, info->finder); next_message = mqi->next_message; msg_queue_item_destroy(mqi); mqi = next_message; } gdk_threads_enter(); + libbalsa_mailbox_sync_storage(info->outbox, TRUE); libbalsa_mailbox_close(info->outbox, TRUE); gdk_flush(); gdk_threads_leave(); @@ -1713,7 +1742,7 @@ static LibBalsaMsgCreateResult libbalsa_fill_msg_queue_item_from_queu(LibBalsaMessage * message, - MessageQueueItem *mqi) + MessageQueueItem *mqi) { mqi->orig = message; g_object_ref(mqi->orig); @@ -1756,7 +1785,7 @@ message->headers->from->address_list->data); if (message->headers->bcc_list) libbalsa_information(LIBBALSA_INFORMATION_WARNING, - _("This message will not be encrpyted for the BCC: recipient(s).")); + _("This message will not be encrypted for the BCC: recipient(s).")); if (mode & LIBBALSA_PROTECT_SIGN) result = @@ -1832,7 +1861,7 @@ message->headers->from->address_list->data); if (message->headers->bcc_list) libbalsa_information(LIBBALSA_INFORMATION_WARNING, - _("This message will not be encrpyted for the BCC: recipient(s).")); + _("This message will not be encrypted for the BCC: recipient(s).")); if (message->gpg_mode & LIBBALSA_PROTECT_SIGN) success = diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/send.h balsa/libbalsa/send.h --- balsa-ref/libbalsa/send.h 2003-10-13 11:46:13.000000000 +0200 +++ balsa/libbalsa/send.h 2004-08-31 22:47:21.000000000 +0200 @@ -24,16 +24,52 @@ #ifndef __SEND_H__ #define __SEND_H__ +typedef LibBalsaMailbox* (*LibBalsaFccboxFinder)(const gchar *url); +typedef enum _LibBalsaMsgCreateResult LibBalsaMsgCreateResult; +enum _LibBalsaMsgCreateResult { + LIBBALSA_MESSAGE_CREATE_OK, +#ifdef HAVE_GPGME + LIBBALSA_MESSAGE_SIGN_ERROR, + LIBBALSA_MESSAGE_ENCRYPT_ERROR, +#endif + LIBBALSA_MESSAGE_CREATE_ERROR, + LIBBALSA_MESSAGE_QUEUE_ERROR, + LIBBALSA_MESSAGE_SAVE_ERROR, + LIBBALSA_MESSAGE_SEND_ERROR +}; + +LibBalsaMsgCreateResult libbalsa_message_queue(LibBalsaMessage* message, + LibBalsaMailbox* outbox, + LibBalsaMailbox* fccbox, + gint encoding, gboolean flow); #if ENABLE_ESMTP #include +LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage* message, + LibBalsaMailbox* outbox, + LibBalsaMailbox* fccbox, + gint encoding, + LibBalsaFccboxFinder finder, + gchar* smtp_server, + auth_context_t smtp_authctx, + gint tls_mode, gboolean flow, + gboolean debug); gboolean libbalsa_process_queue(LibBalsaMailbox * outbox, + LibBalsaFccboxFinder finder, gchar * smtp_server, auth_context_t smtp_authctx, gint tls_mode, gboolean debug); #else -gboolean libbalsa_process_queue(LibBalsaMailbox* outbox, gboolean debug); +LibBalsaMsgCreateResult libbalsa_message_send(LibBalsaMessage* message, + LibBalsaMailbox* outbox, + LibBalsaMailbox* fccbox, + LibBalsaFccboxFinder finder, + gint encoding, gboolean flow, + gboolean debug); +gboolean libbalsa_process_queue(LibBalsaMailbox* outbox, + LibBalsaFccboxFinder finder, + gboolean debug); #endif diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/server.c balsa/libbalsa/server.c --- balsa-ref/libbalsa/server.c 2004-08-04 14:06:14.000000000 +0200 +++ balsa/libbalsa/server.c 2004-08-27 19:15:24.000000000 +0200 @@ -417,3 +417,13 @@ } va_end(alist); } + +void +libbalsa_server_connect_signals(LibBalsaServer * server, GCallback cb, + gpointer cb_data) +{ + if (!g_signal_has_handler_pending(server, + libbalsa_server_signals + [GET_PASSWORD], 0, TRUE)) + g_signal_connect(server, "get-password", cb, cb_data); +} diff -ur --exclude-from=exclude-files --new-file balsa-ref/libbalsa/server.h balsa/libbalsa/server.h --- balsa-ref/libbalsa/server.h 2004-05-08 16:25:39.000000000 +0200 +++ balsa/libbalsa/server.h 2004-08-27 19:15:24.000000000 +0200 @@ -95,4 +95,7 @@ void libbalsa_server_user_cb(ImapUserEventType ue, void *arg, ...); + +void libbalsa_server_connect_signals(LibBalsaServer * server, GCallback cb, + gpointer cb_data); #endif /* __LIBBALSA_SERVER_H__ */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-directory.c balsa/libinit_balsa/balsa-druid-page-directory.c --- balsa-ref/libinit_balsa/balsa-druid-page-directory.c 2004-08-02 23:28:23.000000000 +0200 +++ balsa/libinit_balsa/balsa-druid-page-directory.c 2004-08-26 18:15:30.000000000 +0200 @@ -220,7 +220,7 @@ g_free(preset); } - gtk_box_pack_start(GTK_BOX(page->vbox), GTK_WIDGET(table), TRUE, TRUE, + gtk_box_pack_start(GTK_BOX(page->vbox), GTK_WIDGET(table), FALSE, TRUE, 8); gtk_widget_show_all(GTK_WIDGET(table)); @@ -283,6 +283,7 @@ g_free(buf); } + /* Don't let them continue unless all entries have something. */ if (ENTRY_MASTER_DONE(dir->emaster)) { gnome_druid_set_buttons_sensitive(druid, TRUE, TRUE, TRUE, FALSE); @@ -349,6 +350,37 @@ return FALSE; } +#define SET_MAILBOX(fname, config, mbx) \ +do { gchar *t=g_strconcat(balsa_app.local_mail_directory,"/",(fname),NULL);\ + unconditional_mailbox(t, config, (mbx), &error); g_free(t);}while(0) + +void +balsa_druid_page_directory_later(GtkWidget *druid) +{ + gchar *error = NULL; + gchar *spool = libbalsa_guess_mail_spool(); + unconditional_mailbox(spool, INBOX_NAME, &balsa_app.inbox, &error); + g_free(spool); + SET_MAILBOX("trash", TRASH_NAME, &balsa_app.trash); + SET_MAILBOX("outbox", OUTBOX_NAME, &balsa_app.outbox); + SET_MAILBOX("sentbox", SENTBOX_NAME, &balsa_app.sentbox); + SET_MAILBOX("draftbox", DRAFTBOX_NAME, &balsa_app.draftbox); + if (error) { + GtkWidget *dlg = + gtk_message_dialog_new(GTK_WINDOW(gtk_widget_get_ancestor + (GTK_WIDGET(druid), + GTK_TYPE_WINDOW)), + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Problem Creating Mailboxes\n%s"), + error); + g_free(error); + gtk_dialog_run(GTK_DIALOG(dlg)); + gtk_widget_destroy(dlg); + } +} + static gboolean balsa_druid_page_directory_back(GnomeDruidPage * page, GtkWidget * druid, BalsaDruidPageDirectory * dir) diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-directory.h balsa/libinit_balsa/balsa-druid-page-directory.h --- balsa-ref/libinit_balsa/balsa-druid-page-directory.h 2002-03-09 09:14:34.000000000 +0100 +++ balsa/libinit_balsa/balsa-druid-page-directory.h 2004-08-26 18:15:30.000000000 +0200 @@ -65,13 +65,10 @@ /* * Public methods */ -#if BALSA_MAJOR < 2 - void balsa_druid_page_directory(GnomeDruid * druid, - GdkImlibImage * default_logo); -#else void balsa_druid_page_directory(GnomeDruid * druid, GdkPixbuf * default_logo); -#endif /* BALSA_MAJOR < 2 */ + void balsa_druid_page_directory_later(GtkWidget *druid); + #ifdef __cplusplus } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-finish.c balsa/libinit_balsa/balsa-druid-page-finish.c --- balsa-ref/libinit_balsa/balsa-druid-page-finish.c 2004-07-10 00:16:28.000000000 +0200 +++ balsa/libinit_balsa/balsa-druid-page-finish.c 2004-09-04 19:31:52.000000000 +0200 @@ -19,11 +19,18 @@ * 02111-1307, USA. */ +#include "config.h" + +#include "balsa-druid-page-directory.h" #include "balsa-druid-page-finish.h" #include "save-restore.h" #include "balsa-app.h" +#if defined(ENABLE_TOUCH_UI) && defined(HAVE_SQLITE) +#include "address-book-gpe.h" +#endif + /* here are local prototypes */ static void balsa_druid_page_finish_prepare(GnomeDruidPage * page, GnomeDruid * druid); @@ -65,6 +72,9 @@ gchar *address_book; LibBalsaAddressBook *ab = NULL; +#if defined(ENABLE_TOUCH_UI) + balsa_druid_page_directory_later(GTK_WIDGET(druid)); +#endif address_book = gnome_util_home_file("GnomeCard.gcrd"); if (g_file_test(address_book, G_FILE_TEST_EXISTS)) ab = libbalsa_address_book_vcard_new(_("GnomeCard Address Book"), @@ -79,6 +89,9 @@ g_free(address_book); } if(!ab) { +#if defined(ENABLE_TOUCH_UI) && defined(HAVE_SQLITE) + ab = libbalsa_address_book_gpe_new(_("Address Book")); +#else /* This will be the default address book and its location */ address_book = g_strconcat(g_get_home_dir(), "/.balsa/addressbook.ldif", NULL); @@ -86,12 +99,15 @@ address_book); g_free(address_book); libbalsa_assure_balsa_dir(); +#endif } balsa_app.address_book_list = g_list_prepend(balsa_app.address_book_list, ab); balsa_app.default_address_book = ab; + g_signal_handlers_disconnect_by_func(G_OBJECT(druid), + G_CALLBACK(exit), NULL); config_save(); gtk_main_quit(); } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-user.c balsa/libinit_balsa/balsa-druid-page-user.c --- balsa-ref/libinit_balsa/balsa-druid-page-user.c 2004-02-08 01:18:41.000000000 +0100 +++ balsa/libinit_balsa/balsa-druid-page-user.c 2004-08-26 18:15:30.000000000 +0200 @@ -19,12 +19,16 @@ * 02111-1307, USA. */ +#include "config.h" + #include "balsa-druid-page-user.h" #include #include +#include "imap-server.h" #include "balsa-app.h" +#include "save-restore.h" /* here are local prototypes */ @@ -43,59 +47,102 @@ GnomeDruidPageStandard * page, GnomeDruid * druid) { + static const char *header2 = + N_("The following settings are also needed " + "(and you can find them later, if need be, in the Email " + "application in the 'Preferences' and 'Identities' " + "commands on the 'Tools' menu)"); + static const char *header21 = + N_(" Whoever provides your email account should be able " + "to give you the following information (if you have " + "a Network Administrator, they may already have set " + "this up for you):"); + static const char* server_types[] = { "POP3", "IMAP", NULL }; + static const char* remember_passwd[] = { + N_("Yes, remember it"), N_("No, type it in every time"), NULL }; GtkTable *table; GtkLabel *label; gchar *preset; + int row = 0; user->emaster.setbits = 0; user->emaster.numentries = 0; user->emaster.donemask = 0; user->ed0.master = &(user->emaster); user->ed1.master = &(user->emaster); - user->ed2.master = &(user->emaster); #if ENABLE_ESMTP + user->ed2.master = &(user->emaster); +#endif +#ifndef ENABLE_TOUCH_UI user->ed3.master = &(user->emaster); - - table = GTK_TABLE(gtk_table_new(5, 2, FALSE)); -#else - table = GTK_TABLE(gtk_table_new(4, 2, FALSE)); #endif - label = - GTK_LABEL(gtk_label_new - (_("Please enter information about yourself."))); + label = GTK_LABEL(gtk_label_new(_(header2))); + gtk_label_set_line_wrap(label, TRUE); + gtk_box_pack_start_defaults(GTK_BOX(page->vbox), GTK_WIDGET(label)); + + table = GTK_TABLE(gtk_table_new(10, 2, FALSE)); + + label = GTK_LABEL(gtk_label_new(_(header21))); gtk_label_set_justify(label, GTK_JUSTIFY_CENTER); gtk_label_set_line_wrap(label, TRUE); gtk_table_attach(table, GTK_WIDGET(label), 0, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 8, 4); - preset = g_strdup(g_get_real_name()); - balsa_init_add_table_entry(table, 0, _("_Name:"), preset, + /* 2.1 */ + balsa_init_add_table_entry(table, row++, + _("Name of mail server for incoming _mail:"), + "", /* no guessing here */ + NULL, druid, &(user->incoming_srv)); + + balsa_init_add_table_option(table, row++, + _("_Type of mail server:"), + server_types, druid, &(user->incoming_type)); + + balsa_init_add_table_checkbox(table, row++, + _("Connect using _SSL:"), FALSE, + druid, &(user->using_ssl)); + + balsa_init_add_table_entry(table, row++, _("Your e-mail _login name:"), + g_get_user_name(), + NULL, druid, &(user->login)); + balsa_init_add_table_entry(table, row++, _("Your _password:"), + "", + NULL, druid, &(user->passwd)); + gtk_entry_set_visibility(GTK_ENTRY(user->passwd), FALSE); + /* separator line here */ + +#if ENABLE_ESMTP + preset = "localhost:25"; + balsa_init_add_table_entry(table, row++, _("_SMTP Server:"), preset, + &(user->ed2), druid, &(user->smtp)); +#endif + + /* 2.1 */ + balsa_init_add_table_entry(table, row++, _("Your real _name:"), + g_get_real_name(), &(user->ed0), druid, &(user->name)); - g_free(preset); preset = libbalsa_guess_email_address(); - balsa_init_add_table_entry(table, 1, _("_Email Address:"), preset, - &(user->ed1), druid, &(user->email)); + balsa_init_add_table_entry + (table, row++, _("Your _Email Address, for this email account:"), + preset, &(user->ed1), druid, &(user->email)); g_free(preset); + balsa_init_add_table_option(table, row++, + _("_Remember your password:"), + remember_passwd, druid, + &(user->remember_passwd)); +#if !defined(ENABLE_TOUCH_UI) preset = g_strconcat(g_get_home_dir(), "/mail", NULL); - balsa_init_add_table_entry(table, 2, _("_Local Mail Directory:"), - preset, &(user->ed2), - druid, &(user->localmaildir)); + balsa_init_add_table_entry(table, row++, _("_Local mail directory:"), + preset, + &(user->ed3), druid, &(user->localmaildir)); g_free(preset); - -#if ENABLE_ESMTP - preset = "localhost:25"; - balsa_init_add_table_entry(table, 3, _("_SMTP Server:"), preset, - &(user->ed3), druid, &(user->smtp)); #endif - gtk_box_pack_start(GTK_BOX(page->vbox), GTK_WIDGET(table), TRUE, TRUE, 8); - - return; } void @@ -130,15 +177,87 @@ } gnome_druid_set_show_finish(druid, FALSE); + gtk_widget_grab_focus(user->incoming_srv); +} + +static LibBalsaMailbox* +create_pop3_mbx(const gchar* host, gboolean ssl, + const gchar *login, const gchar *passwd, + gboolean remember) +{ + LibBalsaMailboxPop3 *pop = libbalsa_mailbox_pop3_new(); + LibBalsaMailbox *mbx = LIBBALSA_MAILBOX(pop); + LibBalsaServer *server = LIBBALSA_MAILBOX_REMOTE_SERVER(pop); + + libbalsa_server_set_username(server, login); + libbalsa_server_set_password(server, passwd); + libbalsa_server_set_host(server, host, ssl); + server->tls_mode = LIBBALSA_TLS_ENABLED; + server->remember_passwd = remember; + mbx->name = g_strdup(host); + pop->check = TRUE; + pop->disable_apop = FALSE; + pop->delete_from_server = TRUE; + pop->filter = FALSE; + pop->filter_cmd = g_strdup("procmail -f -"); + + return mbx; +} + +static LibBalsaMailbox* +create_imap_mbx(const gchar* host, gboolean ssl, + const gchar *login, const gchar *passwd, + gboolean remember) +{ + LibBalsaMailboxImap *imap = libbalsa_mailbox_imap_new(); + LibBalsaMailbox *mbx = LIBBALSA_MAILBOX(imap); + LibBalsaServer *server = + LIBBALSA_SERVER(libbalsa_imap_server_new(login, host)); + libbalsa_mailbox_remote_set_server(LIBBALSA_MAILBOX_REMOTE(imap), + server); + libbalsa_server_set_username(server, login); + libbalsa_server_set_password(server, passwd); + libbalsa_server_set_host(server, host, ssl); + server->tls_mode = LIBBALSA_TLS_ENABLED; + server->remember_passwd = remember; + mbx->name = g_strdup(host); + + libbalsa_mailbox_imap_set_path(imap, "INBOX"); + return mbx; } static gboolean balsa_druid_page_user_next(GnomeDruidPage * page, GnomeDruid * druid, BalsaDruidPageUser * user) { + const gchar *host; gchar *uhoh; LibBalsaIdentity *ident; + + /* incoming mail */ + host = gtk_entry_get_text(GTK_ENTRY(user->incoming_srv)); + if(host && *host) { + LibBalsaMailbox *mbx = NULL; + const gchar *login = gtk_entry_get_text(GTK_ENTRY(user->login)); + const gchar *passwd = gtk_entry_get_text(GTK_ENTRY(user->passwd)); + gboolean ssl = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(user->using_ssl)); + gboolean remember = + balsa_option_get_active(user->remember_passwd) == 0; + switch(balsa_option_get_active(user->incoming_type)) { + case 0: /* POP */ + mbx = create_pop3_mbx(host, ssl, login, passwd, remember); + break; + case 1: /* IMAP */ + mbx = create_imap_mbx(host, ssl, login, passwd, remember); + break; + default: /* hm */; + } + if(mbx) + config_mailbox_add(mbx, NULL); + } + /* identity */ if (balsa_app.identities == NULL) { ident = LIBBALSA_IDENTITY(libbalsa_identity_new()); balsa_app.identities = g_list_append(NULL, ident); @@ -155,15 +274,21 @@ g_list_prepend(NULL, gtk_editable_get_chars(GTK_EDITABLE(user->email), 0, -1)); - + /* outgoing mail */ #if ENABLE_ESMTP g_free(balsa_app.smtp_server); balsa_app.smtp_server = gtk_editable_get_chars(GTK_EDITABLE(user->smtp), 0, -1); #endif + g_free(balsa_app.local_mail_directory); +#if defined(ENABLE_TOUCH_UI) + balsa_app.local_mail_directory = + g_strconcat(g_get_home_dir(), "/mail", NULL); +#else balsa_app.local_mail_directory = gtk_editable_get_chars(GTK_EDITABLE(user->localmaildir), 0, -1); +#endif /* ENABLE_TOUCH_UI */ if (balsa_init_create_to_directory (balsa_app.local_mail_directory, &uhoh)) { diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-user.h balsa/libinit_balsa/balsa-druid-page-user.h --- balsa-ref/libinit_balsa/balsa-druid-page-user.h 2002-03-09 09:14:34.000000000 +0100 +++ balsa/libinit_balsa/balsa-druid-page-user.h 2004-08-26 18:15:30.000000000 +0200 @@ -44,28 +44,36 @@ #endif #define BALSA_DRUID_PAGE_USER(obj) ((BalsaDruidPageUser *) obj) struct _BalsaDruidPageUser { + GtkWidget *incoming_srv; + GtkWidget *incoming_type; + GtkWidget *using_ssl; + GtkWidget *login; + GtkWidget *passwd; + GtkWidget *remember_passwd; +#if ENABLE_ESMTP + GtkWidget *smtp; +#endif GtkWidget *name; GtkWidget *email; - GtkWidget *smtp; +#if !defined(ENABLE_TOUCH_UI) GtkWidget *localmaildir; +#endif /* ENABLE_TOUCH_UI */ EntryMaster emaster; EntryData ed0; EntryData ed1; EntryData ed2; EntryData ed3; - + EntryData ed4; + EntryData ed5; + EntryData ed6; + EntryData ed7; }; /* * Public methods */ -#if BALSA_MAJOR < 2 - void balsa_druid_page_user(GnomeDruid * druid, - GdkImlibImage * default_logo); -#else void balsa_druid_page_user(GnomeDruid * druid, GdkPixbuf * default_logo); -#endif /* BALSA_MAJOR < 2 */ #ifdef __cplusplus } diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-druid-page-welcome.c balsa/libinit_balsa/balsa-druid-page-welcome.c --- balsa-ref/libinit_balsa/balsa-druid-page-welcome.c 2004-02-08 01:18:41.000000000 +0100 +++ balsa/libinit_balsa/balsa-druid-page-welcome.c 2004-08-26 18:15:30.000000000 +0200 @@ -31,15 +31,14 @@ static const gchar title[] = N_("Welcome to Balsa!"); static const gchar text[] = N_ - ("You seem to be running Balsa for the first time. " - "The following steps will set up Balsa by asking " - "a few simple questions. Once you have completed " - "these steps, you can always change them later in " - "Balsa's preferences. If any files or directories " - "need to be created, it will be done so automatically.\n" - " Please check the about box in Balsa's main window " - "for more information about contacting the authors " - "or reporting bugs."); + ("Before you can send or receive email:\n\n" + "-- either you should already have Internet access and an " + "email account, provided by an Internet Service Provider, " + "and you should have made that Internet connection on your " + "Netbook -- for example, using Desk / Programs / Modem Dialler.\n\n" + "-- or your Network Administrator at your place of " + "work/study/similar may have set up your Netbook to " + "connect to the network."); page = GNOME_DRUID_PAGE_EDGE(gnome_druid_page_edge_new diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/balsa-initdruid.c balsa/libinit_balsa/balsa-initdruid.c --- balsa-ref/libinit_balsa/balsa-initdruid.c 2004-02-08 01:18:41.000000000 +0100 +++ balsa/libinit_balsa/balsa-initdruid.c 2004-09-03 20:27:05.000000000 +0200 @@ -40,8 +40,10 @@ balsa_druid_page_welcome(druid, default_logo); balsa_druid_page_user(druid, default_logo); +#if !defined(ENABLE_TOUCH_UI) balsa_druid_page_directory(druid, default_logo); balsa_druid_page_defclient(druid, default_logo); +#endif balsa_druid_page_finish(druid, default_logo); } @@ -57,6 +59,8 @@ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(druid)); g_signal_connect(G_OBJECT(druid), "cancel", G_CALLBACK(balsa_initdruid_cancel), NULL); + g_signal_connect(G_OBJECT(druid), "destroy", + G_CALLBACK(exit), NULL); g_object_ref(G_OBJECT(window)); balsa_initdruid_init(druid); diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/helper.c balsa/libinit_balsa/helper.c --- balsa-ref/libinit_balsa/helper.c 2004-02-08 01:18:41.000000000 +0100 +++ balsa/libinit_balsa/helper.c 2004-08-26 18:15:30.000000000 +0200 @@ -33,6 +33,9 @@ #include "libbalsa.h" #include "url.h" +#if GTK_CHECK_VERSION(2,4,0) +#define USE_COMBO_BOX 1 +#endif /* * #ifdef BALSA_LOCAL_INSTALL * #define gnome_pixmap_file(s) g_strconcat(BALSA_RESOURCE_PREFIX, "/pixmaps/", s, NULL) @@ -77,9 +80,6 @@ { GtkWidget *l, *e; - ed->num = num; - ed->druid = druid; - l = gtk_label_new_with_mnemonic(ltext); gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_RIGHT); gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); @@ -87,19 +87,21 @@ GTK_FILL, GTK_FILL, 8, 4); e = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(e), etext); - g_signal_connect(G_OBJECT(e), "changed", - G_CALLBACK(entry_changed_cb), ed); gtk_label_set_mnemonic_widget(GTK_LABEL(l), e); gtk_table_attach(table, GTK_WIDGET(e), 1, 2, num + 1, num + 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 8, 4); - - if (etext && etext[0] != '\0') - ed->master->setbits |= (1 << num); - (*dest) = e; - ed->master->numentries++; - ed->master->donemask = (ed->master->donemask << 1) | 1; + if(ed) { + g_signal_connect(G_OBJECT(e), "changed", + G_CALLBACK(entry_changed_cb), ed); + ed->num = ed->master->numentries++; + ed->druid = druid; + if (etext && etext[0] != '\0') + ed->master->setbits |= (1 << num); + + ed->master->donemask = (ed->master->donemask << 1) | 1; + } + gtk_entry_set_text(GTK_ENTRY(e), etext); } static void @@ -131,6 +133,78 @@ } } + +void +balsa_init_add_table_option(GtkTable *table, guint num, + const gchar *ltext, const gchar **optns, + GnomeDruid *druid, GtkWidget **dest) +{ + GtkWidget *l, *om; + int i; + l = gtk_label_new_with_mnemonic(ltext); + gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); + gtk_table_attach(table, l, 0, 1, num + 1, num + 2, + GTK_FILL, GTK_FILL, 8, 4); + +#ifdef USE_COMBO_BOX + *dest = om = gtk_combo_box_new_text(); + for(i=0; optns[i]; i++) + gtk_combo_box_append_text(GTK_COMBO_BOX(om), _(optns[i])); + gtk_label_set_mnemonic_widget(GTK_LABEL(l), om); + gtk_combo_box_set_active(GTK_COMBO_BOX(om), 0); + gtk_table_attach(table, om, 1, 2, num + 1, num + 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 8, 4); +#else + *dest = gtk_menu_new(); + for(i=0; optns[i]; i++) { + GtkWidget *menu_item = gtk_menu_item_new_with_label(_(optns[i])); + g_object_set_data(G_OBJECT(menu_item), "balsa-data", + GINT_TO_POINTER(i)); + gtk_menu_shell_append(GTK_MENU_SHELL(*dest), menu_item); + } + om = gtk_option_menu_new(); + gtk_option_menu_set_menu (GTK_OPTION_MENU(om), *dest); + gtk_label_set_mnemonic_widget(GTK_LABEL(l), om); + gtk_table_attach(table, om, 1, 2, num + 1, num + 2, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 8, 4); + +#endif /* USE_COMBO_BOX */ +} + +gint +balsa_option_get_active(GtkWidget *option_widget) +{ +#ifdef USE_COMBO_BOX + return gtk_combo_box_get_active(GTK_COMBO_BOX(option_widget)); +#else + GtkWidget *menu_item = gtk_menu_get_active(GTK_MENU(option_widget)); + return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menu_item), + "balsa-data")); +#endif +} + +void +balsa_init_add_table_checkbox(GtkTable *table, guint num, + const gchar *ltext, gboolean defval, + GnomeDruid *druid, GtkWidget **dest) +{ + GtkWidget *l; + + l = gtk_label_new_with_mnemonic(ltext); + gtk_label_set_justify(GTK_LABEL(l), GTK_JUSTIFY_RIGHT); + gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); + gtk_table_attach(table, l, 0, 1, num + 1, num + 2, + GTK_FILL, GTK_FILL, 8, 4); + + *dest = gtk_check_button_new(); + gtk_table_attach(table, *dest, 1, 2, num + 1, num + 2, + GTK_FILL, GTK_FILL, 8, 4); + if(defval) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(*dest), TRUE); + gtk_label_set_mnemonic_widget(GTK_LABEL(l), *dest); +} + gboolean balsa_init_create_to_directory(const gchar * dir, gchar ** complaint) { diff -ur --exclude-from=exclude-files --new-file balsa-ref/libinit_balsa/helper.h balsa/libinit_balsa/helper.h --- balsa-ref/libinit_balsa/helper.h 2002-03-09 09:14:34.000000000 +0100 +++ balsa/libinit_balsa/helper.h 2004-08-26 18:15:30.000000000 +0200 @@ -54,6 +54,14 @@ void balsa_init_add_table_entry(GtkTable * table, guint num, gchar * ltext, const gchar * etext, EntryData * ed, GnomeDruid * druid, GtkWidget ** dest); +void balsa_init_add_table_option(GtkTable *table, guint num, + const gchar *ltext, const gchar **optns, + GnomeDruid *druid, GtkWidget **dest); +void balsa_init_add_table_checkbox(GtkTable *table, guint num, + const gchar *ltext, gboolean defval, + GnomeDruid *druid, GtkWidget **dest); +gint balsa_option_get_active(GtkWidget *option_widget); + gboolean balsa_init_create_to_directory(const gchar * dir, gchar ** complaint); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/ab-main.c balsa/src/ab-main.c --- balsa-ref/src/ab-main.c 2003-09-12 20:14:04.000000000 +0200 +++ balsa/src/ab-main.c 2004-08-21 23:55:50.000000000 +0200 @@ -38,6 +38,7 @@ #include "address-book-ldap.h" #endif #include "address-book-vcard.h" +#include "address-book-gpe.h" struct ABMainWindow { GtkWidget *entry_list; /* GtkListView widget */ @@ -443,6 +444,9 @@ #if ENABLE_LDAP LIBBALSA_TYPE_ADDRESS_BOOK_LDAP; #endif +#if HAVE_SQLITE + LIBBALSA_TYPE_ADDRESS_BOOK_GPE; +#endif memset(&contacts_app, 0, sizeof(contacts_app)); } diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/address-book-config.c balsa/src/address-book-config.c --- balsa-ref/src/address-book-config.c 2004-08-02 23:28:23.000000000 +0200 +++ balsa/src/address-book-config.c 2004-08-24 08:08:48.000000000 +0200 @@ -25,6 +25,7 @@ #include "balsa-app.h" #include "address-book-config.h" +#include "address-book-gpe.h" typedef struct _AddressBookConfig AddressBookConfig; struct _AddressBookConfig { @@ -81,6 +82,9 @@ #ifdef ENABLE_LDAP static GtkWidget *create_ldap_page(AddressBookConfig * abc); #endif +#ifdef HAVE_SQLITE +static GtkWidget *create_gpe_page(AddressBookConfig * abc); +#endif static void set_the_page(GtkWidget * button, AddressBookConfig * abc); static void abc_response_cb(GtkDialog* d, gint respo, AddressBookConfig * abc); @@ -248,6 +252,19 @@ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_widget_show(label); #endif +#ifdef HAVE_SQLITE + radio_button = gtk_radio_button_new_with_label + (gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button)), + _("GPE Address Book")); + gtk_box_pack_start(GTK_BOX(vbox), radio_button, FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(radio_button), "clicked", + G_CALLBACK(set_the_page), (gpointer) abc); + g_object_set_data(G_OBJECT(radio_button), "user_data", + GINT_TO_POINTER(LIBBALSA_TYPE_ADDRESS_BOOK_GPE)); + gtk_widget_show(radio_button); +#else + /* Should we inform about missing SQLite support? */ +#endif return vbox; @@ -267,6 +284,10 @@ } else if (abc->type == LIBBALSA_TYPE_ADDRESS_BOOK_LDAP) { return create_ldap_page(abc); #endif +#ifdef HAVE_SQLITE + } else if (abc->type == LIBBALSA_TYPE_ADDRESS_BOOK_GPE) { + return create_gpe_page(abc); +#endif } else { g_assert_not_reached(); } @@ -499,6 +520,34 @@ } #endif +#ifdef HAVE_SQLITE +static GtkWidget * +create_gpe_page(AddressBookConfig * abc) +{ + GtkWidget *table = gtk_table_new(2, 6, FALSE); + + LibBalsaAddressBook* ab; + GtkDialog* mcw = GTK_DIALOG(abc->window); + GtkWidget* label; + + ab = (LibBalsaAddressBook*)abc->address_book; /* may be NULL */ + + abc->link_id = "GPE"; + /* mailbox name */ + + label = create_label(_("A_ddress Book Name"), table, 0); + abc->name_entry = create_entry(mcw, table, NULL, NULL, 0, + ab ? ab->name : _("GPE Address Book"), + label); + abc->expand_aliases_button = + create_check(mcw, _("_Expand aliases as you type"), table, 3, + ab ? ab->expand_aliases : TRUE); + gtk_widget_show_all(table); + + return table; +} +#endif + static void set_the_page(GtkWidget * button, AddressBookConfig * abc) { @@ -726,6 +775,11 @@ libbalsa_address_book_ldap_new(name, host_name, base_dn, bind_dn, passwd, enable_tls); #endif +#ifdef HAVE_SQLITE + } else if (abc->type == LIBBALSA_TYPE_ADDRESS_BOOK_GPE) { + address_book = + libbalsa_address_book_gpe_new(name); +#endif } else g_assert_not_reached(); if (address_book) { @@ -813,6 +867,10 @@ ldap->enable_tls = enable_tls; libbalsa_address_book_ldap_close_connection(ldap); #endif +#ifdef HAVE_SQLITE + } else if (abc->type == LIBBALSA_TYPE_ADDRESS_BOOK_GPE) { + /* nothing to do, name was updated above */ +#endif } else g_assert_not_reached(); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-app.c balsa/src/balsa-app.c --- balsa-ref/src/balsa-app.c 2004-08-06 17:02:26.000000000 +0200 +++ balsa/src/balsa-app.c 2004-08-31 22:47:21.000000000 +0200 @@ -80,6 +80,7 @@ dialog = gtk_dialog_new_with_buttons(_("Password needed"), GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, @@ -776,6 +777,13 @@ return mailbox; } +LibBalsaMailbox* +balsa_find_sentbox_by_url(const gchar *url) +{ + LibBalsaMailbox *res = balsa_find_mailbox_by_url(url); + return res ? res : balsa_app.sentbox; +} + struct balsa_find_iter_by_data_info { GtkTreeIter *iter; gpointer data; @@ -838,8 +846,8 @@ || mailbox == balsa_app.sentbox || mailbox == balsa_app.draftbox || mailbox == balsa_app.trash) { - g_object_ref(mbnode); - *specials = g_slist_prepend(*specials, mbnode); + g_object_ref(mailbox); + *specials = g_slist_prepend(*specials, mailbox); } ba_remove_children_mailbox_nodes(model, &iter, specials); valid = @@ -872,7 +880,9 @@ ba_remove_children_mailbox_nodes(model, iter, &specials); for (l = specials; l; l = l->next) - balsa_mblist_mailbox_node_append(NULL, l->data); + balsa_mblist_mailbox_node_append(NULL, + balsa_mailbox_node_new_from_mailbox + (l->data)); g_slist_free(specials); } diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-app.h balsa/src/balsa-app.h --- balsa-ref/src/balsa-app.h 2004-08-06 00:07:58.000000000 +0200 +++ balsa/src/balsa-app.h 2004-08-31 22:47:21.000000000 +0200 @@ -56,16 +56,16 @@ #define NUM_DEFAULT_WIDTH 30 #define STATUS_DEFAULT_WIDTH 16 #define ATTACHMENT_DEFAULT_WIDTH 16 -#define FROM_DEFAULT_WIDTH 160 -#define SUBJECT_DEFAULT_WIDTH 250 +#define FROM_DEFAULT_WIDTH 128 +#define SUBJECT_DEFAULT_WIDTH 180 #define DATE_DEFAULT_WIDTH 128 #define SIZE_DEFAULT_WIDTH 40 /* default width settings for the mailbox list columns, not fully utilized yet */ #define MBNAME_DEFAULT_WIDTH 80 -#define NEWMSGCOUNT_DEFAULT_WIDTH 45 -#define TOTALMSGCOUNT_DEFAULT_WIDTH 45 +#define NEWMSGCOUNT_DEFAULT_WIDTH 20 +#define TOTALMSGCOUNT_DEFAULT_WIDTH 25 #define INFO_FIELD_LENGTH 10 /* @@ -89,9 +89,9 @@ #define DEFAULT_SUBJECT_FONT "helvetica Bold 10" #define DEFAULT_DATE_FORMAT "%x %X" #define DEFAULT_PAPER_SIZE "A4" -#define DEFAULT_PRINT_HEADER_FONT "Times Roman 11" -#define DEFAULT_PRINT_BODY_FONT "Courier 11" -#define DEFAULT_PRINT_FOOTER_FONT "Times Roman 7" +#define DEFAULT_PRINT_HEADER_FONT "Bitstream Charter Bold 12" +#define DEFAULT_PRINT_BODY_FONT "Courier Regular 11" +#define DEFAULT_PRINT_FOOTER_FONT "Bitstream Charter Bold Italic 8" #define DEFAULT_SELECTED_HDRS "from to date cc subject" #define DEFAULT_MESSAGE_TITLE_FORMAT "Message from %F: %s" #define DEFAULT_ENCODING ENC8BIT @@ -411,6 +411,7 @@ BalsaMailboxNode *balsa_find_dir(LibBalsaServer *server, const gchar * path); BalsaMailboxNode *balsa_find_url(const gchar * url); LibBalsaMailbox *balsa_find_mailbox_by_url(const gchar * url); +LibBalsaMailbox *balsa_find_sentbox_by_url(const gchar * url); gboolean balsa_find_iter_by_data(GtkTreeIter * iter, gpointer data); BalsaIndex* balsa_find_index_by_mailbox(LibBalsaMailbox* mailbox); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-bonobo.c balsa/src/balsa-bonobo.c --- balsa-ref/src/balsa-bonobo.c 2004-01-14 23:53:43.000000000 +0100 +++ balsa/src/balsa-bonobo.c 2004-08-21 23:26:36.000000000 +0200 @@ -64,10 +64,14 @@ CORBA_Environment * ev); static void impl_balsa_application_openInbox (PortableServer_Servant _servant, CORBA_Environment * ev); +static void impl_balsa_application_getStats (PortableServer_Servant _servant, + CORBA_long *unread, + CORBA_long *unsent, + CORBA_Environment * ev); /* from main.c */ gboolean initial_open_unread_mailboxes(); gboolean initial_open_inbox(); - +void balsa_get_stats(long *unread, long *unsent); /* * @@ -209,6 +213,7 @@ epv->openMailbox = impl_balsa_application_openMailbox; epv->openUnread = impl_balsa_application_openUnread; epv->openInbox = impl_balsa_application_openInbox; + epv->getStats = impl_balsa_application_getStats; } @@ -239,6 +244,17 @@ CORBA_Environment * ev) { initial_open_inbox(); } + +static void +impl_balsa_application_getStats (PortableServer_Servant _servant, + CORBA_long *unread, + CORBA_long *unsent, + CORBA_Environment * ev) { + long r, s; + balsa_get_stats(&r, &s); + *unread = r; + *unsent = s; +} static void balsa_application_init (BalsaApplication *c) diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/Balsa.idl balsa/src/Balsa.idl --- balsa-ref/src/Balsa.idl 2004-01-04 01:56:54.000000000 +0100 +++ balsa/src/Balsa.idl 2004-08-21 23:20:25.000000000 +0200 @@ -41,6 +41,7 @@ void openMailbox (in string name); void openUnread ( ); void openInbox ( ); + void getStats (out long unread, out long unsent); }; }; }; diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-index.c balsa/src/balsa-index.c --- balsa-ref/src/balsa-index.c 2004-08-04 14:06:14.000000000 +0200 +++ balsa/src/balsa-index.c 2004-09-04 19:27:04.000000000 +0200 @@ -30,13 +30,6 @@ key and replace the key on every change of the sort method. */ -/* TREE_VIEW_FIXED_HEIGHT enables hight-performance mode of GtkTreeView - * very useful for large mailboxes (#msg >5000) but: a. is available only - * in gtk2>=2.3.5 b. may expose some bugs in gtk. - */ -#define TREE_VIEW_FIXED_HEIGHT 1 -#undef TREE_VIEW_FIXED_HEIGHT - #include "config.h" #include @@ -57,6 +50,16 @@ #include "filter-funcs.h" #include "misc.h" +/* TREE_VIEW_FIXED_HEIGHT enables hight-performance mode of GtkTreeView + * very useful for large mailboxes (#msg >5000) but: a. is available only + * in gtk2>=2.3.5 b. may expose some bugs in gtk. + * gtk-2.4.9 has been tested with a positive result. + */ +#if GTK_CHECK_VERSION(2,4,9) +#define TREE_VIEW_FIXED_HEIGHT 1 +#endif + + /* gtk widget */ static void bndx_class_init(BalsaIndexClass * klass); static void bndx_instance_init(BalsaIndex * index); @@ -270,7 +273,7 @@ gtk_tree_view_column_set_alignment(column, 0.5); #if GTK_CHECK_VERSION(2,4,0) && defined(TREE_VIEW_FIXED_HEIGHT) - gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); #endif } @@ -612,6 +615,10 @@ gtk_tree_model_get(model, iter, LB_MBOX_MESSAGE_COL, &sci->message, -1); + if(!sci->message) /* Sad but true: backend knows the message + * exists but could not fetch more data - we + * need to handle it gracefully. */ + return; if (!g_slist_find(*sci->selected, sci->message)) *sci->selected = g_slist_prepend(*sci->selected, sci->message); else { @@ -873,6 +880,7 @@ g_free(msg); try_cnt = 0; do { + g_clear_error(err); gdk_threads_leave(); successp = libbalsa_mailbox_open(mailbox, err); gdk_threads_enter(); @@ -882,7 +890,6 @@ !(*err && (*err)->code == LIBBALSA_MAILBOX_TOOMANYOPEN_ERROR)) break; balsa_mblist_close_lru_peer_mbx(balsa_app.mblist, mailbox); - g_clear_error(err); } while(try_cnt++<3); gnome_appbar_pop(balsa_app.appbar); @@ -1347,8 +1354,10 @@ balsa_index_selected_list_func, &list); if (index->current_message - && !g_list_find(list, index->current_message)) + && !g_list_find(list, index->current_message)) { list = g_list_prepend(list, index->current_message); + g_object_ref(index->current_message); + } return list; } diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-mblist.c balsa/src/balsa-mblist.c --- balsa-ref/src/balsa-mblist.c 2004-08-07 19:27:57.000000000 +0200 +++ balsa/src/balsa-mblist.c 2004-09-12 23:07:41.000000000 +0200 @@ -327,7 +327,7 @@ * under its heading. */ /* Unread message count column */ column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(column, _("Unread")); + gtk_tree_view_column_set_title(column, "U"); gtk_tree_view_column_set_alignment(column, 0.5); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column, renderer, TRUE); @@ -352,7 +352,7 @@ /* Total message count column */ column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(column, _("Total")); + gtk_tree_view_column_set_title(column, "T"); gtk_tree_view_column_set_alignment(column, 0.5); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column, renderer, TRUE); @@ -1764,9 +1764,10 @@ if (req.height > balsa_app.mw_height) req.height = balsa_app.mw_height; /* For the mailbox list width, we use the one used on the main - * window. This is the user choice and required because the mblist - * widget saves the size in balsa_app.mblist_width */ - req.width = balsa_app.mblist_width; + * window enhanced somewhat. This is the user choice and required + * because the mblist widget saves the size in + * balsa_app.mblist_width */ + req.width = balsa_app.mblist_width> 200 ? balsa_app.mblist_width : 200; gtk_widget_set_size_request(GTK_WIDGET(mblist), req.width, req.height); gtk_container_add(GTK_CONTAINER(scroll), mblist); @@ -1795,7 +1796,7 @@ GtkTreePath *path; GtkTreeViewColumn *column; GdkRectangle rect; - GValue expander_size; + GValue expander_size = {0}; if (!data) return; diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/balsa-message.c balsa/src/balsa-message.c --- balsa-ref/src/balsa-message.c 2004-08-07 19:39:48.000000000 +0200 +++ balsa/src/balsa-message.c 2004-08-31 22:47:21.000000000 +0200 @@ -45,6 +45,7 @@ # include #endif +#include "send.h" #include "quote-color.h" #include "sendmsg-window.h" @@ -1504,7 +1505,6 @@ } g_free(body_type); #endif - g_print("TODO: part_info_init_application\n"); part_info_init_unknown(bm, info); } @@ -2410,7 +2410,9 @@ for (lines = l; *lines; ++lines) { gint quote_level = is_a_quote(*lines, &rex); GtkTextTag *tag = quote_tag(buffer, quote_level); - + int len = strlen(*lines); + if(len>0 && (*lines)[len-1] == '\r') + (*lines)[len-1] = '\0'; /* tag is NULL if the line isn't quoted, but it causes * no harm */ libbalsa_insert_with_url(buffer, *lines, tag, @@ -3143,15 +3145,15 @@ #if ENABLE_ESMTP libbalsa_message_send(message, balsa_app.outbox, NULL, balsa_app.encoding_style, - balsa_app.smtp_server, + balsa_find_sentbox_by_url, balsa_app.smtp_server, (balsa_app.smtp_user && *balsa_app.smtp_user) ? balsa_app.smtp_authctx : NULL, balsa_app.smtp_tls_mode, FALSE, balsa_app.debug); #else libbalsa_message_send(message, balsa_app.outbox, NULL, - balsa_app.encoding_style, - FALSE, balsa_app.debug); + balsa_find_sentbox_by_url, + balsa_app.encoding_style, FALSE, balsa_app.debug); #endif g_object_unref(G_OBJECT(message)); } @@ -3945,13 +3947,16 @@ #if ENABLE_ESMTP libbalsa_message_send(mdn, balsa_app.outbox, NULL, balsa_app.encoding_style, + balsa_find_sentbox_by_url, balsa_app.smtp_server, (balsa_app.smtp_user && *balsa_app.smtp_user) ? balsa_app.smtp_authctx : NULL, balsa_app.smtp_tls_mode, TRUE, balsa_app.debug); #else libbalsa_message_send(mdn, balsa_app.outbox, NULL, - balsa_app.encoding_style, TRUE, balsa_app.debug); + balsa_find_sentbox_by_url, + balsa_app.encoding_style, + TRUE, balsa_app.debug); #endif g_object_unref(G_OBJECT(mdn)); } @@ -4044,6 +4049,7 @@ mdn_dialog = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, @@ -4073,13 +4079,16 @@ #if ENABLE_ESMTP libbalsa_message_send(send_msg, balsa_app.outbox, NULL, balsa_app.encoding_style, + balsa_find_sentbox_by_url, balsa_app.smtp_server, (balsa_app.smtp_user && *balsa_app.smtp_user) ? balsa_app.smtp_authctx : NULL, balsa_app.smtp_tls_mode, TRUE, balsa_app.debug); #else libbalsa_message_send(send_msg, balsa_app.outbox, NULL, - balsa_app.encoding_style, TRUE, balsa_app.debug); + balsa_find_sentbox_by_url, + balsa_app.encoding_style, + TRUE, balsa_app.debug); #endif } diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/expand-alias.c balsa/src/expand-alias.c --- balsa-ref/src/expand-alias.c 2003-09-23 00:25:29.000000000 +0200 +++ balsa/src/expand-alias.c 2004-09-03 20:43:27.000000000 +0200 @@ -158,7 +158,10 @@ } addr = LIBBALSA_ADDRESS(search->data); } - output=libbalsa_address_to_gchar(addr, -1); + /* FIXME: in principle, we should pass -1 instead of 0 but the + * group support is incomplete and these things has to be done + * in one shot otherwise they do more harm than good. */ + output=libbalsa_address_to_gchar(addr, 0); addy->address = addr; g_object_ref(addy->address); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/filter-edit-callbacks.c balsa/src/filter-edit-callbacks.c --- balsa-ref/src/filter-edit-callbacks.c 2004-06-04 23:46:25.000000000 +0200 +++ balsa/src/filter-edit-callbacks.c 2004-08-21 23:20:25.000000000 +0200 @@ -1128,6 +1128,7 @@ condition_dialog= gtk_dialog_new_with_buttons("", GTK_WINDOW(fe_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/filter-edit-dialog.c balsa/src/filter-edit-dialog.c --- balsa-ref/src/filter-edit-dialog.c 2004-01-11 17:55:17.000000000 +0100 +++ balsa/src/filter-edit-dialog.c 2004-08-21 23:20:25.000000000 +0200 @@ -492,7 +492,9 @@ piece = build_left_side(); fe_window = gtk_dialog_new_with_buttons(_("Balsa Filters"), - NULL, 0, /* FIXME */ + NULL, + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/filter-export-dialog.c balsa/src/filter-export-dialog.c --- balsa-ref/src/filter-export-dialog.c 2003-01-21 00:02:07.000000000 +0100 +++ balsa/src/filter-export-dialog.c 2004-08-21 23:20:25.000000000 +0200 @@ -71,7 +71,9 @@ fex_window = gtk_dialog_new_with_buttons(_("Balsa Filters Export"), - NULL, 0, /* FIXME */ + NULL, + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_HELP, GTK_RESPONSE_HELP, diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/folder-conf.c balsa/src/folder-conf.c --- balsa-ref/src/folder-conf.c 2004-08-02 23:28:23.000000000 +0200 +++ balsa/src/folder-conf.c 2004-09-08 00:59:23.000000000 +0200 @@ -54,7 +54,7 @@ GtkWidget *folder_name, *server, *port, *username, *remember, *password, *subscribed, *list_inbox, *prefix; GtkWidget *use_ssl, *tls_mode; - GtkWidget *connection_limit, *enable_persistent; + GtkWidget *connection_limit, *enable_persistent, *has_bugs; }; /* FIXME: identity_name will leak on cancelled folder edition */ @@ -187,6 +187,9 @@ (LIBBALSA_IMAP_SERVER(s), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->enable_persistent))); #endif + libbalsa_imap_server_set_bug + (LIBBALSA_IMAP_SERVER(s), ISBUG_FETCH, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->has_bugs))); libbalsa_server_set_username(s, username); s->remember_passwd = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fcw->remember)); @@ -257,6 +260,7 @@ GTK_DIALOG(gtk_dialog_new_with_buttons (_("Remote IMAP folder"), GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, mn ? _("_Update") : _("_Create"), GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, @@ -279,7 +283,7 @@ table = gtk_table_new(9, 2, FALSE); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, gtk_label_new_with_mnemonic(_("_Basic"))); - advanced = balsa_server_conf_get_advanced_widget(&fcw->bsc, s, 2); + advanced = balsa_server_conf_get_advanced_widget(&fcw->bsc, s, 3); /* Limit number of connections */ fcw->connection_limit = balsa_server_conf_add_spinner @@ -296,6 +300,13 @@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->enable_persistent), TRUE); #endif + fcw->has_bugs = + balsa_server_conf_add_checkbox(&fcw->bsc, + _("Enable _bug workarounds")); + if(s && + libbalsa_imap_server_has_bug(LIBBALSA_IMAP_SERVER(s), ISBUG_FETCH)) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcw->has_bugs), + TRUE); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced, gtk_label_new_with_mnemonic(_("_Advanced"))); @@ -482,6 +493,7 @@ dialog = gtk_dialog_new_with_buttons(_("Select parent folder"), GTK_WINDOW(sdd->dialog), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, @@ -755,7 +767,9 @@ return; } - ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), 0, + ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, _("This will remove the folder " diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/information-dialog.c balsa/src/information-dialog.c --- balsa-ref/src/information-dialog.c 2004-08-07 19:39:48.000000000 +0200 +++ balsa/src/information-dialog.c 2004-08-21 23:20:25.000000000 +0200 @@ -27,6 +27,10 @@ #include "config.h" #include +#if defined(ENABLE_TOUCH_UI) +#include +#include +#endif #include "libbalsa.h" #include "balsa-app.h" @@ -43,6 +47,9 @@ const char *msg); static void balsa_information_stderr(LibBalsaInformationType type, const char *msg); +#if defined(ENABLE_TOUCH_UI) +static void balsa_information_infoprint(GtkWindow *parent, const char *msg); +#endif /* ENABLE_TOUCH_UI */ /* Handle button clicks in the warning window */ static void @@ -97,6 +104,11 @@ break; case BALSA_INFORMATION_SHOW_BAR: balsa_information_bar(parent, type, show_msg); +#if defined(ENABLE_TOUCH_UI) + /* We show as infoprints extactly the kind of information we + * would show in the status bar in the ordinary build. */ + balsa_information_infoprint(parent, show_msg); +#endif /* ENABLE_TOUCH_UI */ break; case BALSA_INFORMATION_SHOW_STDERR: balsa_information_stderr(type, show_msg); @@ -172,6 +184,7 @@ * the message string. */ messagebox = gtk_message_dialog_new(GTK_WINDOW(parent), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, message_type, GTK_BUTTONS_CLOSE, "%s", msg); @@ -219,6 +232,7 @@ information_dialog = gtk_dialog_new_with_buttons(_("Information - Balsa"), parent, + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLEAR, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, @@ -319,3 +333,31 @@ } fprintf(stderr, "%s\n", msg); } + +#if defined(ENABLE_TOUCH_UI) +static void +gpe_popup_infoprint (Display *dpy, const char *s) +{ + Window w; + static Atom infoprint_atom; + + if (infoprint_atom == None) + infoprint_atom = XInternAtom (dpy, "_GPE_INFOPRINT", False); + + w = XGetSelectionOwner (dpy, infoprint_atom); + if (w != None) + { + XChangeProperty (dpy, w, infoprint_atom, XA_STRING, 8, + PropModeReplace, s, strlen (s)); + } + /* else infoprints not available */ +} + +static void +balsa_information_infoprint(GtkWindow *parent, const char *msg) +{ + Display *display = gdk_x11_get_default_xdisplay(); + gpe_popup_infoprint(display, msg); +} + +#endif /* ENABLE_TOUCH_UI */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/mailbox-conf.c balsa/src/mailbox-conf.c --- balsa-ref/src/mailbox-conf.c 2004-08-05 23:05:52.000000000 +0200 +++ balsa/src/mailbox-conf.c 2004-08-29 23:28:22.000000000 +0200 @@ -86,7 +86,7 @@ GtkWidget *remember; GtkWidget *password; GtkWidget *folderpath; - GtkWidget *enable_persistent; + GtkWidget *enable_persistent, *has_bugs; BalsaServerConf bsc; } imap; @@ -346,7 +346,9 @@ } if (LIBBALSA_IS_MAILBOX_LOCAL(mailbox)) { - ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), 0, + ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("This will remove the mailbox " @@ -367,8 +369,10 @@ NULL); } else if (LIBBALSA_IS_MAILBOX_IMAP(mailbox) && !mailbox->config_prefix) { /* deleting remote IMAP mailbox in a folder set */ - ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), 0, - GTK_MESSAGE_QUESTION, + ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("This will remove the mailbox " "\"%s\" and all its messages " @@ -387,7 +391,9 @@ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL); } else { /* deleting other remote mailbox */ - ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), 0, + ask = gtk_message_dialog_new(GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("This will remove the mailbox " @@ -516,7 +522,8 @@ GTK_DIALOG(gtk_dialog_new_with_buttons (_("Mailbox Configurator"), GTK_WINDOW(balsa_app.main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, ok_button_name, GTK_RESPONSE_OK, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL)); @@ -649,6 +656,11 @@ (GTK_TOGGLE_BUTTON(mcw->mb_data.imap.enable_persistent), TRUE); #endif + if(libbalsa_imap_server_has_bug(LIBBALSA_IMAP_SERVER(server), + ISBUG_FETCH)) + gtk_toggle_button_set_active + (GTK_TOGGLE_BUTTON(mcw->mb_data.imap.has_bugs), + TRUE); if(!server->remember_passwd) gtk_widget_set_sensitive(GTK_WIDGET(mcw->mb_data.imap.password), FALSE); @@ -792,6 +804,10 @@ gtk_toggle_button_get_active GTK_TOGGLE_BUTTON(mcw->mb_data.imap.enable_persistent)); #endif + libbalsa_imap_server_set_bug + (LIBBALSA_IMAP_SERVER(server), ISBUG_FETCH, + gtk_toggle_button_get_active + GTK_TOGGLE_BUTTON(mcw->mb_data.imap.has_bugs)); g_signal_connect(G_OBJECT(server), "get-password", G_CALLBACK(ask_password), mailbox); @@ -1086,7 +1102,7 @@ advanced = balsa_server_conf_get_advanced_widget(&mcw->mb_data.pop3.bsc, - NULL, 1); + NULL, 2); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced, gtk_label_new_with_mnemonic(_("_Advanced"))); /* toggle for apop */ @@ -1196,6 +1212,9 @@ balsa_server_conf_add_checkbox(&mcw->mb_data.imap.bsc, _("Enable _persistent cache")); #endif + mcw->mb_data.imap.has_bugs = + balsa_server_conf_add_checkbox(&mcw->mb_data.imap.bsc, + _("Enable _bug workarounds")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), advanced, gtk_label_new_with_mnemonic(_("_Advanced"))); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/mailbox-node.c balsa/src/mailbox-node.c --- balsa-ref/src/mailbox-node.c 2004-08-05 23:02:43.000000000 +0200 +++ balsa/src/mailbox-node.c 2004-08-27 19:15:24.000000000 +0200 @@ -216,6 +216,13 @@ g_free(mn->dir); mn->dir = NULL; g_free(mn->config_prefix); mn->config_prefix = NULL; + if (mn->server) { + g_signal_handlers_disconnect_matched(mn->server, + G_SIGNAL_MATCH_DATA, 0, + (GQuark) 0, NULL, NULL, mn); + mn->server = NULL; + } + G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(object)); } @@ -349,11 +356,12 @@ imap_scan_attach_mailbox(BalsaMailboxNode * mbnode, imap_scan_item * isi) { LibBalsaMailboxImap *m; + + g_signal_connect(G_OBJECT(mbnode), "show-prop-dialog", + G_CALLBACK(folder_conf_imap_sub_node), NULL); if (LIBBALSA_IS_MAILBOX_IMAP(mbnode->mailbox)) /* it already has a mailbox */ return FALSE; - g_signal_connect(G_OBJECT(mbnode), "show-prop-dialog", - G_CALLBACK(folder_conf_imap_sub_node), NULL); m = LIBBALSA_MAILBOX_IMAP(libbalsa_mailbox_imap_new()); libbalsa_mailbox_remote_set_server(LIBBALSA_MAILBOX_REMOTE(m), mbnode->server); @@ -546,8 +554,8 @@ G_CALLBACK(folder_conf_imap_node), NULL); g_signal_connect(G_OBJECT(folder), "append-subtree", G_CALLBACK(imap_dir_cb), NULL); - g_signal_connect(G_OBJECT(folder->server), "get-password", - G_CALLBACK(ask_password), NULL); + libbalsa_server_connect_signals(folder->server, + G_CALLBACK(ask_password), NULL); balsa_mailbox_node_load_config(folder, prefix); folder->dir = gnome_config_get_string("Directory"); @@ -1069,6 +1077,9 @@ LibBalsaMailbox *mailbox; GtkType type; gchar* url; +#if defined(ENABLE_TOUCH_UI) + gboolean opened = FALSE; +#endif /* ENABLE_TOUCH_UI */ if(root == NULL) return NULL; url = g_strconcat("file://", path, NULL); @@ -1109,8 +1120,18 @@ g_free(url); /* no type checking, parent is NULL for root */ mbnode->parent = root; +#if defined(ENABLE_TOUCH_UI) + opened = libbalsa_mailbox_open(mbnode->mailbox, NULL); /* ignore errors */ + if(opened) {/* scan for unread */ + mbnode->mailbox->msg_tree = g_node_new(NULL); + libbalsa_mailbox_local_load_messages(mbnode->mailbox, 0); + } +#endif /* ENABLE_TOUCH_UI */ load_mailbox_view(mbnode); balsa_mblist_mailbox_node_append(root, mbnode); +#if defined(ENABLE_TOUCH_UI) + if(opened) libbalsa_mailbox_close(mbnode->mailbox, FALSE); +#endif /* ENABLE_TOUCH_UI */ return mbnode; } @@ -1160,6 +1181,7 @@ BalsaMailboxNode *parent; const gchar *basename; gchar *url = libbalsa_imap_url(root->server, isi->fn); + LibBalsaMailbox *mailbox = NULL; mbnode = balsa_find_url(url); if (mbnode) { @@ -1172,6 +1194,8 @@ return mbnode; } g_object_unref(mbnode); + mailbox = special->mailbox; + g_object_ref(mailbox); g_object_unref(special); } g_free(url); @@ -1185,6 +1209,7 @@ g_free(parent_name); mbnode = balsa_mailbox_node_new_imap_node(root->server, isi->fn); + mbnode->mailbox = mailbox; basename = strrchr(isi->fn, delim); if (!basename) basename = isi->fn; diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/main.c balsa/src/main.c --- balsa-ref/src/main.c 2004-08-06 17:02:26.000000000 +0200 +++ balsa/src/main.c 2004-08-21 23:28:10.000000000 +0200 @@ -61,12 +61,12 @@ #include #endif -#ifdef BALSA_USE_THREADS -#include "threads.h" - /* we force expunge now and then so that mailboxes do not grow too * large. This is overriden by "do not expunge on close" setting. */ -#define EXPUNGE_PERIOD_HOURS 26 +#define EXPUNGE_UNUSED_MIN 120 + +#ifdef BALSA_USE_THREADS +#include "threads.h" /* Globals for Thread creation, messaging, pipe I/O */ pthread_t get_mail_thread; @@ -88,8 +88,8 @@ #endif /* BALSA_USE_THREADS */ static void balsa_init(int argc, char **argv); -static void config_init(void); -static void mailboxes_init(void); +static void config_init(gboolean check_only); +static void mailboxes_init(gboolean check_only); static void balsa_cleanup(void); static gint balsa_kill_session(GnomeClient * client, gpointer client_data); static gint balsa_save_session(GnomeClient * client, gint phase, @@ -106,7 +106,7 @@ */ static gchar *cmd_line_open_mailboxes; static gboolean cmd_check_mail_on_startup, - cmd_open_unread_mailbox, cmd_open_inbox; + cmd_open_unread_mailbox, cmd_open_inbox, cmd_get_stats; /* opt_attach_list: list of attachments */ static GSList* opt_attach_list = NULL; @@ -144,6 +144,12 @@ if (cmd_open_inbox) GNOME_Balsa_Application_openInbox (app, &ev); + if (cmd_get_stats) { + CORBA_long unread = 0, unsent = 0; + GNOME_Balsa_Application_getStats (app, &unread, &unsent, &ev); + printf("Unread: %ld Unsent: %ld\n", (long)unread, (long)unsent); + } + if (cmd_line_open_mailboxes) GNOME_Balsa_Application_openMailbox (app, cmd_line_open_mailboxes, @@ -217,6 +223,9 @@ {"open-inbox", 'i', POPT_ARG_NONE, &(cmd_open_inbox), 0, N_("Opens default Inbox on startup"), NULL}, + {"get-stats", 's', POPT_ARG_NONE, + &(cmd_get_stats), 0, + N_("Prints number unread and unsent messages"), NULL}, {"debug-pop", 'd', POPT_ARG_NONE, &PopDebug, 0, N_("Debug POP3 connection"), NULL}, {"debug-imap", 'D', POPT_ARG_NONE, &ImapDebug, 0, @@ -290,19 +299,19 @@ } static void -config_init(void) +config_init(gboolean check_only) { - while(!config_load()) { + while(!config_load() && !check_only) { balsa_init_begin(); config_defclient_save(); } } static void -mailboxes_init(void) +mailboxes_init(gboolean check_only) { check_special_mailboxes(); - if (!balsa_app.inbox) { + if (!balsa_app.inbox && !check_only) { g_warning("*** error loading mailboxes\n"); balsa_init_begin(); config_defclient_save(); @@ -396,6 +405,26 @@ return FALSE; } +void balsa_get_stats(long *unread, long *unsent); +void +balsa_get_stats(long *unread, long *unsent) +{ + + if(balsa_app.inbox && libbalsa_mailbox_open(balsa_app.inbox, NULL) ) { + /* set threading type to load messages */ + gdk_threads_enter(); + libbalsa_mailbox_set_threading(balsa_app.inbox, + balsa_app.inbox->view->threading_type); + gdk_threads_leave(); + *unread = balsa_app.inbox->unread_messages; + libbalsa_mailbox_close(balsa_app.inbox, FALSE); + } else *unread = -1; + if(balsa_app.draftbox && libbalsa_mailbox_open(balsa_app.outbox, NULL)){ + *unsent = libbalsa_mailbox_total_messages(balsa_app.outbox); + libbalsa_mailbox_close(balsa_app.outbox, FALSE); + } else *unsent = -1; +} + /* scan_mailboxes: this is an idle handler. Expands subtrees. */ @@ -452,9 +481,11 @@ g_return_val_if_fail(mbnode, FALSE); gtk_tree_model_get(model, iter, 0, &mbnode, -1); - if (mbnode->mailbox && libbalsa_mailbox_is_open(mbnode->mailbox)) - libbalsa_mailbox_sync_storage(mbnode->mailbox, TRUE); - + if (mbnode->mailbox && libbalsa_mailbox_is_open(mbnode->mailbox)) { + time_t tm = time(NULL); + if(tm-mbnode->last_use > EXPUNGE_UNUSED_MIN*60) + libbalsa_mailbox_sync_storage(mbnode->mailbox, TRUE); + } g_object_unref(mbnode); return FALSE; @@ -468,8 +499,8 @@ if(!balsa_app.expunge_on_close) return TRUE; #endif - libbalsa_message(LIBBALSA_INFORMATION_MESSAGE, - _("Compressing mail folders...")); + libbalsa_information(LIBBALSA_INFORMATION_MESSAGE, + _("Compressing mail folders...")); /* make sure it is shown before we continue */ gdk_threads_enter(); gtk_tree_model_foreach(GTK_TREE_MODEL(balsa_app.mblist_tree_store), @@ -536,7 +567,8 @@ libbalsa_filters_set_filter_list(&balsa_app.filters); /* checking for valid config files */ - config_init(); + config_init(cmd_get_stats); + libbalsa_mailbox_view_table = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify) g_free, @@ -561,7 +593,14 @@ /* load mailboxes */ config_load_sections(); - mailboxes_init(); + mailboxes_init(cmd_get_stats); + + if(cmd_get_stats) { + long unread, unsent; + balsa_get_stats(&unread, &unsent); + printf("Unread: %ld Unsent: %ld\n", unread, unsent); + exit(0); + } /* session management */ client = gnome_master_client(); @@ -604,8 +643,7 @@ g_idle_add((GSourceFunc) scan_mailboxes_idle_cb, NULL); - g_timeout_add(EXPUNGE_PERIOD_HOURS*3600*1000, - (GSourceFunc) periodic_expunge_cb, NULL); + g_timeout_add(1801*1000, (GSourceFunc) periodic_expunge_cb, NULL); gdk_threads_enter(); gtk_main(); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/main-window.c balsa/src/main-window.c --- balsa-ref/src/main-window.c 2004-08-08 14:55:33.000000000 +0200 +++ balsa/src/main-window.c 2004-08-31 22:47:21.000000000 +0200 @@ -178,8 +178,10 @@ static void store_address_cb(GtkWidget * widget, gpointer data); #if defined(ENABLE_TOUCH_UI) static void sort_change_cb(GtkWidget * widget, gpointer data); +static void toggle_order_cb(GtkWidget * widget, gpointer data); static void balsa_window_set_sort_menu(BalsaWindow *window, - LibBalsaMailboxSortFields col); + LibBalsaMailboxSortFields col, + LibBalsaMailboxSortType order); #endif /* ENABLE_TOUCH_UI */ static void wrap_message_cb(GtkWidget * widget, gpointer data); static void show_no_headers_cb(GtkWidget * widget, gpointer data); @@ -890,15 +892,11 @@ GNOMEUIINFO_RADIOITEM_DATA (N_("By S_ubject"), N_("Subject order"), sort_change_cb, GINT_TO_POINTER(LB_MAILBOX_SORT_SUBJECT), NULL), -#define VIEW_SORT_DATE_POS 3 - GNOMEUIINFO_RADIOITEM_DATA - (N_("By _Date"), N_("By sending date"), sort_change_cb, - GINT_TO_POINTER(LB_MAILBOX_SORT_DATE), NULL), -#define VIEW_SORT_SIZE_POS 4 +#define VIEW_SORT_SIZE_POS 3 GNOMEUIINFO_RADIOITEM_DATA (N_("By Si_ze"), N_("By message size"), sort_change_cb, GINT_TO_POINTER(LB_MAILBOX_SORT_SIZE), NULL), -#define VIEW_SORT_THREAD_POS 5 +#define VIEW_SORT_THREAD_POS 4 GNOMEUIINFO_RADIOITEM_DATA (N_("_Threaded"), N_("Use message threading"), sort_change_cb, GINT_TO_POINTER(LB_MAILBOX_SORT_THREAD), NULL), @@ -906,6 +904,11 @@ }; static GnomeUIInfo tu_view_sort_menu[] = { +#define MENU_VIEW_SORT_DESCENDING_POS 0 + GNOMEUIINFO_TOGGLEITEM_DATA + (N_("_Descending"), N_("Sort in a descending order"), + toggle_order_cb, NULL, NULL), + GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_RADIOLIST(tu_sort_l_menu), GNOMEUIINFO_END }; @@ -1061,7 +1064,7 @@ GNOMEUIINFO_ITEM_STOCK(N_("_Manage..."), N_("Manage filters"), filter_dlg_cb, GTK_STOCK_PROPERTIES), #define TOOLS_SELECT_FILTER_POS 1 - GNOMEUIINFO_ITEM_STOCK(N_("_Select _Filters"), + GNOMEUIINFO_ITEM_STOCK(N_("_Select Filters"), N_("Select filters to be applied automatically to current mailbox"), filter_run_cb, GTK_STOCK_PROPERTIES), GNOMEUIINFO_ITEM_STOCK(N_("_Export Filters"), @@ -1249,7 +1252,7 @@ /* Standard buttons; "" means a separator. */ static const gchar* main_toolbar[] = { #if defined(ENABLE_TOUCH_UI) - BALSA_PIXMAP_RECEIVE, + BALSA_PIXMAP_SEND_RECEIVE, "", BALSA_PIXMAP_NEW, BALSA_PIXMAP_REPLY, @@ -1655,7 +1658,6 @@ &tu_sort_l_menu[VIEW_SORT_MSGNO_POS], &tu_sort_l_menu[VIEW_SORT_SENDER_POS], &tu_sort_l_menu[VIEW_SORT_SUBJECT_POS], - &tu_sort_l_menu[VIEW_SORT_DATE_POS], &tu_sort_l_menu[VIEW_SORT_MSGNO_POS], &tu_sort_l_menu[VIEW_SORT_SIZE_POS], &tu_sort_l_menu[VIEW_SORT_THREAD_POS], @@ -1712,7 +1714,8 @@ if (mailbox) { #if defined(ENABLE_TOUCH_UI) balsa_window_set_sort_menu(window, - libbalsa_mailbox_get_sort_field(mailbox)); + libbalsa_mailbox_get_sort_field(mailbox), + libbalsa_mailbox_get_sort_type(mailbox)); #else balsa_window_set_threading_menu(window, libbalsa_mailbox_get_threading_type @@ -2609,6 +2612,7 @@ progress_dialog_bar = gtk_progress_bar_new(); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(progress_dialog)->vbox), progress_dialog_bar, FALSE, FALSE, 0); + gtk_window_set_default_size(GTK_WINDOW(progress_dialog), 250, 100); gtk_widget_show_all(progress_dialog); } #endif @@ -2674,11 +2678,13 @@ { check_new_messages_real(widget, data, TYPE_CALLBACK); #if ENABLE_ESMTP - libbalsa_process_queue(balsa_app.outbox, balsa_app.smtp_server, + libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, + balsa_app.smtp_server, balsa_app.smtp_authctx, balsa_app.smtp_tls_mode, balsa_app.debug); #else - libbalsa_process_queue(balsa_app.outbox, balsa_app.debug); + libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, + balsa_app.debug); #endif } @@ -2730,11 +2736,13 @@ send_outbox_messages_cb(GtkWidget * widget, gpointer data) { #if ENABLE_ESMTP - libbalsa_process_queue(balsa_app.outbox, balsa_app.smtp_server, + libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, + balsa_app.smtp_server, balsa_app.smtp_authctx, balsa_app.smtp_tls_mode, balsa_app.debug); #else - libbalsa_process_queue(balsa_app.outbox, balsa_app.debug); + libbalsa_process_queue(balsa_app.outbox, balsa_find_sentbox_by_url, + balsa_app.debug); #endif } @@ -3331,32 +3339,49 @@ #if defined(ENABLE_TOUCH_UI) static void -balsa_window_set_sort_menu(BalsaWindow *window, LibBalsaMailboxColumn col) +balsa_window_set_sort_menu(BalsaWindow *window, + LibBalsaMailboxSortFields col, + LibBalsaMailboxSortType order) { int pos; + GtkWidget *w; + switch(col) { + case LB_MAILBOX_SORT_DATE: case LB_MAILBOX_SORT_NO: pos = VIEW_SORT_MSGNO_POS; break; case LB_MAILBOX_SORT_SENDER: pos = VIEW_SORT_SENDER_POS; break; case LB_MAILBOX_SORT_SUBJECT: pos = VIEW_SORT_SUBJECT_POS; break; - case LB_MAILBOX_SORT_DATE: pos = VIEW_SORT_DATE_POS; break; case LB_MAILBOX_SORT_SIZE: pos = VIEW_SORT_SIZE_POS; break; case LB_MAILBOX_SORT_THREAD: pos = VIEW_SORT_THREAD_POS; break; default: return; } - g_signal_handlers_block_by_func(G_OBJECT(tu_sort_l_menu[pos].widget), - tu_sort_l_menu[pos].moreinfo, + w = tu_sort_l_menu[pos].widget; + g_signal_handlers_block_by_func(G_OBJECT(w), + tu_sort_l_menu[pos].moreinfo, window); - gtk_check_menu_item_set_active - (GTK_CHECK_MENU_ITEM(tu_sort_l_menu[pos].widget), TRUE); - g_signal_handlers_unblock_by_func(G_OBJECT(tu_sort_l_menu[pos].widget), + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), TRUE); + g_signal_handlers_unblock_by_func(G_OBJECT(w), tu_sort_l_menu[pos].moreinfo, window); + w = tu_view_sort_menu[MENU_VIEW_SORT_DESCENDING_POS].widget; + g_signal_handlers_block_by_func + (G_OBJECT(w), + tu_view_sort_menu[MENU_VIEW_SORT_DESCENDING_POS].moreinfo, + window); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), + order == LB_MAILBOX_SORT_TYPE_DESC); + g_signal_handlers_unblock_by_func + (G_OBJECT(w), + tu_view_sort_menu[MENU_VIEW_SORT_DESCENDING_POS].moreinfo, + window); + gtk_widget_set_sensitive(w, pos != VIEW_SORT_THREAD_POS); } static void sort_change_cb(GtkWidget * widget, gpointer data) { LibBalsaMailboxSortFields key; + LibBalsaMailboxSortType order; GtkWidget *bindex; LibBalsaMailbox *mailbox; gint col; @@ -3371,7 +3396,7 @@ key = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), GNOMEUIINFO_KEY_UIDATA)); mailbox = BALSA_INDEX(bindex)->mailbox_node->mailbox; - libbalsa_mailbox_set_sort_field(mailbox, key); + switch(key) { case LB_MAILBOX_SORT_NO: col = LB_MBOX_MSGNO_COL; break; case LB_MAILBOX_SORT_SENDER: col = LB_MBOX_FROM_COL; break; @@ -3379,18 +3404,60 @@ case LB_MAILBOX_SORT_DATE: col = LB_MBOX_DATE_COL; break; case LB_MAILBOX_SORT_SIZE: col = LB_MBOX_SIZE_COL; break; case LB_MAILBOX_SORT_THREAD: + libbalsa_mailbox_set_sort_field(mailbox, key); balsa_index_set_threading_type(BALSA_INDEX(bindex), LB_MAILBOX_THREADING_JWZ); + gtk_widget_set_sensitive + (tu_view_sort_menu[MENU_VIEW_SORT_DESCENDING_POS].widget, FALSE); return; default: return; } + gtk_widget_set_sensitive + (tu_view_sort_menu[MENU_VIEW_SORT_DESCENDING_POS].widget, TRUE); if(libbalsa_mailbox_get_threading_type(mailbox) != LB_MAILBOX_THREADING_FLAT) balsa_index_set_threading_type(BALSA_INDEX(bindex), LB_MAILBOX_THREADING_FLAT); + order = libbalsa_mailbox_get_sort_type(mailbox); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(mailbox), - col, GTK_SORT_ASCENDING); - } + col, + order == LB_MAILBOX_SORT_TYPE_ASC + ? GTK_SORT_ASCENDING + : GTK_SORT_DESCENDING); +} + +static void +toggle_order_cb(GtkWidget * widget, gpointer data) +{ + LibBalsaMailboxSortType order; + GtkWidget *bindex; + LibBalsaMailbox *mailbox; + gint col; + + bindex = balsa_window_find_current_index(BALSA_WINDOW(data)); + if(!bindex) + return; + mailbox = BALSA_INDEX(bindex)->mailbox_node->mailbox; + order = GTK_CHECK_MENU_ITEM(widget)->active + ? LB_MAILBOX_SORT_TYPE_DESC : LB_MAILBOX_SORT_TYPE_ASC; + + switch(libbalsa_mailbox_get_sort_field(mailbox)) { + case LB_MAILBOX_SORT_NO: col = LB_MBOX_MSGNO_COL; break; + case LB_MAILBOX_SORT_SENDER: col = LB_MBOX_FROM_COL; break; + case LB_MAILBOX_SORT_SUBJECT: col = LB_MBOX_SUBJECT_COL; break; + case LB_MAILBOX_SORT_DATE: col = LB_MBOX_DATE_COL; break; + case LB_MAILBOX_SORT_SIZE: col = LB_MBOX_SIZE_COL; break; + default: + case LB_MAILBOX_SORT_THREAD: + g_warning("This should not be possible"); return; + } + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(mailbox), + col, + order == LB_MAILBOX_SORT_TYPE_ASC + ? GTK_SORT_ASCENDING + : GTK_SORT_DESCENDING); +} + #endif /* ENABLE_TOUCH_UI */ static void wrap_message_cb(GtkWidget * widget, gpointer data) @@ -3606,6 +3673,7 @@ GtkWidget* vbox, *dia = gtk_dialog_new_with_buttons(_("Search mailbox"), GTK_WINDOW(window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_HELP, GTK_RESPONSE_HELP, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/Makefile.am balsa/src/Makefile.am --- balsa-ref/src/Makefile.am 2004-07-10 01:40:21.000000000 +0200 +++ balsa/src/Makefile.am 2004-08-21 23:20:18.000000000 +0200 @@ -66,6 +66,10 @@ balsa_SOURCES = $(balsa_BASE_SRCLIST) +# see http://sources.redhat.com/automake/dependencies.html +BUILT_SOURCES = Balsa.h + + EXTRA_DIST = \ Balsa.idl diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/message-window.c balsa/src/message-window.c --- balsa-ref/src/message-window.c 2004-08-02 18:17:54.000000000 +0200 +++ balsa/src/message-window.c 2004-09-09 00:34:14.000000000 +0200 @@ -321,6 +321,19 @@ /* Standard buttons; "" means a separator. */ static const gchar* message_toolbar[] = { +#if defined(ENABLE_TOUCH_UI) + BALSA_PIXMAP_NEXT_UNREAD, + "", + BALSA_PIXMAP_REPLY, + BALSA_PIXMAP_REPLY_ALL, + BALSA_PIXMAP_FORWARD, + "", + BALSA_PIXMAP_PRINT, + "", + BALSA_PIXMAP_TRASH, + "", + GTK_STOCK_CLOSE +#else /* ENABLE_TOUCH_UI */ BALSA_PIXMAP_NEXT_UNREAD, "", BALSA_PIXMAP_REPLY, @@ -334,7 +347,8 @@ "", BALSA_PIXMAP_PRINT, "", - BALSA_PIXMAP_TRASH, + BALSA_PIXMAP_TRASH +#endif /* ENEBLE_TOUCH_UI */ }; /* Create the toolbar model for the message window's toolbar. diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/pref-manager.c balsa/src/pref-manager.c --- balsa-ref/src/pref-manager.c 2004-08-02 23:28:23.000000000 +0200 +++ balsa/src/pref-manager.c 2004-08-26 18:44:04.000000000 +0200 @@ -23,6 +23,9 @@ #include "config.h" #include +#ifdef HAVE_SQLITE +#include "address-book-gpe.h" +#endif #include "balsa-app.h" #include "pref-manager.h" #include "mailbox-conf.h" @@ -123,7 +126,9 @@ GtkWidget *font_picker2; +#if !defined(ENABLE_TOUCH_UI) GtkWidget *date_format; +#endif GtkWidget *selected_headers; @@ -138,7 +143,9 @@ gint threading_style_index; /* quote regex */ +#if !defined(ENABLE_TOUCH_UI) GtkWidget *quote_pattern; +#endif /* wrap incoming text/plain */ GtkWidget *browse_wrap; @@ -384,7 +391,6 @@ GTK_WINDOW(active_win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, - GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_HELP, GTK_RESPONSE_HELP, NULL); @@ -536,11 +542,13 @@ /* arp */ g_signal_connect(G_OBJECT(pui->quote_str), "changed", G_CALLBACK(properties_modified_cb), property_box); +#if !defined(ENABLE_TOUCH_UI) g_signal_connect(G_OBJECT (gnome_entry_gtk_entry (GNOME_ENTRY(pui->quote_pattern))), "changed", G_CALLBACK(properties_modified_cb), property_box); +#endif /* multipart/alternative */ g_signal_connect(G_OBJECT(pui->display_alt_plain), "toggled", @@ -590,8 +598,10 @@ /* Date format */ +#if !defined(ENABLE_TOUCH_UI) g_signal_connect(G_OBJECT(pui->date_format), "changed", G_CALLBACK(properties_modified_cb), property_box); +#endif /* Selected headers */ g_signal_connect(G_OBJECT(pui->selected_headers), "changed", @@ -660,9 +670,11 @@ { gint i; GtkWidget *balsa_window; +#if !defined(ENABLE_TOUCH_UI) GtkWidget *entry_widget; - GtkWidget *menu_item; const gchar* tmp; +#endif + GtkWidget *menu_item; /* * identity page @@ -800,10 +812,12 @@ balsa_app.subject_font = g_strdup(gtk_entry_get_text(GTK_ENTRY(pui->subject_font))); +#if !defined(ENABLE_TOUCH_UI) g_free(balsa_app.quote_regex); entry_widget = gnome_entry_gtk_entry(GNOME_ENTRY(pui->quote_pattern)); tmp = gtk_entry_get_text(GTK_ENTRY(entry_widget)); balsa_app.quote_regex = g_strcompress(tmp); +#endif balsa_app.browse_wrap = GTK_TOGGLE_BUTTON(pui->browse_wrap)->active; /* main window view menu can also toggle balsa_app.browse_wrap @@ -841,9 +855,11 @@ GTK_TOGGLE_BUTTON(pui->spell_check_quoted)->active; /* date format */ +#if !defined(ENABLE_TOUCH_UI) g_free(balsa_app.date_string); balsa_app.date_string = g_strdup(gtk_entry_get_text(GTK_ENTRY(pui->date_format))); +#endif /* selected headers */ g_free(balsa_app.selected_headers); @@ -925,9 +941,11 @@ void set_prefs(void) { +#if !defined(ENABLE_TOUCH_UI) GtkWidget *entry_widget; - unsigned i; gchar* tmp; +#endif + unsigned i; for (i = 0; i < NUM_PWINDOW_MODES; i++) if (balsa_app.pwindow_option == pwindow_type[i]) { @@ -1058,10 +1076,12 @@ /* arp */ gtk_entry_set_text(GTK_ENTRY(pui->quote_str), balsa_app.quote_str); +#if !defined(ENABLE_TOUCH_UI) entry_widget = gnome_entry_gtk_entry(GNOME_ENTRY(pui->quote_pattern)); tmp = g_strescape(balsa_app.quote_regex, NULL); gtk_entry_set_text(GTK_ENTRY(entry_widget), tmp); g_free(tmp); +#endif /* wrap incoming text/plain */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pui->browse_wrap), @@ -1124,9 +1144,11 @@ /* date format */ +#if !defined(ENABLE_TOUCH_UI) if (balsa_app.date_string) gtk_entry_set_text(GTK_ENTRY(pui->date_format), balsa_app.date_string); +#endif /* selected headers */ if (balsa_app.selected_headers) @@ -1200,6 +1222,10 @@ else if (LIBBALSA_IS_ADDRESS_BOOK_LDAP(address_book)) type = "LDAP"; #endif +#if HAVE_SQLITE + else if (LIBBALSA_IS_ADDRESS_BOOK_GPE(address_book)) + type = "GPE"; +#endif else type = _("Unknown"); @@ -1461,7 +1487,7 @@ gtk_box_pack_start(GTK_BOX(hbox), scrolledwindow, TRUE, TRUE, 0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request(scrolledwindow, -1, 150); + gtk_widget_set_size_request(scrolledwindow, -1, 100); pm_page_add_to_size_group(page, scrolledwindow); store = gtk_list_store_new(MS_N_COLUMNS, @@ -1680,6 +1706,7 @@ table = create_table(3, 3, page); pm_group_add(group, table); +#if !defined(ENABLE_TOUCH_UI) label = gtk_label_new(_("Quoted Text Regular Expression")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach(GTK_TABLE(table), label, @@ -1689,7 +1716,7 @@ pui->quote_pattern = gnome_entry_new("quote-regex-history"); gtk_table_attach(GTK_TABLE(table), pui->quote_pattern, 1, 3, 0, 1, GTK_FILL, 0, 0, 0); - +#endif pui->browse_wrap = gtk_check_button_new_with_label(_("Wrap Incoming Text at:")); gtk_table_attach(GTK_TABLE(table), pui->browse_wrap, @@ -2054,8 +2081,10 @@ table = create_table(2, 2, page); pm_group_add(group, table); +#if !defined(ENABLE_TOUCH_UI) pui->date_format = attach_entry(_("Date encoding (for strftime):"), 0, GTK_TABLE(table)); +#endif pui->selected_headers = attach_entry(_("Selected headers:"), 1, GTK_TABLE(table)); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/print.c balsa/src/print.c --- balsa-ref/src/print.c 2004-07-19 10:03:02.000000000 +0200 +++ balsa/src/print.c 2004-08-24 23:06:55.000000000 +0200 @@ -662,7 +662,9 @@ } dialog = - gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, + gtk_message_dialog_new(NULL, + GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("Preparing an HTML part, " "which must start on a new page.\n" @@ -1552,15 +1554,11 @@ gtk_label_set_text(GTK_LABEL(fi->font_status), _("Font available for printing")); else { - GnomeFont* fncl = - gnome_font_find_closest_from_full_name(*fi->font_name); - gchar* fn = gnome_font_get_full_name(fncl); gchar *msg = - g_strdup_printf(_("Font not available for printing. " - "Closest: %s"), fn); + g_strdup_printf(_("Font not available for printing.")); gtk_label_set_markup(GTK_LABEL(fi->font_status), msg); - g_free(fn); g_free(msg); + g_free(msg); } } /* @@ -1623,6 +1621,7 @@ /* * creates the print dialog, and adds a page for fonts */ +static void common_info_setup(CommonInfo * ci); static GtkWidget * print_dialog(CommonInfo * ci) { @@ -1637,6 +1636,8 @@ dialog = BALSA_GNOME_PRINT_DIALOG_NEW(ci->master, _("Print message"), GNOME_PRINT_DIALOG_COPIES); + ci->dialog = dialog; + common_info_setup(ci); gtk_window_set_wmclass(GTK_WINDOW(dialog), "print", "Balsa"); dlgVbox = GTK_DIALOG(dialog)->vbox; childList = gtk_container_get_children(GTK_CONTAINER(dlgVbox)); @@ -1683,11 +1684,12 @@ fi->common_info = ci; fi->font = find_font(*font_name); if (!fi->font) - balsa_information(LIBBALSA_INFORMATION_WARNING, - _("Balsa could not find font \"%s\".\n" - "Use the \"Fonts\" page on the " - "\"Print message\" dialog to change it."), - *fi->font_name); + balsa_information_parented + (GTK_WINDOW(ci->dialog), LIBBALSA_INFORMATION_WARNING, + _("Balsa could not find font \"%s\".\n" + "Use the \"Fonts\" page on the " + "\"Print message\" dialog to change it."), + *fi->font_name); } static void @@ -1837,7 +1839,6 @@ (GDestroyNotify) common_info_destroy); ci->parent_object = parent_object; - common_info_setup(ci); ci->message = msg; if (!msg->mailbox) { /* temporary message from the compose window */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/save-restore.c balsa/src/save-restore.c --- balsa-ref/src/save-restore.c 2004-08-08 14:55:34.000000000 +0200 +++ balsa/src/save-restore.c 2004-08-27 19:15:24.000000000 +0200 @@ -505,10 +505,14 @@ mailbox = libbalsa_mailbox_new_from_config(prefix); if (mailbox == NULL) return FALSE; - if (LIBBALSA_IS_MAILBOX_REMOTE(mailbox)) - g_signal_connect(G_OBJECT(LIBBALSA_MAILBOX_REMOTE_SERVER(mailbox)), - "get-password", G_CALLBACK(ask_password), - mailbox); + if (LIBBALSA_IS_MAILBOX_REMOTE(mailbox)) { + LibBalsaServer *server = LIBBALSA_MAILBOX_REMOTE_SERVER(mailbox); + libbalsa_server_connect_signals(server, + G_CALLBACK(ask_password), mailbox); + g_signal_connect_swapped(server, "set-host", + G_CALLBACK(config_mailbox_update), + mailbox); + } if (LIBBALSA_IS_MAILBOX_POP3(mailbox)) { g_signal_connect(G_OBJECT(mailbox), @@ -561,8 +565,12 @@ g_return_val_if_fail(prefix != NULL, FALSE); - if( (folder = balsa_mailbox_node_new_from_config(prefix)) ) + if( (folder = balsa_mailbox_node_new_from_config(prefix)) ) { + g_signal_connect_swapped(folder->server, "set-host", + G_CALLBACK(config_folder_update), + folder); balsa_mblist_mailbox_node_append(NULL, folder); + } return folder != NULL; } /* config_folder_init */ @@ -643,7 +651,7 @@ /* ... window sizes */ balsa_app.mw_width = gnome_config_get_int("MainWindowWidth=640"); balsa_app.mw_height = gnome_config_get_int("MainWindowHeight=480"); - balsa_app.mblist_width = gnome_config_get_int("MailboxListWidth=100"); + balsa_app.mblist_width = gnome_config_get_int("MailboxListWidth=130"); /* sendmsg window sizes */ balsa_app.sw_width = gnome_config_get_int("SendMsgWindowWidth=640"); balsa_app.sw_height = gnome_config_get_int("SendMsgWindowHeight=480"); diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/sendmsg-window.c balsa/src/sendmsg-window.c --- balsa-ref/src/sendmsg-window.c 2004-08-08 21:22:20.000000000 +0200 +++ balsa/src/sendmsg-window.c 2004-09-11 00:20:01.000000000 +0200 @@ -49,6 +49,7 @@ #include "libbalsa.h" #include "misc.h" +#include "send.h" #include "balsa-app.h" #include "balsa-message.h" @@ -715,6 +716,7 @@ g_object_set_data(G_OBJECT(parent), BALSA_SENDMSG_ADDRESS_BOOK_KEY, NULL); gtk_widget_set_sensitive(GTK_WIDGET(address_entry), TRUE); + libbalsa_address_entry_fill_input(address_entry); } static gint @@ -783,6 +785,8 @@ g_signal_handler_disconnect(G_OBJECT(balsa_app.main_window), bsmsg->delete_sig_id); + g_signal_handler_disconnect(G_OBJECT(balsa_app.main_window), + bsmsg->identities_changed_id); if(balsa_app.debug) g_message("balsa_sendmsg_destroy()_handler: Start."); if (bsmsg->orig_message) { @@ -1428,6 +1432,7 @@ attach = gnome_icon_list_get_icon_data(ilist, num); extbody_dialog = gtk_message_dialog_new(GTK_WINDOW(parent), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, @@ -1566,8 +1571,11 @@ event_button = 0; event_time = gtk_get_current_event_time(); } + g_object_ref(menu); + gtk_object_sink(GTK_OBJECT(menu)); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button, event_time); + g_object_unref(menu); return TRUE; } @@ -2133,15 +2141,15 @@ g_signal_connect_swapped(G_OBJECT(bsmsg->to[1]), "changed", G_CALLBACK(sendmsg_window_set_title), bsmsg); - /* Subject: */ - create_string_entry(table, _("S_ubject:"), 2, bsmsg->subject); - g_signal_connect_swapped(G_OBJECT(bsmsg->subject[1]), "changed", - G_CALLBACK(sendmsg_window_set_title), bsmsg); /* cc: */ - create_email_entry(table, _("Cc:"), 3, GNOME_STOCK_BOOK_YELLOW, + create_email_entry(table, _("Cc:"), 2, GNOME_STOCK_BOOK_YELLOW, bsmsg, bsmsg->cc, &bsmsg->cc_info, 0, -1); + /* Subject: */ + create_string_entry(table, _("S_ubject:"), 3, bsmsg->subject); + g_signal_connect_swapped(G_OBJECT(bsmsg->subject[1]), "changed", + G_CALLBACK(sendmsg_window_set_title), bsmsg); /* bcc: */ create_email_entry(table, _("Bcc:"), 4, GNOME_STOCK_BOOK_GREEN, bsmsg, bsmsg->bcc, @@ -2298,7 +2306,8 @@ gtk_container_add(GTK_CONTAINER(table), bsmsg->text); g_signal_connect(G_OBJECT(bsmsg->text), "drag_data_received", G_CALLBACK(drag_data_quote), bsmsg); - gtk_drag_dest_set(GTK_WIDGET(bsmsg->text), GTK_DEST_DEFAULT_ALL, + /* GTK_DEST_DEFAULT_ALL in drag_set would trigger bug 150141 */ + gtk_drag_dest_set(GTK_WIDGET(bsmsg->text), 0, drop_types, ELEMENTS(drop_types), GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); @@ -3005,7 +3014,7 @@ } static void -bsmsg_identites_changed_cb(BalsaSendmsg *bsmsg) +bsmsg_identities_changed_cb(BalsaSendmsg *bsmsg) { GtkWidget *toolbar = balsa_toolbar_get_from_gnome_app(GNOME_APP(bsmsg->window)); @@ -3091,8 +3100,10 @@ gnome_app_set_toolbar(GNOME_APP(window), GTK_TOOLBAR(toolbar)); balsa_toolbar_set_button_sensitive(toolbar, BALSA_PIXMAP_IDENTITY, g_list_length(balsa_app.identities)>1); - g_signal_connect_swapped(balsa_app.main_window, "identities-changed", - (GCallback)bsmsg_identites_changed_cb, bsmsg); + bsmsg->identities_changed_id = + g_signal_connect_swapped(balsa_app.main_window, "identities-changed", + (GCallback)bsmsg_identities_changed_cb, + bsmsg); sw_buffer_set_undo(bsmsg, TRUE, FALSE); bsmsg->ready_widgets[0] = file_menu[MENU_FILE_SEND_POS].widget; @@ -3375,6 +3386,7 @@ GtkWidget * dialog = gtk_dialog_new_with_buttons(_("Choose charset"), GTK_WINDOW(bsmsg->window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_STOCK_CANCEL, @@ -3666,7 +3678,8 @@ message->references = g_list_reverse(message->references); } ctime_r(&bsmsg->orig_message->headers->date, recvtime); - + if(recvtime[0]) /* safety check; remove trailing '\n' */ + recvtime[strlen(recvtime)-1] = '\0'; if (bsmsg->orig_message->message_id) { message->references = g_list_append(message->references, @@ -3832,13 +3845,15 @@ #if ENABLE_ESMTP result = libbalsa_message_send (message, balsa_app.outbox, fcc, - balsa_app.encoding_style, balsa_app.smtp_server, + balsa_app.encoding_style, balsa_find_sentbox_by_url, + balsa_app.smtp_server, (balsa_app.smtp_user && *balsa_app.smtp_user) ? balsa_app.smtp_authctx : NULL, balsa_app.smtp_tls_mode, bsmsg->flow, balsa_app.debug); #else result = libbalsa_message_send(message, balsa_app.outbox, fcc, + balsa_find_sentbox_by_url, balsa_app.encoding_style, bsmsg->flow, balsa_app.debug); #endif @@ -3869,7 +3884,7 @@ case LIBBALSA_MESSAGE_QUEUE_ERROR: msg = _("Message could not be queued in outbox"); break; case LIBBALSA_MESSAGE_SAVE_ERROR: - msg = _("Message could not be saved in senbox"); break; + msg = _("Message could not be saved in sentbox"); break; case LIBBALSA_MESSAGE_SEND_ERROR: msg = _("Message could not be sent"); break; } diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/sendmsg-window.h balsa/src/sendmsg-window.h --- balsa-ref/src/sendmsg-window.h 2004-08-07 00:22:11.000000000 +0200 +++ balsa/src/sendmsg-window.h 2004-09-08 01:10:38.000000000 +0200 @@ -84,6 +84,7 @@ gulong changed_sig_id; gulong delete_range_sig_id; guint wrap_timeout_id; + gulong identities_changed_id; gboolean modified; gboolean flow; /* send format=flowed */ gboolean req_dispnotify; /* send a MDN */ diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/store-address.c balsa/src/store-address.c --- balsa-ref/src/store-address.c 2004-03-27 14:59:38.000000000 +0100 +++ balsa/src/store-address.c 2004-08-21 23:20:25.000000000 +0200 @@ -177,6 +177,7 @@ GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Store Address"), GTK_WINDOW(balsa_app.main_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_SAVE, SA_RESPONSE_SAVE, diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/toolbar-factory.c balsa/src/toolbar-factory.c --- balsa-ref/src/toolbar-factory.c 2004-07-28 13:16:16.000000000 +0200 +++ balsa/src/toolbar-factory.c 2004-08-27 08:50:18.000000000 +0200 @@ -119,8 +119,8 @@ N_("Print current message"), TOOLBAR_BUTTON_TYPE_BUTTON}, {BALSA_PIXMAP_SEND, N_("Send"), N_("Send this message"), TOOLBAR_BUTTON_TYPE_BUTTON}, - {BALSA_PIXMAP_SEND_RECEIVE, N_("Exchange"), - N_("Send and Receive messages"), TOOLBAR_BUTTON_TYPE_BUTTON}, + {BALSA_PIXMAP_SEND_RECEIVE, N_("Send/Check"), + N_("Send and Check for new messages"), TOOLBAR_BUTTON_TYPE_BUTTON}, {BALSA_PIXMAP_ATTACHMENT, N_("Attach"), N_("Add attachments to this message"), TOOLBAR_BUTTON_TYPE_BUTTON}, {BALSA_PIXMAP_SAVE, N_("Save"), diff -ur --exclude-from=exclude-files --new-file balsa-ref/src/toolbar-prefs.c balsa/src/toolbar-prefs.c --- balsa-ref/src/toolbar-prefs.c 2003-09-03 22:34:25.000000000 +0200 +++ balsa/src/toolbar-prefs.c 2004-08-21 23:20:25.000000000 +0200 @@ -135,6 +135,7 @@ customize_widget = gtk_dialog_new_with_buttons(_("Customize Toolbars"), GTK_WINDOW(active_window), + GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_HELP, GTK_RESPONSE_HELP,