Commit 014c99be 014c99be6f811a0e099f3c0013a0a0bcc6316a1c by Sergey Poznyakoff

Further improvements of IMAP LIST functionality

* imap4d/list.c (list_fun): Ignore names that contain delimiter
as part of their name (untranslatable names);
Don't insert spurious separators.
(list_ref): Make sure a pathnames are properly separated from
namespace prefixes.
(imap4d_list): Fix eventual use of uninitialized pfx.
* imap4d/namespace.c (prefix_translate_name): Allow for NS_OTHER
prefixes ending with a delimiter.
(extract_username): Return NULL if prefix without trailing delimiter
was used.
* imap4d/tests/atlocal.in (make_config): Add more namespace prefixes.
* imap4d/tests/list.at: Add more tests.
* libmailutils/string/expvar.c (exp_getvar): Return MU_WRDSE_UNDEF if
the variable is defined, but has NULL value.
1 parent 8282a0f6
...@@ -42,12 +42,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -42,12 +42,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
42 && refinfo->pfx->record != resp->format) 42 && refinfo->pfx->record != resp->format)
43 return 0; 43 return 0;
44 44
45 name = resp->name; 45 name = resp->name + refinfo->dirlen;
46 size = strlen (name); 46
47 if (size == refinfo->reflen + 6 47 /* There can be only one INBOX */
48 && memcmp (name + refinfo->reflen + 1, "INBOX", 5) == 0) 48 if (refinfo->reflen == 0 && strcmp (name, "INBOX") == 0)
49 return 0;
50
51 /* Ignore mailboxes that contain delimiter as part of their name */
52 if (refinfo->pfx->delim != resp->separator
53 && strchr (name, refinfo->pfx->delim))
49 return 0; 54 return 0;
50 55
51 io_sendf ("* %s", "LIST ("); 56 io_sendf ("* %s", "LIST (");
52 if ((resp->type & (MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY)) 57 if ((resp->type & (MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY))
53 == (MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY)) 58 == (MU_FOLDER_ATTRIBUTE_FILE|MU_FOLDER_ATTRIBUTE_DIRECTORY))
...@@ -59,7 +64,6 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -59,7 +64,6 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
59 64
60 io_sendf (") \"%c\" ", refinfo->pfx->delim); 65 io_sendf (") \"%c\" ", refinfo->pfx->delim);
61 66
62 name = resp->name + refinfo->dirlen + 1;
63 size = strlen (name) + refinfo->reflen + 2; 67 size = strlen (name) + refinfo->reflen + 2;
64 if (size > refinfo->bufsize) 68 if (size > refinfo->bufsize)
65 { 69 {
...@@ -77,9 +81,8 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -77,9 +81,8 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
77 81
78 if (refinfo->refptr[0]) 82 if (refinfo->refptr[0])
79 { 83 {
80 p = mu_stpcpy (refinfo->buf, refinfo->refptr); 84 memcpy (refinfo->buf, refinfo->refptr, refinfo->reflen);
81 if (refinfo->reflen == strlen (refinfo->pfx->prefix) - 1) 85 p = refinfo->buf + refinfo->reflen;
82 *p++ = refinfo->pfx->delim;
83 } 86 }
84 else 87 else
85 p = refinfo->buf; 88 p = refinfo->buf;
...@@ -101,6 +104,21 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -101,6 +104,21 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
101 } 104 }
102 105
103 static int 106 static int
107 match_pfx (struct namespace_prefix const *pfx, char const *ref)
108 {
109 char const *p = pfx->prefix, *q = ref;
110
111 for (; *q; p++, q++)
112 {
113 if (*p == 0 || *p != *q)
114 return 0;
115 }
116 if (*p == pfx->delim)
117 p++;
118 return *p == 0;
119 }
120
121 static int
104 list_ref (char const *ref, char const *wcard, char const *cwd, 122 list_ref (char const *ref, char const *wcard, char const *cwd,
105 struct namespace_prefix const *pfx) 123 struct namespace_prefix const *pfx)
106 { 124 {
...@@ -110,8 +128,7 @@ list_ref (char const *ref, char const *wcard, char const *cwd, ...@@ -110,8 +128,7 @@ list_ref (char const *ref, char const *wcard, char const *cwd,
110 char const *dir; 128 char const *dir;
111 mu_url_t url; 129 mu_url_t url;
112 130
113 if (pfx->ns == NS_OTHER && strcmp (ref, pfx->prefix) == 0 131 if (pfx->ns == NS_OTHER && match_pfx (pfx, ref) && strpbrk (wcard, "*%"))
114 && strpbrk (wcard, "*%"))
115 { 132 {
116 /* [A] server MAY return NO to such a LIST command, requiring that a 133 /* [A] server MAY return NO to such a LIST command, requiring that a
117 user name be included with the Other Users' Namespace prefix 134 user name be included with the Other Users' Namespace prefix
...@@ -128,18 +145,23 @@ list_ref (char const *ref, char const *wcard, char const *cwd, ...@@ -128,18 +145,23 @@ list_ref (char const *ref, char const *wcard, char const *cwd,
128 145
129 memset (&refinfo, 0, sizeof refinfo); 146 memset (&refinfo, 0, sizeof refinfo);
130 147
148 refinfo.pfx = pfx;
131 /* Note: original reference would always coincide with the pfx->prefix, 149 /* Note: original reference would always coincide with the pfx->prefix,
132 if it weren't for the special handling of NS_OTHER namespace, where 150 if it weren't for the special handling of NS_OTHER namespace, where
133 the part between the prefix and the first delimiter is considered to 151 the part between the prefix and the first delimiter is considered to
134 be a user name and is handled as part of the actual prefix. */ 152 be a user name and is handled as part of the actual prefix. */
135 refinfo.refptr = ref; 153 refinfo.refptr = ref;
136 refinfo.reflen = strlen (ref); 154 refinfo.reflen = strlen (ref);
137 refinfo.pfx = pfx; 155
138
139 mu_folder_get_url (folder, &url); 156 mu_folder_get_url (folder, &url);
140 mu_url_sget_path (url, &dir); 157 mu_url_sget_path (url, &dir);
141 refinfo.dirlen = strlen (dir); 158 refinfo.dirlen = strlen (dir);
142 159
160 if (refinfo.refptr[refinfo.reflen-1] == pfx->delim)
161 refinfo.reflen--;
162 else if (strcmp (ref, pfx->prefix) == 0)
163 refinfo.dirlen++;
164
143 /* The special name INBOX is included in the output from LIST, if 165 /* The special name INBOX is included in the output from LIST, if
144 INBOX is supported by this server for this user and if the 166 INBOX is supported by this server for this user and if the
145 uppercase string "INBOX" matches the interpreted reference and 167 uppercase string "INBOX" matches the interpreted reference and
...@@ -236,8 +258,7 @@ imap4d_list (struct imap4d_session *session, ...@@ -236,8 +258,7 @@ imap4d_list (struct imap4d_session *session,
236 else 258 else
237 { 259 {
238 char *cwd = NULL; 260 char *cwd = NULL;
239 size_t i; 261 struct namespace_prefix const *pfx = NULL;
240 struct namespace_prefix const *pfx;
241 262
242 if (ref[0] == 0) 263 if (ref[0] == 0)
243 { 264 {
...@@ -254,27 +275,37 @@ imap4d_list (struct imap4d_session *session, ...@@ -254,27 +275,37 @@ imap4d_list (struct imap4d_session *session,
254 } 275 }
255 else 276 else
256 ref = mu_strdup (ref); 277 ref = mu_strdup (ref);
257 278
258 /* Find the longest directory prefix */ 279 if (!pfx)
259 i = strcspn (wcard, "%*"); 280 {
260 if (wcard[i]) 281 cwd = namespace_translate_name (ref, &pfx);
282 if (cwd)
283 free (cwd);
284 }
285
286 if (pfx)
261 { 287 {
262 while (i > 0 && wcard[i - 1] != pfx->delim) 288 /* Find the longest directory prefix */
263 i--; 289 size_t i = strcspn (wcard, "%*");
264 /* Append it to the reference */ 290 if (wcard[i])
265 if (i)
266 { 291 {
267 size_t reflen = strlen (ref); 292 while (i > 0 && wcard[i - 1] != pfx->delim)
268 size_t len = i + reflen; 293 i--;
269 294 /* Append it to the reference */
270 ref = mu_realloc (ref, len); 295 if (i)
271 memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ 296 {
272 ref[len-1] = 0; 297 size_t reflen = strlen (ref);
273 298 size_t len = i + reflen;
274 wcard += i; 299
300 ref = mu_realloc (ref, len);
301 memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */
302 ref[len-1] = 0;
303
304 wcard += i;
305 }
275 } 306 }
276 } 307 }
277 308
278 cwd = namespace_translate_name (ref, &pfx); 309 cwd = namespace_translate_name (ref, &pfx);
279 if (cwd) 310 if (cwd)
280 status = list_ref (ref, wcard, cwd, pfx); 311 status = list_ref (ref, wcard, cwd, pfx);
......
...@@ -188,9 +188,11 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name, ...@@ -188,9 +188,11 @@ prefix_translate_name (struct namespace_prefix const *pfx, char const *name,
188 p = mu_stpcpy (p, pfx->dir); 188 p = mu_stpcpy (p, pfx->dir);
189 if (*name) 189 if (*name)
190 { 190 {
191 if (pfx->ns == NS_OTHER 191 if (pfx->ns == NS_OTHER)
192 && pfx->prefix[strlen(pfx->prefix) - 1] != pfx->delim)
193 { 192 {
193 if (pfx->prefix[strlen (pfx->prefix) - 1] == pfx->delim)
194 ++name;
195
194 while (*name && *name != pfx->delim) 196 while (*name && *name != pfx->delim)
195 name++; 197 name++;
196 } 198 }
...@@ -246,10 +248,15 @@ translate_name (char const *name, struct namespace_prefix const **return_pfx) ...@@ -246,10 +248,15 @@ translate_name (char const *name, struct namespace_prefix const **return_pfx)
246 static char * 248 static char *
247 extract_username (char const *name, struct namespace_prefix const *pfx) 249 extract_username (char const *name, struct namespace_prefix const *pfx)
248 { 250 {
249 char const *p = name + strlen (pfx->prefix); 251 char const *p;
250 char *end = strchr (p, pfx->delim); 252 char *end;
251 char *user; 253 char *user;
252 size_t len; 254 size_t len;
255
256 if (strlen (name) < strlen (pfx->prefix))
257 return NULL;
258 p = name + strlen (pfx->prefix);
259 end = strchr (p, pfx->delim);
253 260
254 if (end) 261 if (end)
255 len = end - p; 262 len = end - p;
......
...@@ -22,8 +22,22 @@ namespace personal { ...@@ -22,8 +22,22 @@ namespace personal {
22 prefix "" { 22 prefix "" {
23 directory "$HOMEDIR"; 23 directory "$HOMEDIR";
24 } 24 }
25 prefix "~/" { 25 prefix "#archive:" {
26 directory "$HOMEDIR"; 26 directory "$CWD/archive";
27 delimiter ".";
28 }
29 prefix "archive." {
30 directory "$CWD/archive";
31 delimiter ".";
32 }
33 }
34
35 namespace other {
36 prefix "~" {
37 directory "$CWD/home/\$user";
38 }
39 prefix "other/" {
40 directory "$CWD/home/\$user";
27 } 41 }
28 } 42 }
29 43
......
...@@ -18,15 +18,15 @@ m4_pushdef([IMAP4D_HOMEDIR],[spool]) ...@@ -18,15 +18,15 @@ m4_pushdef([IMAP4D_HOMEDIR],[spool])
18 18
19 dnl LIST_CHECK([NAME],[KW],[ARG],[OUTPUT],[EXTRA-CODE],[filter,][expand] 19 dnl LIST_CHECK([NAME],[KW],[ARG],[OUTPUT],[EXTRA-CODE],[filter,][expand]
20 m4_define([LIST_CHECK],[ 20 m4_define([LIST_CHECK],[
21 AT_SETUP([$1]) 21 AT_SETUP([m4_if([$1],,[list $3],[$1])])
22 AT_KEYWORDS([list $2]) 22 AT_KEYWORDS([list $2])
23 23
24 IMAP4D_CHECK([ 24 IMAP4D_CHECK([
25 mkdir IMAP4D_HOMEDIR 25 mkdir IMAP4D_HOMEDIR
26 m4_foreach([MAILBOX],[bigto.mbox,mbox1,mbox,relational.mbox,relational.mbox, 26 for name in bigto relational search sieve teaparty
27 search.mbox,sieve.mbox,teaparty.mbox],[ 27 do
28 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/MAILBOX,IMAP4D_HOMEDIR) 28 cp $abs_top_srcdir/testsuite/spool/$name.mbox IMAP4D_HOMEDIR/$name
29 ]) 29 done
30 $5 30 $5
31 ], 31 ],
32 [1 LIST $3 32 [1 LIST $3
...@@ -39,54 +39,246 @@ AT_CLEANUP ...@@ -39,54 +39,246 @@ AT_CLEANUP
39 ]) 39 ])
40 40
41 dnl ---------------------------------------------------------------------- 41 dnl ----------------------------------------------------------------------
42 LIST_CHECK([asterisk],[list00], 42 LIST_CHECK([],[list02],
43 ["~" "*"], 43 ["" "*"],
44 [dnl 44 [dnl
45 * LIST (\NoInferiors) "/" ~/bigto.mbox 45 * LIST (\NoInferiors) "/" bigto
46 * LIST (\NoInferiors) "/" ~/mbox 46 * LIST (\NoInferiors) "/" relational
47 * LIST (\NoInferiors) "/" ~/mbox1 47 * LIST (\NoInferiors) "/" search
48 * LIST (\NoInferiors) "/" ~/relational.mbox 48 * LIST (\NoInferiors) "/" sieve
49 * LIST (\NoInferiors) "/" ~/search.mbox 49 * LIST (\NoInferiors) "/" teaparty
50 * LIST (\NoInferiors) "/" ~/sieve.mbox 50 * LIST (\NoInferiors) NIL INBOX
51 * LIST (\NoInferiors) "/" ~/teaparty.mbox
52 ]) 51 ])
53 52
54 LIST_CHECK([percent],[list01], 53 LIST_CHECK([],[list02],
55 ["~" "%"], 54 ["" "%"],
56 [dnl 55 [dnl
57 * LIST (\NoInferiors) "/" ~/bigto.mbox 56 * LIST (\NoInferiors) "/" bigto
58 * LIST (\NoInferiors) "/" ~/mbox 57 * LIST (\NoInferiors) "/" relational
59 * LIST (\NoInferiors) "/" ~/mbox1 58 * LIST (\NoInferiors) "/" search
60 * LIST (\NoInferiors) "/" ~/relational.mbox 59 * LIST (\NoInferiors) "/" sieve
61 * LIST (\NoInferiors) "/" ~/search.mbox 60 * LIST (\NoInferiors) "/" teaparty
62 * LIST (\NoInferiors) "/" ~/sieve.mbox 61 * LIST (\NoInferiors) NIL INBOX
63 * LIST (\NoInferiors) "/" ~/teaparty.mbox
64 ]) 62 ])
65 63
66 LIST_CHECK([empty ref + asterisk],[list02], 64 LIST_CHECK([duplicate INBOX],[list02],
67 ["" "*"], 65 ["" "%"],
66 [dnl
67 * LIST (\NoInferiors) "/" bigto
68 * LIST (\NoInferiors) "/" relational
69 * LIST (\NoInferiors) "/" search
70 * LIST (\NoInferiors) "/" sieve
71 * LIST (\NoInferiors) "/" teaparty
72 * LIST (\NoInferiors) NIL INBOX
73 ],
74 [cp $abs_top_srcdir/testsuite/spool/mbox IMAP4D_HOMEDIR/INBOX
75 ])
76
77 LIST_CHECK([],[list07],
78 ["" INBOX],
68 [dnl 79 [dnl
69 * LIST (\NoInferiors) "/" bigto.mbox
70 * LIST (\NoInferiors) "/" mbox
71 * LIST (\NoInferiors) "/" mbox1
72 * LIST (\NoInferiors) "/" relational.mbox
73 * LIST (\NoInferiors) "/" search.mbox
74 * LIST (\NoInferiors) "/" sieve.mbox
75 * LIST (\NoInferiors) "/" teaparty.mbox
76 * LIST (\NoInferiors) NIL INBOX 80 * LIST (\NoInferiors) NIL INBOX
77 ]) 81 ])
78 82
83 LIST_CHECK([],[list08],
84 ["" "search"],
85 [dnl
86 * LIST (\NoInferiors) "/" search
87 ])
88
89 LIST_CHECK([],[],
90 ["" "#archive:*"],
91 [* LIST (\NoInferiors) "." #archive:mbox
92 * LIST (\NoInferiors) "." #archive:old.mbox1
93 * LIST (\NoInferiors) "." #archive:old.very.saved
94 * LIST (\NoSelect) "." #archive:old
95 * LIST (\NoSelect) "." #archive:old.very
96 ],
97 [mkdir archive archive/old archive/old/very
98 cp $abs_top_srcdir/testsuite/spool/mbox archive
99 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
100 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
101 ])
102
103 LIST_CHECK([],[],
104 ["" "#archive:%"],
105 [* LIST (\NoInferiors) "." #archive:mbox
106 * LIST (\NoSelect) "." #archive:old
107 ],
108 [mkdir archive archive/old archive/old/very
109 cp $abs_top_srcdir/testsuite/spool/mbox archive
110 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
111 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
112 ])
113
114 LIST_CHECK([],[],
115 ["" "archive.*"],
116 [* LIST (\NoInferiors) "." archive.mbox
117 * LIST (\NoInferiors) "." archive.old.mbox1
118 * LIST (\NoInferiors) "." archive.old.very.saved
119 * LIST (\NoSelect) "." archive.old
120 * LIST (\NoSelect) "." archive.old.very
121 ],
122 [mkdir archive archive/old archive/old/very
123 cp $abs_top_srcdir/testsuite/spool/mbox archive
124 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
125 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
126 ])
127
128 LIST_CHECK([],[],
129 ["archive" "*"],
130 [* LIST (\NoInferiors) "." archive.mbox
131 * LIST (\NoInferiors) "." archive.old.mbox1
132 * LIST (\NoInferiors) "." archive.old.very.saved
133 * LIST (\NoSelect) "." archive.old
134 * LIST (\NoSelect) "." archive.old.very
135 ],
136 [mkdir archive archive/old archive/old/very
137 cp $abs_top_srcdir/testsuite/spool/mbox archive
138 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
139 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
140 ])
141
142 LIST_CHECK([],[],
143 ["archive." "*"],
144 [* LIST (\NoInferiors) "." archive.mbox
145 * LIST (\NoInferiors) "." archive.old.mbox1
146 * LIST (\NoInferiors) "." archive.old.very.saved
147 * LIST (\NoSelect) "." archive.old
148 * LIST (\NoSelect) "." archive.old.very
149 ],
150 [mkdir archive archive/old archive/old/very
151 cp $abs_top_srcdir/testsuite/spool/mbox archive
152 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
153 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
154 ])
155
156 LIST_CHECK([],[],
157 ["archive." "*"],
158 [* LIST (\NoInferiors) "." archive.mbox
159 * LIST (\NoInferiors) "." archive.old.mbox1
160 * LIST (\NoInferiors) "." archive.old.very.saved
161 * LIST (\NoSelect) "." archive.old
162 * LIST (\NoSelect) "." archive.old.very
163 ],
164 [mkdir archive archive/old archive/old/very
165 cp $abs_top_srcdir/testsuite/spool/mbox archive
166 cp $abs_top_srcdir/testsuite/spool/mbox archive/mbox.1
167 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old
168 cp $abs_top_srcdir/testsuite/spool/mbox1 archive/old/very/saved
169 ])
170
171 LIST_CHECK([],[],
172 ["~" "*"],
173 [1 NO LIST The requested item could not be found
174 ])
175
176 LIST_CHECK([],[],
177 ["~foo" "%"],
178 [* LIST (\NoInferiors) "/" ~foo/mbox
179 * LIST (\NoSelect) "/" ~foo/dir
180 ],
181 [mkdir home home/foo home/foo/dir home/bar
182 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
183 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
184 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
185 ])
186
187 LIST_CHECK([],[],
188 ["~foo" "*"],
189 [* LIST (\NoInferiors) "/" ~foo/dir/saved
190 * LIST (\NoInferiors) "/" ~foo/mbox
191 * LIST (\NoSelect) "/" ~foo/dir
192 ],
193 [mkdir home home/foo home/foo/dir home/bar
194 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
195 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
196 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
197 ])
198
199 LIST_CHECK([],[],
200 ["" "~foo/*"],
201 [* LIST (\NoInferiors) "/" ~foo/dir/saved
202 * LIST (\NoInferiors) "/" ~foo/mbox
203 * LIST (\NoSelect) "/" ~foo/dir
204 ],
205 [mkdir home home/foo home/foo/dir home/bar
206 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
207 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
208 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
209 ])
210
211 LIST_CHECK([],[],
212 ["~foo" "%/*"],
213 [* LIST (\NoInferiors) "/" ~foo/dir/saved
214 ],
215 [mkdir home home/foo home/foo/dir home/bar
216 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
217 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
218 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
219 ])
220
221 # ###
222
223 LIST_CHECK([],[],
224 ["other" "*"],
225 [1 NO LIST The requested item could not be found
226 ])
227
228 LIST_CHECK([],[],
229 ["other/foo" "%"],
230 [* LIST (\NoInferiors) "/" other/foo/mbox
231 * LIST (\NoSelect) "/" other/foo/dir
232 ],
233 [mkdir home home/foo home/foo/dir home/bar
234 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
235 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
236 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
237 ])
238
239 LIST_CHECK([],[],
240 ["other/foo" "*"],
241 [* LIST (\NoInferiors) "/" other/foo/dir/saved
242 * LIST (\NoInferiors) "/" other/foo/mbox
243 * LIST (\NoSelect) "/" other/foo/dir
244 ],
245 [mkdir home home/foo home/foo/dir home/bar
246 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
247 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
248 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
249 ])
250
251 LIST_CHECK([],[],
252 ["" "other/foo/*"],
253 [* LIST (\NoInferiors) "/" other/foo/dir/saved
254 * LIST (\NoInferiors) "/" other/foo/mbox
255 * LIST (\NoSelect) "/" other/foo/dir
256 ],
257 [mkdir home home/foo home/foo/dir home/bar
258 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
259 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
260 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
261 ])
262
263 LIST_CHECK([],[],
264 ["other/foo" "%/*"],
265 [* LIST (\NoInferiors) "/" other/foo/dir/saved
266 ],
267 [mkdir home home/foo home/foo/dir home/bar
268 cp $abs_top_srcdir/testsuite/spool/mbox home/foo
269 cp $abs_top_srcdir/testsuite/spool/mbox1 home/foo/dir/saved
270 cp $abs_top_srcdir/testsuite/spool/mbox1 home/bar
271 ])
272
79 # FIXME: I'm not sure whether it should include / in the reply. 273 # FIXME: I'm not sure whether it should include / in the reply.
80 LIST_CHECK([root ref + asterisk],[list03], 274 LIST_CHECK([root ref + asterisk],[list03],
81 ["/" "*"], 275 ["/" "*"],
82 [dnl 276 [dnl
83 * LIST (\NoInferiors) "/" /bigto.mbox 277 * LIST (\NoInferiors) "/" /bigto
84 * LIST (\NoInferiors) "/" /mbox 278 * LIST (\NoInferiors) "/" /relational
85 * LIST (\NoInferiors) "/" /mbox1 279 * LIST (\NoInferiors) "/" /search
86 * LIST (\NoInferiors) "/" /relational.mbox 280 * LIST (\NoInferiors) "/" /sieve
87 * LIST (\NoInferiors) "/" /search.mbox 281 * LIST (\NoInferiors) "/" /teaparty
88 * LIST (\NoInferiors) "/" /sieve.mbox
89 * LIST (\NoInferiors) "/" /teaparty.mbox
90 ]) 282 ])
91 283
92 LIST_CHECK([absolute reference + asterisk],[list04], 284 LIST_CHECK([absolute reference + asterisk],[list04],
...@@ -110,18 +302,6 @@ LIST_CHECK([absolute reference + mailbox],[list06], ...@@ -110,18 +302,6 @@ LIST_CHECK([absolute reference + mailbox],[list06],
110 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder) 302 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
111 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)]) 303 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
112 304
113 LIST_CHECK([empty reference + INBOX],[list07],
114 ["" INBOX],
115 [dnl
116 * LIST (\NoInferiors) NIL INBOX
117 ])
118
119 LIST_CHECK([empty reference + mailbox],[list08],
120 ["" "search.mbox"],
121 [dnl
122 * LIST (\NoInferiors) "/" search.mbox
123 ])
124
125 dnl ---------------------------------------------------------------------- 305 dnl ----------------------------------------------------------------------
126 306
127 m4_popdef([IMAP4D_HOMEDIR]) 307 m4_popdef([IMAP4D_HOMEDIR])
......
...@@ -77,7 +77,8 @@ exp_getvar (char **ret, const char *vptr, size_t vlen, void *data) ...@@ -77,7 +77,8 @@ exp_getvar (char **ret, const char *vptr, size_t vlen, void *data)
77 return MU_WRDSE_NOSPACE; 77 return MU_WRDSE_NOSPACE;
78 *ret = s; 78 *ret = s;
79 } 79 }
80 80 else
81 rc = MU_WRDSE_UNDEF;
81 return rc; 82 return rc;
82 } 83 }
83 84
......