diff options
-rw-r--r-- | mail/ChangeLog | 24 | ||||
-rw-r--r-- | mail/component-factory.c | 150 | ||||
-rw-r--r-- | mail/mail-folder-cache.c | 19 | ||||
-rw-r--r-- | mail/mail-local.c | 28 | ||||
-rw-r--r-- | mail/mail-vfolder.c | 109 | ||||
-rw-r--r-- | mail/mail-vfolder.h | 3 |
6 files changed, 237 insertions, 96 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 9f4208cdb6..bc4656abd9 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,27 @@ +2001-10-28 <NotZed@Ximian.com> + + * mail-vfolder.c (mail_vfolder_rename_uri): Implemented. + (mail_vfolder_rename_uri): We do want to check renamed uri's from + vstores. + (mail_vfolder_delete_uri): Same. + (store_folder_renamed): Fix the folder hash at the same time. + + * mail-folder-cache.c (real_flush_updates): Pass the rename event + to vfolder rename uri. + + * mail-local.c (mail_local_folder_reconfigure): Change the store + path to be same as parent + mbox to be full path. + (mls_delete_folder): Change store path to be parent path, and mbox + to be full path. + (mail_local_folder_reconfigure): Fix a leak of tmpname. + + * component-factory.c (xfer_folder): Only do a rename if we have + remove set, cleaned up logic a bit. + (idle_quit): Put the components still active check last last of + all. + (storage_create_folder): IF we have a fragment, use that as part + part for parent. + 2001-10-27 Jeffrey Stedfast <fejj@ximian.com> * mail-format.c (mail_format_get_data_wrapper_text): Allow the diff --git a/mail/component-factory.c b/mail/component-factory.c index d521d97df1..92dfddb79b 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -317,52 +317,96 @@ xfer_folder (EvolutionShellComponent *shell_component, void *closure) { CORBA_Environment ev; - const char *noselect; CamelFolder *source; CamelException ex; GPtrArray *uids; - CamelURL *url; + CamelURL *src, *dst; printf("Renaming folder '%s' to dest '%s' type '%s'\n", source_physical_uri, destination_physical_uri, type); - - url = camel_url_new (destination_physical_uri, NULL); - noselect = url ? camel_url_get_param (url, "noselect") : NULL; - - if (noselect && !g_strcasecmp (noselect, "yes")) { - camel_url_free (url); - GNOME_Evolution_ShellComponentListener_notifyResult (listener, - GNOME_Evolution_ShellComponentListener_UNSUPPORTED_OPERATION, &ev); - return; - } - - camel_url_free (url); - + + CORBA_exception_init (&ev); + if (strcmp (type, "mail") != 0) { GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); return; } + + src = camel_url_new(source_physical_uri, NULL); + if (src == NULL) { + GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + return; + } + + dst = camel_url_new(destination_physical_uri, NULL); + if (dst == NULL) { + camel_url_free(src); + GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + return; + } + + if (camel_url_get_param(dst, "noselect") != NULL) { + camel_url_free(src); + camel_url_free(dst); + GNOME_Evolution_ShellComponentListener_notifyResult (listener, + GNOME_Evolution_ShellComponentListener_UNSUPPORTED_OPERATION, &ev); + return; + } camel_exception_init (&ex); - source = mail_tool_uri_to_folder (source_physical_uri, 0, &ex); - camel_exception_clear (&ex); + + /* If we are really doing a rename, implement it as a rename */ + if (remove && strcmp(src->protocol, dst->protocol) == 0) { + char *sname, *dname; + CamelStore *store; + + if (src->fragment) + sname = src->fragment; + else { + if (src->path && *src->path) + sname = src->path+1; + else + sname = ""; + } + + if (dst->fragment) + dname = dst->fragment; + else { + if (dst->path && *dst->path) + dname = dst->path+1; + else + dname = ""; + } + + store = camel_session_get_store(session, source_physical_uri, &ex); + if (store != NULL) + camel_store_rename_folder(store, sname, dname, &ex); + + if (camel_exception_is_set(&ex)) + GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + } else { + source = mail_tool_uri_to_folder (source_physical_uri, 0, &ex); - CORBA_exception_init (&ev); - if (source) { - xfer_folder_data *xfd; - - xfd = g_new0 (xfer_folder_data, 1); - xfd->remove_source = remove_source; - xfd->source_uri = g_strdup (source_physical_uri); - xfd->listener = CORBA_Object_duplicate (listener, &ev); + if (source) { + xfer_folder_data *xfd; + + xfd = g_new0 (xfer_folder_data, 1); + xfd->remove_source = remove_source; + xfd->source_uri = g_strdup (source_physical_uri); + xfd->listener = CORBA_Object_duplicate (listener, &ev); - uids = camel_folder_get_uids (source); - mail_transfer_messages (source, uids, remove_source, destination_physical_uri, - CAMEL_STORE_FOLDER_CREATE, xfer_folder_done, xfd); - camel_object_unref (CAMEL_OBJECT (source)); - } else - GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + uids = camel_folder_get_uids (source); + mail_transfer_messages (source, uids, remove_source, destination_physical_uri, CAMEL_STORE_FOLDER_CREATE, xfer_folder_done, xfd); + camel_object_unref (CAMEL_OBJECT (source)); + } else + GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); + } + CORBA_exception_free (&ev); + camel_exception_clear (&ex); + + camel_url_free(src); + camel_url_free(dst); } #if 0 @@ -472,7 +516,6 @@ destination_folder_handle_drop (EvolutionShellComponentDndDestinationFolder *des gpointer user_data) { char *tmp, *url, **urls, *in, *inptr, *inend; - char *vfolder_uri = NULL; gboolean retval = FALSE; const char *noselect; CamelFolder *folder; @@ -822,9 +865,6 @@ idle_quit (gpointer user_data) static int shutdown_shutdown = FALSE; if (!shutdown_shutdown) { - if (e_list_length (folder_browser_factory_get_control_list ())) - return TRUE; - if (mail_msg_active(-1)) { /* short sleep? */ return TRUE; @@ -845,6 +885,9 @@ idle_quit (gpointer user_data) storages_hash = NULL; } + if (e_list_length (folder_browser_factory_get_control_list ())) + return TRUE; + gtk_main_quit (); return FALSE; @@ -991,17 +1034,20 @@ storage_create_folder (EvolutionStorage *storage, char *name; CamelURL *url; CamelException ex; - + + /* We could just use 'path' always here? */ + if (strcmp (type, "mail") != 0) { notify_listener (listener, GNOME_Evolution_Storage_UNSUPPORTED_TYPE); return; } name = strrchr (path, '/'); - if (!name++) { + if (!name) { notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); return; } + name++; camel_exception_init (&ex); if (*parent_physical_uri) { @@ -1011,7 +1057,7 @@ storage_create_folder (EvolutionStorage *storage, return; } - root = camel_store_create_folder (store, url->path + 1, name, &ex); + root = camel_store_create_folder (store, url->fragment?url->fragment:url->path + 1, name, &ex); camel_url_free (url); } else root = camel_store_create_folder (store, NULL, name, &ex); @@ -1102,25 +1148,39 @@ storage_xfer_folder (EvolutionStorage *storage, CamelStore *store) { CamelException ex; + char *src, *dst; + char *p, c, sep; printf("Transfer folder on store source = '%s' dest = '%s'\n", source_path, destination_path); - /* FIXME: Need to remap path to real name */ - - if (source_path[0] == '/') - source_path++; - if (destination_path[0] == '/') - destination_path++; + /* Remap the 'path' to the camel friendly name based on the store dir separator */ + sep = store->dir_sep; + src = g_strdup(source_path[0]=='/'?source_path+1:source_path); + dst = g_strdup(destination_path[0]=='/'?destination_path+1:destination_path); + if (sep != '/') { + p = src; + while ((c = *p++)) + if (c == '/') + p[-1] = sep; + + p = dst; + while ((c = *p++)) + if (c == '/') + p[-1] = sep; + } camel_exception_init (&ex); if (remove_source) { printf("trying to rename\n"); - camel_store_rename_folder(store, source_path, destination_path, &ex); + camel_store_rename_folder(store, src, dst, &ex); } else { printf("No remove, can't rename\n"); camel_exception_setv(&ex, 1, "Can copy folders"); } + g_free(src); + g_free(dst); + if (camel_exception_is_set(&ex)) { notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); } else { diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c index 6ae250df0c..7e6c3bca26 100644 --- a/mail/mail-folder-cache.c +++ b/mail/mail-folder-cache.c @@ -76,6 +76,7 @@ struct _folder_update { char *name; char *uri; char *oldpath; + char *olduri; int unread; CamelStore *store; @@ -118,6 +119,8 @@ free_update(struct _folder_update *up) g_free(up->uri); if (up->store) camel_object_unref((CamelObject *)up->store); + g_free(up->oldpath); + g_free(up->olduri); g_free(up); } @@ -152,12 +155,17 @@ real_flush_updates(void *o, void *event_data, void *data) else mail_vfolder_add_uri(up->store, up->uri, TRUE); } else { + /* Its really a rename, but we have no way of telling the shell that, so remove it */ if (up->oldpath) { if (storage != NULL) evolution_storage_removed_folder(storage, up->oldpath); /* ELSE? Shell supposed to handle the local snot case */ } + /* We can tell the vfolder code though */ + if (up->olduri && up->add) + mail_vfolder_rename_uri(up->store, up->olduri, up->uri); + if (up->name == NULL) { if (storage != NULL) { d(printf("Updating existing folder: %s (%d unread)\n", up->path, up->unread)); @@ -174,7 +182,8 @@ real_flush_updates(void *o, void *event_data, void *data) d(printf("Adding new folder: %s\n", up->path)); evolution_storage_new_folder(storage, up->path, up->name, type, up->uri, up->name, up->unread); } - if (up->add) + + if (!up->olduri && up->add) mail_vfolder_add_uri(up->store, up->uri, FALSE); } @@ -441,6 +450,8 @@ store_folder_subscribed(CamelObject *o, void *event_data, void *data) struct _store_info *si; CamelFolderInfo *fi = event_data; + printf("Store folder subscribed '%s' store '%s' \n", fi->full_name, camel_url_to_string(((CamelService *)o)->url, 0)); + LOCK(info_lock); si = g_hash_table_lookup(stores, o); if (si) @@ -451,6 +462,8 @@ store_folder_subscribed(CamelObject *o, void *event_data, void *data) static void store_folder_created(CamelObject *o, void *event_data, void *data) { + printf("Store folder created\n"); + /* we only want created events to do more work if we dont support subscriptions */ if (!camel_store_supports_subscriptions(CAMEL_STORE(o))) store_folder_subscribed(o, event_data, data); @@ -504,12 +517,12 @@ rename_folders(struct _store_info *si, const char *oldbase, const char *newbase, printf("Found old folder '%s' renaming to '%s'\n", mfi->full_name, fi->full_name); up->oldpath = mfi->path; + up->olduri = mfi->uri; /* Its a rename op */ g_hash_table_remove(si->folders, mfi->full_name); g_hash_table_remove(si->folders, mfi->uri); g_free(mfi->full_name); - g_free(mfi->uri); mfi->path = g_strdup(fi->path); mfi->full_name = g_strdup(fi->full_name); mfi->uri = g_strdup(fi->url); @@ -578,10 +591,10 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) LOCK(info_lock); si = g_hash_table_lookup(stores, store); if (si) { +#if 0 GPtrArray *folders = g_ptr_array_new(); struct _folder_update *up; -#if 0 /* first, get an array of all folders */ get_folders(folders, info->new); #endif diff --git a/mail/mail-local.c b/mail/mail-local.c index ffaa890e9a..8f43497ce4 100644 --- a/mail/mail-local.c +++ b/mail/mail-local.c @@ -605,11 +605,12 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int CamelStore *fromstore = NULL; CamelFolder *fromfolder = NULL; char *oldformat = NULL; - char *tmpname; char *store_uri; GPtrArray *uids; int real_folder_frozen = FALSE; int format_change, index_changed; + char *tmpname = NULL; + char *mbox = NULL; format_change = strcmp(mlf->meta->format, new_format) != 0; index_changed = mlf->meta->indexed != index_body; @@ -639,8 +640,7 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int goto cleanup; } - store_uri = g_strdup_printf("%s:%s%s", mlf->meta->format, - ((CamelService *)((CamelFolder *)mlf)->parent_store)->url->path, mlf->real_path); + store_uri = g_strdup_printf("%s:%s", mlf->meta->format, ((CamelService *)((CamelFolder *)mlf)->parent_store)->url->path); fromstore = camel_session_get_store(session, store_uri, ex); g_free(store_uri); if (fromstore == NULL) @@ -650,10 +650,11 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int mlf->meta->format = g_strdup(new_format); /* rename the old mbox and open it again, without indexing */ - tmpname = g_strdup_printf ("%s_reconfig", mlf->meta->name); - d(printf("renaming %s to %s, and opening it\n", mlf->meta->name, tmpname)); + tmpname = g_strdup_printf ("%s/%s_reconfig", mlf->real_path, mlf->meta->name); + mbox = g_strdup_printf("%s/%s", mlf->real_path, mlf->meta->name); + d(printf("renaming %s to %s, and opening it\n", mbox, tmpname)); - camel_store_rename_folder(fromstore, mlf->meta->name, tmpname, ex); + camel_store_rename_folder(fromstore, mbox, tmpname, ex); if (camel_exception_is_set(ex)) goto cleanup; @@ -662,7 +663,7 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int if (fromfolder == NULL || camel_exception_is_set(ex)) { /* try and recover ... */ camel_exception_clear(ex); - camel_store_rename_folder(fromstore, tmpname, mlf->meta->name, ex); + camel_store_rename_folder(fromstore, tmpname, mbox, ex); goto cleanup; } @@ -673,7 +674,7 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int d(printf("cannot open destination folder\n")); /* try and recover ... */ camel_exception_clear(ex); - camel_store_rename_folder(fromstore, tmpname, mlf->meta->name, ex); + camel_store_rename_folder(fromstore, tmpname, mbox, ex); goto cleanup; } @@ -716,6 +717,9 @@ mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int if (fromstore) camel_object_unref((CamelObject *)fromstore); + g_free(tmpname); + g_free(mbox); + LOCAL_FOLDER_UNLOCK (mlf); if (real_folder_frozen) @@ -765,7 +769,7 @@ static void mls_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) { CamelStore *real_store; - char *metapath, *uri; + char *metapath, *uri, *mbox; CamelException local_ex; struct _local_meta *meta; @@ -776,7 +780,7 @@ mls_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex /* find the real store for this folder, and proxy the call */ metapath = g_strdup_printf("%s%s/local-metadata.xml", ((CamelService *)store)->url->path, folder_name); meta = load_metainfo(metapath); - uri = g_strdup_printf("%s:%s%s", meta->format, ((CamelService *)store)->url->path, folder_name); + uri = g_strdup_printf("%s:%s", meta->format, ((CamelService *)store)->url->path); real_store = (CamelStore *)camel_session_get_service(session, uri, CAMEL_PROVIDER_STORE, ex); g_free(uri); if (real_store == NULL) { @@ -785,7 +789,9 @@ mls_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex return; } - camel_store_delete_folder(real_store, meta->name, &local_ex); + mbox = g_strdup_printf("%s/%s", folder_name, meta->name); + camel_store_delete_folder(real_store, mbox, &local_ex); + g_free(mbox); if (camel_exception_is_set(&local_ex)) { camel_exception_xfer(ex, &local_ex); g_free(metapath); diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index d4c979060f..5db432a3b6 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -44,7 +44,7 @@ #include "e-util/e-unicode-i18n.h" -#define d(x) x +#define d(x) static VfolderContext *context; /* context remains open all time */ static CamelStore *vfolder_store; /* the 1 static vfolder store */ @@ -376,7 +376,7 @@ mail_vfolder_delete_uri(CamelStore *store, const char *uri) CamelVeeFolder *vf; GString *changed; - if (context == NULL || CAMEL_IS_VEE_STORE(store) || !strncmp(uri, "vtrash:", 7)) + if (context == NULL || !strncmp(uri, "vtrash:", 7)) return; d(printf("Deleting uri to check: %s\n", uri)); @@ -431,13 +431,56 @@ mail_vfolder_delete_uri(CamelStore *store, const char *uri) } /* called when a uri is renamed in a store */ -#if 0 void mail_vfolder_rename_uri(CamelStore *store, const char *from, const char *to) { + GCompareFunc uri_cmp = CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name; + FilterRule *rule; + const char *source; + CamelVeeFolder *vf; + int changed = 0; + printf("vfolder rename uri: %s to %s\n", from, to); + + if (context == NULL || !strncmp(from, "vtrash:", 7) || !strncmp(to, "vtrash:", 7)) + return; + + g_assert(pthread_self() == mail_gui_thread); + + LOCK(); + + /* see if any rules directly reference this removed uri */ + rule = NULL; + while ( (rule = rule_context_next_rule((RuleContext *)context, rule, NULL)) ) { + source = NULL; + while ( (source = vfolder_rule_next_source((VfolderRule *)rule, source)) ) { + /* Remove all sources that match, ignore changed events though + because the adduri call above does the work async */ + if (uri_cmp(from, source)) { + printf("Vfolder '%s' used '%s' ('%s') now uses '%s'\n", rule->name, source, from, to); + vf = g_hash_table_lookup(vfolder_hash, rule->name); + g_assert(vf); + gtk_signal_disconnect_by_func((GtkObject *)rule, rule_changed, vf); + vfolder_rule_remove_source((VfolderRule *)rule, source); + vfolder_rule_add_source((VfolderRule *)rule, to); + gtk_signal_connect((GtkObject *)rule, "changed", rule_changed, vf); + changed++; + source = NULL; + } + } + } + + UNLOCK(); + + if (changed) { + char *user; + + printf("Vfolders updated from renamed folder\n"); + user = g_strdup_printf("%s/vfolders.xml", evolution_dir); + rule_context_save((RuleContext *)context, user); + g_free(user); + } } -#endif /* ********************************************************************** */ @@ -455,10 +498,11 @@ rule_changed(FilterRule *rule, CamelFolder *folder) /* if the folder has changed name, then add it, then remove the old manually */ if (strcmp(folder->full_name, rule->name) != 0) { - char *path, *key; + char *key; CamelFolder *old; LOCK(); + printf("Changing folder name in hash table to '%s'\n", rule->name); if (g_hash_table_lookup_extended(vfolder_hash, folder->full_name, (void **)&key, (void **)&old)) { g_hash_table_remove(vfolder_hash, key); g_free(key); @@ -470,31 +514,6 @@ rule_changed(FilterRule *rule, CamelFolder *folder) } camel_store_rename_folder(vfolder_store, folder->full_name, rule->name, NULL); - -#if 0 - path = g_strdup_printf("/%s", folder->full_name); - evolution_storage_removed_folder(mail_lookup_storage(vfolder_store), path); - g_free(path); - - gtk_signal_disconnect_by_func((GtkObject *)rule, rule_changed, folder); - - context_rule_added((RuleContext *)context, rule); - - /* TODO: remove folder from folder info cache? */ - - LOCK(); - if (g_hash_table_lookup_extended(vfolder_hash, folder->full_name, (void **)&key, (void **)&old)) { - g_hash_table_remove(vfolder_hash, key); - g_free(key); - UNLOCK(); - camel_object_unref((CamelObject *)folder); - } else { - UNLOCK(); - g_warning("couldn't find a vfolder rule in our table? %s", folder->full_name); - } - - return; -#endif } d(printf("Filter rule changed? for folder '%s'!!\n", folder->name)); @@ -610,7 +629,7 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data) d(printf("Folder deleted: %s\n", info->name)); store = store; - /* WARNING: Not thread safe, joy! */ + /* Warning not thread safe, but might be enough */ LOCK(); @@ -640,22 +659,38 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data) CamelRenameInfo *info = event_data; FilterRule *rule; char *user; + char *key; + CamelFolder *folder; - /* TODO: Scan all sub-folders? */ + store = store; + + /* This should be more-or-less thread-safe */ printf("Folder renamed to '%s' from '%s'\n", info->new->full_name, info->old_base); - rule = rule_context_find_rule((RuleContext *)context, info->old_base, NULL); - if (rule) { - /* TODO: We need to stop listening to removed events, otherwise we'll try and rename it again? */ + /* Folder is already renamed? */ + LOCK(); + printf("Changing folder name in hash table to '%s'\n", info->new->full_name); + if (g_hash_table_lookup_extended(vfolder_hash, info->old_base, (void **)&key, (void **)&folder)) { + g_hash_table_remove(vfolder_hash, key); + g_free(key); + g_hash_table_insert(vfolder_hash, g_strdup(info->new->full_name), folder); - filter_rule_set_name(rule, info->new->name); + rule = rule_context_find_rule((RuleContext *)context, info->old_base, NULL); + g_assert(rule); + + gtk_signal_disconnect_by_func((GtkObject *)rule, rule_changed, folder); + filter_rule_set_name(rule, info->new->name); + gtk_signal_connect((GtkObject *)rule, "changed", rule_changed, folder); user = g_strdup_printf("%s/vfolders.xml", evolution_dir); rule_context_save((RuleContext *)context, user); g_free(user); + + UNLOCK(); } else { - /* We just got it inside renaming it ourself, ignore */ + UNLOCK(); + g_warning("couldn't find a vfolder rule in our table? %s", info->new->full_name); } } diff --git a/mail/mail-vfolder.h b/mail/mail-vfolder.h index 4dde188a69..9561185c4a 100644 --- a/mail/mail-vfolder.h +++ b/mail/mail-vfolder.h @@ -24,6 +24,9 @@ void vfolder_gui_add_from_mlist (CamelMimeMessage *msg, const char *mlist, const /* add a uri that is now (un)available to vfolders in a transient manner */ void mail_vfolder_add_uri(CamelStore *store, const char *uri, int remove); +/* note that a folder has changed name (uri) */ +void mail_vfolder_rename_uri(CamelStore *store, const char *from, const char *to); + /* remove a uri that should be removed from vfolders permanently */ void mail_vfolder_delete_uri(CamelStore *store, const char *uri); |