Improve handling of namespace references
* imap4d/list.c (refinfo) <pfxlen>: Remove. (list_fun): Change the algorithm for restoring the printable reference name. (imap4d_list): Use actual reference, not the prefix value. * imap4d/namespace.c: Fix handling of NS_OTHER prefixes. * imap4d/tests/list.at: Change the testcase.
Showing
3 changed files
with
38 additions
and
85 deletions
... | @@ -24,7 +24,6 @@ struct refinfo | ... | @@ -24,7 +24,6 @@ struct refinfo |
24 | char *refptr; /* Original reference */ | 24 | char *refptr; /* Original reference */ |
25 | size_t reflen; /* Length of the original reference */ | 25 | size_t reflen; /* Length of the original reference */ |
26 | struct namespace_prefix const *pfx; | 26 | struct namespace_prefix const *pfx; |
27 | size_t pfxlen; | ||
28 | size_t dirlen; /* Length of the current directory prefix */ | 27 | size_t dirlen; /* Length of the current directory prefix */ |
29 | char *buf; | 28 | char *buf; |
30 | size_t bufsize; | 29 | size_t bufsize; |
... | @@ -43,8 +42,8 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) | ... | @@ -43,8 +42,8 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) |
43 | 42 | ||
44 | name = resp->name; | 43 | name = resp->name; |
45 | size = strlen (name); | 44 | size = strlen (name); |
46 | if (size == refinfo->pfxlen + 6 | 45 | if (size == refinfo->reflen + 6 |
47 | && memcmp (name + refinfo->pfxlen + 1, "INBOX", 5) == 0) | 46 | && memcmp (name + refinfo->reflen + 1, "INBOX", 5) == 0) |
48 | return 0; | 47 | return 0; |
49 | 48 | ||
50 | io_sendf ("* %s", "LIST ("); | 49 | io_sendf ("* %s", "LIST ("); |
... | @@ -59,37 +58,25 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) | ... | @@ -59,37 +58,25 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) |
59 | io_sendf (") \"%c\" ", refinfo->pfx->delim); | 58 | io_sendf (") \"%c\" ", refinfo->pfx->delim); |
60 | 59 | ||
61 | name = resp->name + refinfo->dirlen + 1; | 60 | name = resp->name + refinfo->dirlen + 1; |
62 | size = strlen (name) + refinfo->pfxlen + 2; | 61 | size = strlen (name) + refinfo->reflen + 2; |
63 | if (size > refinfo->bufsize) | 62 | if (size > refinfo->bufsize) |
64 | { | 63 | { |
65 | if (refinfo->buf == NULL) | 64 | if (refinfo->buf == NULL) |
66 | { | 65 | { |
67 | refinfo->bufsize = size; | 66 | refinfo->bufsize = size; |
68 | refinfo->buf = malloc (refinfo->bufsize); | 67 | refinfo->buf = mu_alloc (refinfo->bufsize); |
69 | if (!refinfo->buf) | ||
70 | { | ||
71 | mu_error ("%s", mu_strerror (errno)); | ||
72 | return 1; | ||
73 | } | ||
74 | memcpy (refinfo->buf, refinfo->refptr, refinfo->reflen); | ||
75 | } | 68 | } |
76 | else | 69 | else |
77 | { | 70 | { |
78 | char *p = realloc (refinfo->buf, size); | 71 | refinfo->buf = mu_realloc (refinfo->buf, size); |
79 | if (!p) | ||
80 | { | ||
81 | mu_error ("%s", mu_strerror (errno)); | ||
82 | return 1; | ||
83 | } | ||
84 | refinfo->buf = p; | ||
85 | refinfo->bufsize = size; | 72 | refinfo->bufsize = size; |
86 | } | 73 | } |
87 | } | 74 | } |
88 | 75 | ||
89 | if (refinfo->pfxlen) | 76 | if (refinfo->refptr[0]) |
90 | { | 77 | { |
91 | p = mu_stpcpy (refinfo->buf, refinfo->pfx->prefix); | 78 | p = mu_stpcpy (refinfo->buf, refinfo->refptr); |
92 | if (*name) | 79 | if (refinfo->refptr[refinfo->reflen-1] != refinfo->pfx->delim) |
93 | *p++ = refinfo->pfx->delim; | 80 | *p++ = refinfo->pfx->delim; |
94 | } | 81 | } |
95 | else | 82 | else |
... | @@ -185,35 +172,16 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -185,35 +172,16 @@ imap4d_list (struct imap4d_session *session, |
185 | struct refinfo refinfo; | 172 | struct refinfo refinfo; |
186 | size_t i; | 173 | size_t i; |
187 | struct namespace_prefix const *pfx; | 174 | struct namespace_prefix const *pfx; |
188 | |||
189 | if (*wcard == '~') | ||
190 | { | ||
191 | for (i = 1; | ||
192 | mu_c_is_class (wcard[i], MU_CTYPE_ALPHA|MU_CTYPE_DIGIT) | ||
193 | || wcard[i] == '_'; i++) | ||
194 | ; | ||
195 | ref = mu_alloc (i + 1); | ||
196 | memcpy (ref, wcard, i); | ||
197 | ref[i] = 0; | ||
198 | wcard += i; | ||
199 | } | ||
200 | else | ||
201 | ref = mu_strdup (ref); | ||
202 | 175 | ||
203 | cwd = namespace_translate_name (ref, 0, &pfx); | 176 | cwd = namespace_translate_name (ref, 0, &pfx); |
204 | if (!cwd) | 177 | if (!cwd) |
205 | { | 178 | { |
206 | free (ref); | ||
207 | return io_completion_response (command, RESP_NO, | 179 | return io_completion_response (command, RESP_NO, |
208 | "The requested item could not be found."); | 180 | "The requested item could not be found."); |
209 | } | 181 | } |
210 | free (cwd); | 182 | free (cwd); |
211 | 183 | ||
212 | if (*wcard == pfx->delim && ref[0] != '~') | 184 | ref = mu_strdup (ref); |
213 | { | ||
214 | /* Absolute Path in wcard, dump the old ref. */ | ||
215 | ref[0] = 0; | ||
216 | } | ||
217 | 185 | ||
218 | /* Find the longest directory prefix */ | 186 | /* Find the longest directory prefix */ |
219 | i = strcspn (wcard, "%*"); | 187 | i = strcspn (wcard, "%*"); |
... | @@ -223,14 +191,9 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -223,14 +191,9 @@ imap4d_list (struct imap4d_session *session, |
223 | if (i) | 191 | if (i) |
224 | { | 192 | { |
225 | size_t reflen = strlen (ref); | 193 | size_t reflen = strlen (ref); |
226 | int addslash = (reflen > 0 | 194 | size_t len = i + reflen; |
227 | && ref[reflen-1] != pfx->delim | ||
228 | && *wcard != pfx->delim); | ||
229 | size_t len = i + reflen + addslash; | ||
230 | 195 | ||
231 | ref = mu_realloc (ref, len); | 196 | ref = mu_realloc (ref, len); |
232 | if (addslash) | ||
233 | ref[reflen++] = pfx->delim; | ||
234 | memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ | 197 | memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ |
235 | ref[len-1] = 0; | 198 | ref[len-1] = 0; |
236 | 199 | ||
... | @@ -278,8 +241,6 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -278,8 +241,6 @@ imap4d_list (struct imap4d_session *session, |
278 | mu_url_sget_path (url, &dir); | 241 | mu_url_sget_path (url, &dir); |
279 | refinfo.dirlen = strlen (dir); | 242 | refinfo.dirlen = strlen (dir); |
280 | 243 | ||
281 | refinfo.pfxlen = strlen (pfx->prefix); | ||
282 | |||
283 | /* The special name INBOX is included in the output from LIST, if | 244 | /* The special name INBOX is included in the output from LIST, if |
284 | INBOX is supported by this server for this user and if the | 245 | INBOX is supported by this server for this user and if the |
285 | uppercase string "INBOX" matches the interpreted reference and | 246 | uppercase string "INBOX" matches the interpreted reference and | ... | ... |
... | @@ -104,7 +104,6 @@ namespace_init (void) | ... | @@ -104,7 +104,6 @@ namespace_init (void) |
104 | } | 104 | } |
105 | pfx->ns = i; | 105 | pfx->ns = i; |
106 | 106 | ||
107 | trim_delim (pfx->prefix, pfx->delim); | ||
108 | trim_delim (pfx->dir, '/'); | 107 | trim_delim (pfx->dir, '/'); |
109 | 108 | ||
110 | rc = mu_assoc_install (prefixes, pfx->prefix, pfx); | 109 | rc = mu_assoc_install (prefixes, pfx->prefix, pfx); |
... | @@ -182,9 +181,7 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name, | ... | @@ -182,9 +181,7 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name, |
182 | { | 181 | { |
183 | size_t pfxlen = strlen (pfx->prefix); | 182 | size_t pfxlen = strlen (pfx->prefix); |
184 | 183 | ||
185 | if (pfxlen <= namelen | 184 | if (pfxlen <= namelen && memcmp (pfx->prefix, name, pfxlen) == 0) |
186 | && memcmp (pfx->prefix, name, pfxlen) == 0 | ||
187 | && (pfxlen == 0 || pfxlen == namelen || name[pfxlen] == pfx->delim)) | ||
188 | { | 185 | { |
189 | char *tmpl, *p; | 186 | char *tmpl, *p; |
190 | 187 | ||
... | @@ -212,10 +209,17 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name, | ... | @@ -212,10 +209,17 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name, |
212 | p = mu_stpcpy (p, pfx->dir); | 209 | p = mu_stpcpy (p, pfx->dir); |
213 | if (*name) | 210 | if (*name) |
214 | { | 211 | { |
215 | *p++ = '/'; | 212 | if (pfx->ns == NS_OTHER |
213 | && pfx->prefix[strlen(pfx->prefix) - 1] != pfx->delim) | ||
214 | { | ||
215 | while (*name && *name != pfx->delim) | ||
216 | name++; | ||
217 | } | ||
218 | else if (*name != pfx->delim) | ||
219 | *p++ = '/'; | ||
216 | translate_delim (p, name, '/', pfx->delim); | 220 | translate_delim (p, name, '/', pfx->delim); |
217 | } | 221 | } |
218 | 222 | ||
219 | return tmpl; | 223 | return tmpl; |
220 | } | 224 | } |
221 | return NULL; | 225 | return NULL; |
... | @@ -230,15 +234,6 @@ i_translate_name (char const *name, int url, int ns, | ... | @@ -230,15 +234,6 @@ i_translate_name (char const *name, int url, int ns, |
230 | char *res = NULL; | 234 | char *res = NULL; |
231 | size_t namelen = strlen (name); | 235 | size_t namelen = strlen (name); |
232 | 236 | ||
233 | #if 0 | ||
234 | FIXME | ||
235 | if (namelen >= 5 | ||
236 | && strcmp (name + namelen - 5, "INBOX") == 0 | ||
237 | && (namelen == 5 && name[namelen - 6] == '/')) | ||
238 | { | ||
239 | } | ||
240 | #endif | ||
241 | |||
242 | rc = mu_assoc_get_iterator (prefixes, &itr); | 237 | rc = mu_assoc_get_iterator (prefixes, &itr); |
243 | if (rc) | 238 | if (rc) |
244 | { | 239 | { |
... | @@ -285,7 +280,10 @@ extract_username (char const *name, struct namespace_prefix const *pfx) | ... | @@ -285,7 +280,10 @@ extract_username (char const *name, struct namespace_prefix const *pfx) |
285 | len = end - p; | 280 | len = end - p; |
286 | else | 281 | else |
287 | len = strlen (p); | 282 | len = strlen (p); |
288 | 283 | ||
284 | if (len == 0) | ||
285 | return mu_strdup (auth_data->name); | ||
286 | |||
289 | user = mu_alloc (len + 1); | 287 | user = mu_alloc (len + 1); |
290 | memcpy (user, p, len); | 288 | memcpy (user, p, len); |
291 | user[len] = 0; | 289 | user[len] = 0; |
... | @@ -310,17 +308,10 @@ namespace_translate_name (char const *name, int url, | ... | @@ -310,17 +308,10 @@ namespace_translate_name (char const *name, int url, |
310 | struct namespace_prefix const *pfx; | 308 | struct namespace_prefix const *pfx; |
311 | char *env[] = ENV_INITIALIZER; | 309 | char *env[] = ENV_INITIALIZER; |
312 | 310 | ||
313 | if (name[0] == '~') | 311 | if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) |
314 | { | 312 | { |
315 | if (name[1] == 0 || name[1] == '/') | 313 | res = mu_strdup (auth_data->mailbox); |
316 | { | 314 | pfx = mu_assoc_get (prefixes, ""); |
317 | if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) | ||
318 | res = mu_strdup (auth_data->mailbox); | ||
319 | else | ||
320 | res = i_translate_name (name, url, NS_PRIVATE, &pfx); | ||
321 | } | ||
322 | else | ||
323 | res = i_translate_name (name, url, NS_OTHER, &pfx); | ||
324 | } | 315 | } |
325 | else | 316 | else |
326 | res = i_translate_name (name, url, NS_MAX, &pfx); | 317 | res = i_translate_name (name, url, NS_MAX, &pfx); |
... | @@ -336,7 +327,7 @@ namespace_translate_name (char const *name, int url, | ... | @@ -336,7 +327,7 @@ namespace_translate_name (char const *name, int url, |
336 | env[ENV_HOME] = real_homedir; | 327 | env[ENV_HOME] = real_homedir; |
337 | break; | 328 | break; |
338 | 329 | ||
339 | case NS_SHARED: | 330 | case NS_OTHER: |
340 | { | 331 | { |
341 | struct mu_auth_data *adata; | 332 | struct mu_auth_data *adata; |
342 | env[ENV_USER] = extract_username (name, pfx); | 333 | env[ENV_USER] = extract_username (name, pfx); |
... | @@ -349,7 +340,7 @@ namespace_translate_name (char const *name, int url, | ... | @@ -349,7 +340,7 @@ namespace_translate_name (char const *name, int url, |
349 | } | 340 | } |
350 | break; | 341 | break; |
351 | 342 | ||
352 | case NS_OTHER: | 343 | case NS_SHARED: |
353 | break; | 344 | break; |
354 | } | 345 | } |
355 | 346 | ... | ... |
... | @@ -76,16 +76,17 @@ LIST_CHECK([empty ref + asterisk],[list02], | ... | @@ -76,16 +76,17 @@ LIST_CHECK([empty ref + asterisk],[list02], |
76 | * LIST (\NoInferiors) NIL INBOX | 76 | * LIST (\NoInferiors) NIL INBOX |
77 | ]) | 77 | ]) |
78 | 78 | ||
79 | # FIXME: I'm not sure whether it should include / in the reply. | ||
79 | LIST_CHECK([root ref + asterisk],[list03], | 80 | LIST_CHECK([root ref + asterisk],[list03], |
80 | ["/" "*"], | 81 | ["/" "*"], |
81 | [dnl | 82 | [dnl |
82 | * LIST (\NoInferiors) "/" bigto.mbox | 83 | * LIST (\NoInferiors) "/" /bigto.mbox |
83 | * LIST (\NoInferiors) "/" mbox | 84 | * LIST (\NoInferiors) "/" /mbox |
84 | * LIST (\NoInferiors) "/" mbox1 | 85 | * LIST (\NoInferiors) "/" /mbox1 |
85 | * LIST (\NoInferiors) "/" relational.mbox | 86 | * LIST (\NoInferiors) "/" /relational.mbox |
86 | * LIST (\NoInferiors) "/" search.mbox | 87 | * LIST (\NoInferiors) "/" /search.mbox |
87 | * LIST (\NoInferiors) "/" sieve.mbox | 88 | * LIST (\NoInferiors) "/" /sieve.mbox |
88 | * LIST (\NoInferiors) "/" teaparty.mbox | 89 | * LIST (\NoInferiors) "/" /teaparty.mbox |
89 | ]) | 90 | ]) |
90 | 91 | ||
91 | LIST_CHECK([absolute reference + asterisk],[list04], | 92 | LIST_CHECK([absolute reference + asterisk],[list04], | ... | ... |
-
Please register or sign in to post a comment