Commit 0255df9a 0255df9a66adad110a45b56a3511b80865725fd0 by Sergey Poznyakoff

Rewrite IMAP namespace support.

* imap4d/imap4d.c (imap4d_cfg_param): other-namespace and
shared-namespace take proper lists as arguments.
(imap4d_session_setup0): Call namespace_init_session.
(main): Call namespace_init.
* imap4d/imap4d.h (set_namespace): Remove.
(namespace_init): Change proto.
(namespace_init_session): New prototype.
(namespace): New declaration.
* imap4d/namespace.c: Rewrite using lists.
* mailbox/cfg_parser.y (parse_param): Cast string to lists if
the parameter has list type.
1 parent 2a45d3c7
1 2008-08-21 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 Rewrite IMAP namespace support.
4 * imap4d/imap4d.c (imap4d_cfg_param): other-namespace and
5 shared-namespace take proper lists as arguments.
6 (imap4d_session_setup0): Call namespace_init_session.
7 (main): Call namespace_init.
8 * imap4d/imap4d.h (set_namespace): Remove.
9 (namespace_init): Change proto.
10 (namespace_init_session): New prototype.
11 (namespace): New declaration.
12 * imap4d/namespace.c: Rewrite using lists.
13 * mailbox/cfg_parser.y (parse_param): Cast string to lists if
14 the parameter has list type.
15
1 2008-08-20 Sergey Poznyakoff <gray@gnu.org.ua> 16 2008-08-20 Sergey Poznyakoff <gray@gnu.org.ua>
2 17
3 Implement ID extension. 18 Implement ID extension.
......
...@@ -173,27 +173,6 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -173,27 +173,6 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state)
173 } 173 }
174 174
175 static int 175 static int
176 cb2_namespace (mu_debug_t debug, const char *arg, void *data)
177 {
178 int what = (int) data;
179 set_namespace (what, arg);
180 return 0;
181 }
182
183 static int
184 cb_other (mu_debug_t debug, void *data, mu_config_value_t *val)
185 {
186 return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_OTHER);
187 }
188
189 static int
190 cb_shared (mu_debug_t debug, void *data, mu_config_value_t *val)
191 {
192 return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_SHARED);
193 return 0;
194 }
195
196 static int
197 cb_mode (mu_debug_t debug, void *data, mu_config_value_t *val) 176 cb_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
198 { 177 {
199 char *p; 178 char *p;
...@@ -304,12 +283,12 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val) ...@@ -304,12 +283,12 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val)
304 } 283 }
305 284
306 static struct mu_cfg_param imap4d_cfg_param[] = { 285 static struct mu_cfg_param imap4d_cfg_param[] = {
307 { "other-namespace", mu_cfg_callback, NULL, 0, cb_other, 286 { "other-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_OTHER],
308 N_("Set other users' namespace. Argument is a colon-separated list " 287 0, NULL,
309 "of directories comprising the namespace.") }, 288 N_("Set other users' namespace.") },
310 { "shared-namespace", mu_cfg_callback, NULL, 0, cb_shared, 289 { "shared-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_SHARED],
311 N_("Set shared namespace. Argument is a colon-separated list " 290 0, NULL,
312 "of directories comprising the namespace.") }, 291 N_("Set shared namespace.") },
313 { "login-disabled", mu_cfg_bool, &login_disabled, 0, NULL, 292 { "login-disabled", mu_cfg_bool, &login_disabled, 0, NULL,
314 N_("Disable LOGIN command.") }, 293 N_("Disable LOGIN command.") },
315 { "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL, 294 { "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
...@@ -351,7 +330,7 @@ imap4d_session_setup0 () ...@@ -351,7 +330,7 @@ imap4d_session_setup0 ()
351 setuid (auth_data->uid); 330 setuid (auth_data->uid);
352 331
353 util_chdir (homedir); 332 util_chdir (homedir);
354 namespace_init (homedir); 333 namespace_init_session (homedir);
355 mu_diag_output (MU_DIAG_INFO, 334 mu_diag_output (MU_DIAG_INFO,
356 _("User `%s' logged in (source: %s)"), auth_data->name, 335 _("User `%s' logged in (source: %s)"), auth_data->name,
357 auth_data->source); 336 auth_data->source);
...@@ -526,6 +505,8 @@ main (int argc, char **argv) ...@@ -526,6 +505,8 @@ main (int argc, char **argv)
526 if (tls_required) 505 if (tls_required)
527 imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED); 506 imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED);
528 #endif 507 #endif
508
509 namespace_init ();
529 510
530 auth_gssapi_init (); 511 auth_gssapi_init ();
531 auth_gsasl_init (); 512 auth_gsasl_init ();
......
...@@ -277,8 +277,10 @@ extern int imap4d_bye (int); ...@@ -277,8 +277,10 @@ extern int imap4d_bye (int);
277 extern int imap4d_bye0 (int reason, struct imap4d_command *command); 277 extern int imap4d_bye0 (int reason, struct imap4d_command *command);
278 278
279 /* Namespace functions */ 279 /* Namespace functions */
280 extern int set_namespace (int i, const char *str); 280 extern mu_list_t namespace[NS_MAX];
281 extern int namespace_init (char *path); 281
282 extern int namespace_init_session (char *path);
283 extern void namespace_init (void);
282 extern char * namespace_getfullpath (char *name, const char *delim); 284 extern char * namespace_getfullpath (char *name, const char *delim);
283 extern char * namespace_checkfullpath (char *name, const char *pattern, 285 extern char * namespace_checkfullpath (char *name, const char *pattern,
284 const char *delim); 286 const char *delim);
......
...@@ -18,38 +18,9 @@ ...@@ -18,38 +18,9 @@
18 18
19 #include "imap4d.h" 19 #include "imap4d.h"
20 20
21 /* FIXME: Rewrite using mu_list_t */
22
23 /*FIXME: should be global? */
24 typedef int (*nsfp_t) (void *closure, int ns, char *path, int delim); 21 typedef int (*nsfp_t) (void *closure, int ns, char *path, int delim);
25 22
26 struct namespace_t 23 mu_list_t namespace[NS_MAX];
27 {
28 int subdir_c;
29 char **subdir_v;
30 };
31
32 struct namespace_t namespace[NS_MAX];
33
34 /* Note: str is not supposed to be NULL */
35 int
36 set_namespace (int i, const char *str)
37 {
38 struct namespace_t *ns = namespace + i;
39 int argc;
40 char **argv;
41
42 mu_argcv_get (str, ":", NULL, &argc, &argv);
43
44 ns->subdir_v = mu_realloc (ns->subdir_v,
45 (ns->subdir_c + argc) * sizeof (ns->subdir_v[0]));
46 for (i = 0; i < argc; i++)
47 ns->subdir_v[ns->subdir_c++] = mu_normalize_path (argv[i], "/");
48 /* Free only argv, not its members */
49 free (argv);
50
51 return 0;
52 }
53 24
54 static char * 25 static char *
55 printable_pathname (char *str) 26 printable_pathname (char *str)
...@@ -63,36 +34,59 @@ printable_pathname (char *str) ...@@ -63,36 +34,59 @@ printable_pathname (char *str)
63 return str; 34 return str;
64 } 35 }
65 36
66 static void 37 static int
67 print_namespace (int n) 38 print_namespace_fun (void *item, void *data)
68 { 39 {
69 int i; 40 int *pcount = data;
70 41 char *dir = printable_pathname (item);
71 if (namespace[n].subdir_c == 0) 42 char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
72 { 43 if ((*pcount)++)
73 util_send ("NIL"); 44 util_send (" ");
74 return; 45 util_send ("(\"%s%s\" \"/\")", dir, suf);
75 } 46 return 0;
47 }
76 48
77 util_send ("("); 49 static void
78 for (i = 0; i < namespace[n].subdir_c; i++) 50 print_namespace (int nsid)
51 {
52 mu_list_t list = namespace[nsid];
53 if (!list)
54 util_send ("NIL");
55 else
79 { 56 {
80 char *dir = printable_pathname (namespace[n].subdir_v[i]); 57 int count;
81 char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : ""; 58 count = 0;
82 util_send ("(\"%s%s\" \"/\")", dir, suf); 59 util_send ("(");
60 mu_list_do (list, print_namespace_fun, &count);
61 util_send (")");
83 } 62 }
84 util_send (")");
85 } 63 }
86 64
65 struct ns_closure
66 {
67 int id;
68 nsfp_t fun;
69 void *closure;
70 };
71
72 static int
73 _enum_fun (void *item, void *data)
74 {
75 struct ns_closure *nsp = data;
76 return nsp->fun (nsp->closure, nsp->id, (char*) item, '/');
77 }
78
87 static int 79 static int
88 namespace_enumerate (int ns, nsfp_t f, void *closure) 80 namespace_enumerate (int id, nsfp_t f, void *closure)
89 { 81 {
90 int i, rc; 82 int i, rc;
83 struct ns_closure nsc;
91 84
92 for (i = 0; i < namespace[ns].subdir_c; i++) 85 nsc.id = id;
93 if ((rc = (*f) (closure, ns, namespace[ns].subdir_v[i], '/'))) 86 nsc.fun = f;
94 return rc; 87 nsc.closure = closure;
95 return 0; 88 return namespace[id] == 0 ? 0 :
89 mu_list_do (namespace[id], _enum_fun, &nsc);
96 } 90 }
97 91
98 static int 92 static int
...@@ -137,7 +131,7 @@ imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok) ...@@ -137,7 +131,7 @@ imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok)
137 return util_finish (command, RESP_OK, "Completed"); 131 return util_finish (command, RESP_OK, "Completed");
138 } 132 }
139 133
140 134
141 struct namespace_info 135 struct namespace_info
142 { 136 {
143 char *name; 137 char *name;
...@@ -240,8 +234,45 @@ namespace_getfullpath (char *name, const char *delim) ...@@ -240,8 +234,45 @@ namespace_getfullpath (char *name, const char *delim)
240 } 234 }
241 235
242 int 236 int
243 namespace_init (char *path) 237 namespace_init_session (char *path)
244 { 238 {
245 set_namespace (NS_PRIVATE, path); 239 mu_list_create (&namespace[NS_PRIVATE]);
240 mu_list_append (namespace[NS_PRIVATE],
241 mu_strdup (mu_normalize_path (path, "/")));
246 return 0; 242 return 0;
247 } 243 }
244
245 static int
246 normalize_fun (void *item, void *data)
247 {
248 char *name = item;
249 mu_list_t list = data;
250 return mu_list_append (list,
251 mu_strdup (mu_normalize_path (name, "/")));
252 }
253
254 static void
255 free_item (void *item)
256 {
257 free (item);
258 }
259
260 void
261 namespace_init ()
262 {
263 int i;
264
265 for (i = 0; i < NS_MAX; i++)
266 {
267 if (namespace[i])
268 {
269 mu_list_t list;
270 mu_list_create (&list);
271 mu_list_set_destroy_item (list, free_item);
272 mu_list_do (namespace[i], normalize_fun, list);
273 mu_list_set_destroy_item (namespace[i], free_item);
274 mu_list_destroy (&namespace[i]);
275 namespace[i] = list;
276 }
277 }
278 }
......
...@@ -1088,6 +1088,27 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node) ...@@ -1088,6 +1088,27 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
1088 { 1088 {
1089 clos.sdata = sdata; 1089 clos.sdata = sdata;
1090 clos.locus = &node->locus; 1090 clos.locus = &node->locus;
1091 switch (node->label->type)
1092 {
1093 case MU_CFG_LIST:
1094 break;
1095
1096 case MU_CFG_STRING:
1097 {
1098 mu_list_t list;
1099 mu_list_create (&list);
1100 mu_list_append (list, config_value_dup (node->label));
1101 node->label->type = MU_CFG_LIST;
1102 node->label->v.list = list;
1103 }
1104 break;
1105
1106 case MU_CFG_ARRAY:
1107 _mu_cfg_perror (sdata->tree->debug, &node->locus,
1108 _("expected list, but found array"));
1109 return 1;
1110 }
1111
1091 mu_list_create (&clos.list); 1112 mu_list_create (&clos.list);
1092 mu_list_do (node->label->v.list, _set_fun, &clos); 1113 mu_list_do (node->label->v.list, _set_fun, &clos);
1093 *(mu_list_t*)tgt = clos.list; 1114 *(mu_list_t*)tgt = clos.list;
......