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
2008-08-21 Sergey Poznyakoff <gray@gnu.org.ua>
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.
2008-08-20 Sergey Poznyakoff <gray@gnu.org.ua>
Implement ID extension.
......
......@@ -173,27 +173,6 @@ imap4d_parse_opt (int key, char *arg, struct argp_state *state)
}
static int
cb2_namespace (mu_debug_t debug, const char *arg, void *data)
{
int what = (int) data;
set_namespace (what, arg);
return 0;
}
static int
cb_other (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_OTHER);
}
static int
cb_shared (mu_debug_t debug, void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (debug, val, cb2_namespace, (void*)NS_SHARED);
return 0;
}
static int
cb_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
{
char *p;
......@@ -304,12 +283,12 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val)
}
static struct mu_cfg_param imap4d_cfg_param[] = {
{ "other-namespace", mu_cfg_callback, NULL, 0, cb_other,
N_("Set other users' namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "shared-namespace", mu_cfg_callback, NULL, 0, cb_shared,
N_("Set shared namespace. Argument is a colon-separated list "
"of directories comprising the namespace.") },
{ "other-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_OTHER],
0, NULL,
N_("Set other users' namespace.") },
{ "shared-namespace", MU_CFG_LIST_OF(mu_cfg_string), &namespace[NS_SHARED],
0, NULL,
N_("Set shared namespace.") },
{ "login-disabled", mu_cfg_bool, &login_disabled, 0, NULL,
N_("Disable LOGIN command.") },
{ "create-home-dir", mu_cfg_bool, &create_home_dir, 0, NULL,
......@@ -351,7 +330,7 @@ imap4d_session_setup0 ()
setuid (auth_data->uid);
util_chdir (homedir);
namespace_init (homedir);
namespace_init_session (homedir);
mu_diag_output (MU_DIAG_INFO,
_("User `%s' logged in (source: %s)"), auth_data->name,
auth_data->source);
......@@ -526,6 +505,8 @@ main (int argc, char **argv)
if (tls_required)
imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED);
#endif
namespace_init ();
auth_gssapi_init ();
auth_gsasl_init ();
......
......@@ -277,8 +277,10 @@ extern int imap4d_bye (int);
extern int imap4d_bye0 (int reason, struct imap4d_command *command);
/* Namespace functions */
extern int set_namespace (int i, const char *str);
extern int namespace_init (char *path);
extern mu_list_t namespace[NS_MAX];
extern int namespace_init_session (char *path);
extern void namespace_init (void);
extern char * namespace_getfullpath (char *name, const char *delim);
extern char * namespace_checkfullpath (char *name, const char *pattern,
const char *delim);
......
......@@ -18,38 +18,9 @@
#include "imap4d.h"
/* FIXME: Rewrite using mu_list_t */
/*FIXME: should be global? */
typedef int (*nsfp_t) (void *closure, int ns, char *path, int delim);
struct namespace_t
{
int subdir_c;
char **subdir_v;
};
struct namespace_t namespace[NS_MAX];
/* Note: str is not supposed to be NULL */
int
set_namespace (int i, const char *str)
{
struct namespace_t *ns = namespace + i;
int argc;
char **argv;
mu_argcv_get (str, ":", NULL, &argc, &argv);
ns->subdir_v = mu_realloc (ns->subdir_v,
(ns->subdir_c + argc) * sizeof (ns->subdir_v[0]));
for (i = 0; i < argc; i++)
ns->subdir_v[ns->subdir_c++] = mu_normalize_path (argv[i], "/");
/* Free only argv, not its members */
free (argv);
return 0;
}
mu_list_t namespace[NS_MAX];
static char *
printable_pathname (char *str)
......@@ -63,36 +34,59 @@ printable_pathname (char *str)
return str;
}
static void
print_namespace (int n)
static int
print_namespace_fun (void *item, void *data)
{
int i;
if (namespace[n].subdir_c == 0)
{
util_send ("NIL");
return;
}
int *pcount = data;
char *dir = printable_pathname (item);
char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
if ((*pcount)++)
util_send (" ");
util_send ("(\"%s%s\" \"/\")", dir, suf);
return 0;
}
util_send ("(");
for (i = 0; i < namespace[n].subdir_c; i++)
static void
print_namespace (int nsid)
{
mu_list_t list = namespace[nsid];
if (!list)
util_send ("NIL");
else
{
char *dir = printable_pathname (namespace[n].subdir_v[i]);
char *suf = (dir[0] && dir[strlen (dir) - 1] != '/') ? "/" : "";
util_send ("(\"%s%s\" \"/\")", dir, suf);
int count;
count = 0;
util_send ("(");
mu_list_do (list, print_namespace_fun, &count);
util_send (")");
}
util_send (")");
}
struct ns_closure
{
int id;
nsfp_t fun;
void *closure;
};
static int
_enum_fun (void *item, void *data)
{
struct ns_closure *nsp = data;
return nsp->fun (nsp->closure, nsp->id, (char*) item, '/');
}
static int
namespace_enumerate (int ns, nsfp_t f, void *closure)
namespace_enumerate (int id, nsfp_t f, void *closure)
{
int i, rc;
struct ns_closure nsc;
for (i = 0; i < namespace[ns].subdir_c; i++)
if ((rc = (*f) (closure, ns, namespace[ns].subdir_v[i], '/')))
return rc;
return 0;
nsc.id = id;
nsc.fun = f;
nsc.closure = closure;
return namespace[id] == 0 ? 0 :
mu_list_do (namespace[id], _enum_fun, &nsc);
}
static int
......@@ -137,7 +131,7 @@ imap4d_namespace (struct imap4d_command *command, imap4d_tokbuf_t tok)
return util_finish (command, RESP_OK, "Completed");
}
struct namespace_info
{
char *name;
......@@ -240,8 +234,45 @@ namespace_getfullpath (char *name, const char *delim)
}
int
namespace_init (char *path)
namespace_init_session (char *path)
{
set_namespace (NS_PRIVATE, path);
mu_list_create (&namespace[NS_PRIVATE]);
mu_list_append (namespace[NS_PRIVATE],
mu_strdup (mu_normalize_path (path, "/")));
return 0;
}
static int
normalize_fun (void *item, void *data)
{
char *name = item;
mu_list_t list = data;
return mu_list_append (list,
mu_strdup (mu_normalize_path (name, "/")));
}
static void
free_item (void *item)
{
free (item);
}
void
namespace_init ()
{
int i;
for (i = 0; i < NS_MAX; i++)
{
if (namespace[i])
{
mu_list_t list;
mu_list_create (&list);
mu_list_set_destroy_item (list, free_item);
mu_list_do (namespace[i], normalize_fun, list);
mu_list_set_destroy_item (namespace[i], free_item);
mu_list_destroy (&namespace[i]);
namespace[i] = list;
}
}
}
......
......@@ -1088,6 +1088,27 @@ parse_param (struct scan_tree_data *sdata, const mu_cfg_node_t *node)
{
clos.sdata = sdata;
clos.locus = &node->locus;
switch (node->label->type)
{
case MU_CFG_LIST:
break;
case MU_CFG_STRING:
{
mu_list_t list;
mu_list_create (&list);
mu_list_append (list, config_value_dup (node->label));
node->label->type = MU_CFG_LIST;
node->label->v.list = list;
}
break;
case MU_CFG_ARRAY:
_mu_cfg_perror (sdata->tree->debug, &node->locus,
_("expected list, but found array"));
return 1;
}
mu_list_create (&clos.list);
mu_list_do (node->label->v.list, _set_fun, &clos);
*(mu_list_t*)tgt = clos.list;
......