Index: camel-imap-store.c =================================================================== --- camel-imap-store.c (revision 3166) +++ camel-imap-store.c (working copy) @@ -415,6 +415,9 @@ disco->diary = NULL; } + if (imap_store->namespaces) + imap_namespaces_destroy (imap_store->namespaces); + /* g_static_rec_mutex_free (imap_store->idle_prefix_lock); */ g_free (imap_store->idle_prefix_lock); imap_store->idle_prefix_lock = NULL; @@ -1863,6 +1866,8 @@ if ((store->capabilities & IMAP_CAPABILITY_NAMESPACE) && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { + struct _namespaces *namespaces; + response = camel_imap_command (store, NULL, ex, "NAMESPACE"); if (!response) goto done; @@ -1871,34 +1876,44 @@ if (!result) goto done; -#if 0 - /* new code... */ - namespaces = imap_parse_namespace_response (result); - imap_namespaces_destroy (namespaces); - /* end new code */ -#endif + store->namespaces = imap_parse_namespace_response (result); + namespaces = store->namespaces; - name = camel_strstrcase (result, "NAMESPACE (("); - if (name) { - char *sep; + if (namespaces && namespaces->personal) { + store->namespace = namespaces->personal->prefix; + store->dir_sep = namespaces->personal->delim; + } else { + store->namespace = NULL; + store->dir_sep = 0; + } - name += 12; - store->namespace = imap_parse_string ((const char **) &name, &len); - if (name && *name++ == ' ') { - sep = imap_parse_string ((const char **) &name, &len); - if (sep) { - store->dir_sep = *sep; - g_free (sep); - } - } + + if (namespaces && namespaces->personal) { + ns = camel_imap_store_summary_namespace_new(store->summary, namespaces->personal->prefix, namespaces->personal->delim); + camel_imap_store_summary_namespace_add(store->summary,ns); + camel_imap_store_summary_namespace_set(store->summary, ns); } + + if (namespaces && namespaces->other) { + ns = camel_imap_store_summary_namespace_new(store->summary, namespaces->other->prefix, namespaces->other->delim); + camel_imap_store_summary_namespace_add(store->summary,ns); + } + + if (namespaces && namespaces->shared) { + ns = camel_imap_store_summary_namespace_new(store->summary, namespaces->shared->prefix, namespaces->shared->delim); + camel_imap_store_summary_namespace_add(store->summary,ns); + } + + g_free (result); + } else { + ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep); + camel_imap_store_summary_namespace_add(store->summary,ns); + camel_imap_store_summary_namespace_set(store->summary, ns); } - if (store->namespace && strlen (store->namespace) == 0) { - g_free (store->namespace); + if (store->namespace && strlen (store->namespace) == 0) store->namespace = NULL; - } if (store->namespace && !store->dir_sep) { if (FALSE && store->server_level >= IMAP_LEVEL_IMAP4REV1) { @@ -1932,7 +1947,7 @@ store->dir_sep = '/'; /* Guess */ if (!store->namespace) - store->namespace = g_strdup (""); + store->namespace = ""; /* canonicalize the namespace to end with dir_sep */ len = strlen (store->namespace); @@ -1946,8 +1961,6 @@ g_static_rec_mutex_lock (store->sum_lock); - ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep); - camel_imap_store_summary_namespace_set(store->summary, ns); if ((store->parameters & IMAP_PARAM_SUBSCRIPTIONS) && camel_store_summary_count((CamelStoreSummary *)store->summary) == 0) @@ -2054,10 +2067,8 @@ store->authtypes = NULL; } - if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { - g_free (store->namespace); + if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) store->namespace = NULL; - } return TRUE; } @@ -3473,19 +3484,6 @@ fi = parse_list_response_as_folder_info (imap_store, list); if (fi) { - if (FALSE && j == 0) { - struct imap_status_item *item, *items; - item = items = get_folder_status (imap_store, fi->full_name, "MESSAGES UNSEEN", TRUE); - while (item != NULL) { - if (!g_ascii_strcasecmp (item->name, "MESSAGES")) - fi->total = item->value; - if (!g_ascii_strcasecmp (item->name, "UNSEEN")) - fi->unread = item->value; - item = item->next; - } - imap_status_item_free (items); - } - if (fi->flags & CAMEL_FOLDER_NONEXISTENT) { camel_folder_info_free(fi); continue; @@ -3514,12 +3512,10 @@ fi->flags |= CAMEL_FOLDER_SUBSCRIBED; hfi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; } - if (j == 0) - { + if (j == 0) { hfi->unread = fi->unread; hfi->total = fi->total; } - camel_folder_info_free(fi); } } } @@ -3613,60 +3609,35 @@ g_free (folder_dir); } -struct _refresh_msg { - CamelSessionThreadMsg msg; - CamelStore *store; - CamelException ex; -}; - static void -refresh_refresh(CamelSession *session, CamelSessionThreadMsg *msg) +get_list_for_namespace (CamelImapStore *imap_store, struct _namespace *namespace, guint32 flags, CamelException *ex) { - struct _refresh_msg *m = (struct _refresh_msg *)msg; - CamelImapStore *store = (CamelImapStore *)m->store; - CamelException nex = CAMEL_EXCEPTION_INITIALISER; + char *pattern; + int i; - CAMEL_SERVICE_REC_LOCK(m->store, connect_lock); + if (namespace->prefix && namespace->prefix[0]) { + i = strlen(namespace->prefix)-1; + pattern = g_alloca(i+5); - if (!camel_disco_store_check_online((CamelDiscoStore *)m->store, &m->ex)) - goto done; + strcpy(pattern, namespace->prefix); + while (i>0 && pattern[i] == namespace->delim) + pattern[i--] = 0; + i++; - if (store->namespace && store->namespace[0]) { - char *pattern; - - get_folders_sync(store, "INBOX", &m->ex); - if (camel_exception_is_set(&m->ex)) - goto done; - get_folders_sync(store, store->namespace, &m->ex); - if (camel_exception_is_set(&m->ex)) - goto done; - pattern = imap_concat(store, store->namespace, "*"); - get_folders_sync(store, pattern, &m->ex); - g_free(pattern); + pattern[i] = namespace->delim; + pattern[i+1] = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)?'*':'%'; + pattern[i+2] = 0; + get_folders_sync(imap_store, pattern, ex); } else { - get_folders_sync((CamelImapStore *)m->store, "*", &m->ex); + pattern = g_alloca(2); + pattern[0] = '*'; + pattern[1] = 0; + i=0; + get_folders_sync(imap_store, pattern, ex); } - camel_store_summary_touch((CamelStoreSummary *)((CamelImapStore *)m->store)->summary); - camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)m->store)->summary, &nex); -done: - CAMEL_SERVICE_REC_UNLOCK(m->store, connect_lock); } -static void -refresh_free(CamelSession *session, CamelSessionThreadMsg *msg) -{ - struct _refresh_msg *m = (struct _refresh_msg *)msg; - - camel_object_unref(m->store); - camel_exception_clear(&m->ex); -} - -static CamelSessionThreadOps refresh_ops = { - refresh_refresh, - refresh_free, -}; - static CamelFolderInfo * get_folder_info_online (CamelStore *store, const char *top, guint32 flags, CamelException *ex) { @@ -3688,71 +3659,59 @@ if (camel_debug("imap:folder_info")) printf("get folder info online\n"); - if (FALSE && (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) - && camel_store_summary_count((CamelStoreSummary *)imap_store->summary) > 0) { - time_t now; - int ref; - now = time(NULL); - ref = now > imap_store->refresh_stamp+60*60*1; - if (ref) { - CAMEL_SERVICE_REC_LOCK(store, connect_lock); - ref = now > imap_store->refresh_stamp+60*60*1; - if (ref) { - struct _refresh_msg *m; - imap_store->refresh_stamp = now; + CAMEL_SERVICE_REC_LOCK(store, connect_lock); - m = camel_session_thread_msg_new(((CamelService *)store)->session, &refresh_ops, sizeof(*m)); - m->store = store; - camel_object_ref(store); - camel_exception_init(&m->ex); - camel_session_thread_queue(((CamelService *)store)->session, &m->msg, 0); - } - CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); - } - } else { - char *pattern; - int i; + if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) + goto fail; - CAMEL_SERVICE_REC_LOCK(store, connect_lock); + if (top[0] == 0) { + if (imap_store->namespaces) { - if (!camel_disco_store_check_online((CamelDiscoStore *)imap_store, ex)) - goto fail; + get_folders_sync (imap_store, "*", ex); + if (camel_exception_is_set(ex)) + goto fail; +/* + if (imap_store->namespaces->personal) + get_list_for_namespace (imap_store, + imap_store->namespaces->personal, flags, ex); + if (camel_exception_is_set(ex)) + goto fail; - if (top[0] == 0) { - if (imap_store->namespace && imap_store->namespace[0]) { - get_folders_sync (imap_store, "INBOX", ex); - if (camel_exception_is_set(ex)) - goto fail; + if (imap_store->namespaces->other) + get_list_for_namespace (imap_store, + imap_store->namespaces->other, flags, ex); + if (camel_exception_is_set(ex)) + goto fail; - i = strlen(imap_store->namespace)-1; - pattern = g_alloca(i+5); - strcpy(pattern, imap_store->namespace); - while (i>0 && pattern[i] == imap_store->dir_sep) - pattern[i--] = 0; - i++; - } else { - pattern = g_alloca(2); - pattern[0] = '*'; - pattern[1] = 0; - i=0; - } - } else { - char *name; + if (imap_store->namespaces->shared) + get_list_for_namespace (imap_store, + imap_store->namespaces->shared, flags, ex); + if (camel_exception_is_set(ex)) + goto fail; */ - name = camel_imap_store_summary_full_from_path(imap_store->summary, top); - if (name == NULL) - name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep); - - i = strlen(name); - pattern = g_alloca(i+5); - strcpy(pattern, name); - g_free(name); + } else { + char *pattern; + int i; + pattern = g_alloca(2); + pattern[0] = '*'; + pattern[1] = 0; + i=0; + get_folders_sync(imap_store, pattern, ex); } - - - if (pattern[0] != '*' && imap_store->dir_sep) { + } else { + char *pattern; + int i; + char *name; + name = camel_imap_store_summary_full_from_path(imap_store->summary, top); + if (name == NULL) + name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep); + i = strlen(name); + pattern = g_alloca(i+5); + strcpy(pattern, name); + g_free(name); + if (imap_store->dir_sep) { pattern[i] = imap_store->dir_sep; pattern[i+1] = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)?'*':'%'; pattern[i+2] = 0; @@ -3763,12 +3722,14 @@ if (camel_exception_is_set(ex)) goto fail; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary, ex); - - CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); } + + camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); + camel_store_summary_save((CamelStoreSummary *)imap_store->summary, ex); + + CAMEL_SERVICE_REC_UNLOCK(store, connect_lock); + tree = get_folder_info_offline(store, top, flags, ex); g_static_rec_mutex_unlock (imap_store->sum_lock); @@ -3810,10 +3771,10 @@ /* get starting point */ if (top[0] == 0) { - if (imap_store->namespace && imap_store->namespace[0]) { - name = g_strdup(imap_store->summary->namespace->full_name); - top = imap_store->summary->namespace->path; - } else + //if (imap_store->namespace && imap_store->namespace[0]) { + // name = g_strdup(imap_store->summary->namespace->full_name); + // top = imap_store->summary->namespace->path; + //} else name = g_strdup(""); } else { name = camel_imap_store_summary_full_from_path(imap_store->summary, top); Index: camel-imap-store-summary.h =================================================================== --- camel-imap-store-summary.h (revision 3166) +++ camel-imap-store-summary.h (working copy) @@ -63,7 +63,8 @@ /* header info */ guint32 version; /* version of base part of file */ guint32 capabilities; - CamelImapStoreNamespace *namespace; /* eventually to be a list */ + GList *namespaces; /* eventually to be a list */ + CamelImapStoreNamespace *namespace; }; struct _CamelImapStoreSummaryClass { @@ -76,6 +77,7 @@ /* TODO: this api needs some more work, needs to support lists */ CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep); void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns); +void camel_imap_store_summary_namespace_add(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns); CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path); CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full_name); Index: camel-imap-store.h =================================================================== --- camel-imap-store.h (revision 3166) +++ camel-imap-store.h (working copy) @@ -160,6 +160,7 @@ /* NB: namespace should be handled by summary->namespace */ char *namespace, dir_sep, *base_url, *storage_path; GHashTable *authtypes; + struct _namespaces *namespaces; time_t refresh_stamp; gchar *idle_prefix; Index: camel-imap-store-summary.c =================================================================== --- camel-imap-store-summary.c (revision 3166) +++ camel-imap-store-summary.c (working copy) @@ -93,14 +93,20 @@ ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelImapStoreInfo); s->version = CAMEL_IMAP_STORE_SUMMARY_VERSION; + s->namespaces = NULL; + s->namespace = NULL; } static void camel_imap_store_summary_finalise (CamelObject *obj) { /*struct _CamelImapStoreSummaryPrivate *p;*/ - /*CamelImapStoreSummary *s = (CamelImapStoreSummary *)obj;*/ + CamelImapStoreSummary *is = (CamelImapStoreSummary *)obj; + CamelStoreSummary *s = (CamelStoreSummary *) s; + if (is->namespaces) + namespace_clear (s); + /*p = _PRIVATE(obj); g_free(p);*/ } @@ -296,7 +302,7 @@ char *full_name; CamelImapStoreNamespace *ns; - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); + printf("adding full name '%s' '%c'\n", full, dir_sep); len = strlen(full); full_name = alloca(len+1); @@ -395,57 +401,67 @@ return ns; } +void camel_imap_store_summary_namespace_add(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns) +{ + s->namespaces = g_list_prepend (s->namespaces, ns); +} + void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns) { - d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path)); - namespace_clear((CamelStoreSummary *)s); s->namespace = ns; - camel_store_summary_touch((CamelStoreSummary *)s); + return; } CamelImapStoreNamespace * camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path) { int len; - CamelImapStoreNamespace *ns; + GList *list; + CamelImapStoreNamespace *nsf = NULL; - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { + list = s->namespaces; + while (list) { + CamelImapStoreNamespace *ns = list->data; len = strlen(ns->path); if (len == 0 || (strncmp(ns->path, path, len) == 0 - && (path[len] == '/' || path[len] == 0))) + && (path[len] == '/' || path[len] == 0))) { + nsf = ns; break; - ns = NULL; + } + list = list->next; } - /* have a default? */ - return ns; + return nsf; } CamelImapStoreNamespace * camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full) { int len; - CamelImapStoreNamespace *ns; + GList *list; + CamelImapStoreNamespace *nsf = NULL; /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { + list = s->namespaces; + while (list) { + CamelImapStoreNamespace *ns = list->data; len = strlen(ns->full_name); d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full)); if (len == 0 || (strncmp(ns->full_name, full, len) == 0 - && (full[len] == ns->sep || full[len] == 0))) + && (full[len] == ns->sep || full[len] == 0))) { + nsf = ns; break; - ns = NULL; + } + list = list->next; } /* have a default? */ - return ns; + return nsf; } + static void namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns) { @@ -458,51 +474,84 @@ namespace_clear(CamelStoreSummary *s) { CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; + GList *list = is->namespaces; - if (is->namespace) - namespace_free(s, is->namespace); - is->namespace = NULL; + while (list) { + CamelImapStoreNamespace *ns = list->data; + namespace_free(s, ns); + list=list->next; + } + g_list_free (is->namespaces); + is->namespaces = NULL; } -static CamelImapStoreNamespace * +static int namespace_load(CamelStoreSummary *s, FILE *in) { + CamelImapStoreSummary *is = (CamelImapStoreSummary *) s; + CamelImapStoreNamespace *ns; - guint32 sep = '/'; + int count = 0, i = 0; - ns = g_malloc0(sizeof(*ns)); + if (is->namespaces) + namespace_clear (s); - if (camel_file_util_decode_string(in, &ns->path) == -1) + if (camel_file_util_decode_uint32(in, &count) == -1) goto nserror; - if (camel_file_util_decode_string(in, &ns->full_name) == -1) - goto nserror; + for (i=0 ; i< count; i++) { + guint32 sep = '/'; + ns = g_malloc0(sizeof(*ns)); + if (camel_file_util_decode_string(in, &ns->path) == -1) { + namespace_free(s, ns); + goto nserror; + } + if (camel_file_util_decode_string(in, &ns->full_name) == -1) { + namespace_free(s, ns); + goto nserror; + } + if (camel_file_util_decode_uint32(in, &sep) == -1) { + namespace_free(s, ns); + goto nserror; + } + ns->sep = sep; + is->namespaces = g_list_prepend (is->namespaces, ns); + } - if (camel_file_util_decode_uint32(in, &sep) == -1) - goto nserror; + return 0; - ns->sep = sep; - - return ns; - nserror: - namespace_free(s, ns); - return NULL; + return -1; } static int -namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns) +namespace_save(CamelStoreSummary *s, FILE *in) { - if (camel_file_util_encode_string(in, ns->path) == -1) - goto serr; + CamelImapStoreSummary *is = (CamelImapStoreSummary *) s; - if (camel_file_util_encode_string(in, ns->full_name) == -1) - goto serr; + GList *list; - if (camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) + if (camel_file_util_encode_uint32(in, (guint32) g_list_length (is->namespaces)) == -1) goto serr; + list = is->namespaces; + + while (list) { + CamelImapStoreNamespace *ns = list->data; + + if (camel_file_util_encode_string(in, ns->path) == -1) + goto serr; + + if (camel_file_util_encode_string(in, ns->full_name) == -1) + goto serr; + + if (camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) + goto serr; + + list = list->next; + } + return 0; serr: @@ -531,18 +580,12 @@ } /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ - if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1 - || count > 1) + if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1) return -1; is->capabilities = capabilities; - if (count == 1) { - if ((is->namespace = namespace_load(s, in)) == NULL) - return -1; - } - return 0; + return namespace_load (s, in); } static int @@ -551,16 +594,13 @@ CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; guint32 count; - count = is->namespace?1:0; - /* always write as latest version */ if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 || camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 - || camel_file_util_encode_fixed_int32(out, count) == -1) + || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1) return -1; - if (is->namespace && namespace_save(s, out, is->namespace) == -1) + if (namespace_save(s, out) == -1) return -1; return 0;