Commit 00c27bc2 00c27bc22c1d032e0b9716bc87abbf6b68cbbb43 by Sergey Poznyakoff

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.
1 parent 5e425f04
...@@ -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],
......