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.
Showing
5 changed files
with
324 additions
and
91 deletions
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment