Commit 9a94d41a 9a94d41a0c8cd941db019478c7a75b1036ddf580 by Sergey Poznyakoff

Rewrite namespace support

* imap4d/imap4d.c (imap4d_homedir)
(modify_homedir, mailbox_mode): Remove.
(imap4d_srv_param): New configuration statement "namespace"
Remove statements: homedir, personal-namespace,
shared-namespace, other-mailbox-mode, shared-mailbox-mode.
* imap4d/imap4d.h (imap4d_homedir, modify_homedir)
(mailbox_mode): Remove.
(namespace, namespace_init_session, util_getfullpath)
(namespace_getfullpath, namespace_checkfullpath): Remove.
(namespace_prefix, namespace): New structs.
(namespace_lookup, namespace_translate_name)
(namespace_get_url, translate_delim): New protos.
* imap4d/list.c (refinfo): Revamp.
(list_fun): Rewrite.
* imap4d/namespace.c: Rewrite from scratch.
* imap4d/append.c: Use new namespace functions.
* imap4d/util.c (util_getfullpath): Remove.

* imap4d/copy.c: Likewise.
* imap4d/create.c: Likewise.
* imap4d/delete.c: Likewise.
* imap4d/quota.c: Likewise.
* imap4d/rename.c: Likewise.
* imap4d/select.c: Likewise.
* imap4d/status.c: Likewise.

* imap4d/tests/atlocal.in (make_config): New function.
* imap4d/tests/testsuite.at (IMAP4D_CONFIG)
(IMAP4D_RUN): New functions.
* imap4d/tests/list.at: Update tests 16, 17, 18, 19

* imap4d/tests/IDEF0955.at: Use IMAP4D_RUN.
* imap4d/tests/IDEF0956.at: Likewise.
* imap4d/tests/append00.at: Likewise.
* imap4d/tests/append01.at: Likewise.
* imap4d/tests/create01.at: Likewise.
* imap4d/tests/create02.at: Likewise.
1 parent 068c0599
...@@ -253,7 +253,7 @@ imap4d_append (struct imap4d_session *session, ...@@ -253,7 +253,7 @@ imap4d_append (struct imap4d_session *session,
253 253
254 msg_text = imap4d_tokbuf_getarg (tok, i); 254 msg_text = imap4d_tokbuf_getarg (tok, i);
255 255
256 mboxname = namespace_getfullpath (mboxname, NULL); 256 mboxname = namespace_get_url (mboxname, NULL);
257 if (!mboxname) 257 if (!mboxname)
258 return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); 258 return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
259 259
......
...@@ -211,7 +211,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -211,7 +211,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
211 char *end; 211 char *end;
212 mu_mailbox_t cmbox = NULL; 212 mu_mailbox_t cmbox = NULL;
213 int arg = IMAP4_ARG_1 + !!isuid; 213 int arg = IMAP4_ARG_1 + !!isuid;
214 int ns; 214 int mode = 0;
215 215
216 *err_text = NULL; 216 *err_text = NULL;
217 if (imap4d_tokbuf_argc (tok) != arg + 2) 217 if (imap4d_tokbuf_argc (tok) != arg + 2)
...@@ -240,7 +240,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -240,7 +240,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
240 return RESP_BAD; 240 return RESP_BAD;
241 } 241 }
242 242
243 mailbox_name = namespace_getfullpath (name, &ns); 243 mailbox_name = namespace_get_url (name, &mode);
244 244
245 if (!mailbox_name) 245 if (!mailbox_name)
246 { 246 {
...@@ -255,7 +255,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text) ...@@ -255,7 +255,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
255 if (status == 0) 255 if (status == 0)
256 { 256 {
257 /* It SHOULD NOT automatifcllly create the mailbox. */ 257 /* It SHOULD NOT automatifcllly create the mailbox. */
258 status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]); 258 status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mode);
259 if (status == 0) 259 if (status == 0)
260 { 260 {
261 mu_list_t msglist; 261 mu_list_t msglist;
......
...@@ -39,7 +39,7 @@ imap4d_create (struct imap4d_session *session, ...@@ -39,7 +39,7 @@ imap4d_create (struct imap4d_session *session,
39 { 39 {
40 char *name; 40 char *name;
41 int isdir = 0; 41 int isdir = 0;
42 int ns; 42 int mode = 0;
43 int rc = RESP_OK; 43 int rc = RESP_OK;
44 const char *msg = "Completed"; 44 const char *msg = "Completed";
45 45
...@@ -67,7 +67,7 @@ imap4d_create (struct imap4d_session *session, ...@@ -67,7 +67,7 @@ imap4d_create (struct imap4d_session *session,
67 isdir = 1; 67 isdir = 1;
68 68
69 /* Allocates memory. */ 69 /* Allocates memory. */
70 name = namespace_getfullpath (name, &ns); 70 name = namespace_get_url (name, &mode);
71 71
72 if (!name) 72 if (!name)
73 return io_completion_response (command, RESP_NO, "Cannot create mailbox"); 73 return io_completion_response (command, RESP_NO, "Cannot create mailbox");
...@@ -96,7 +96,7 @@ imap4d_create (struct imap4d_session *session, ...@@ -96,7 +96,7 @@ imap4d_create (struct imap4d_session *session,
96 } 96 }
97 else if ((rc = mu_mailbox_open (mbox, 97 else if ((rc = mu_mailbox_open (mbox,
98 MU_STREAM_RDWR | MU_STREAM_CREAT 98 MU_STREAM_RDWR | MU_STREAM_CREAT
99 | mailbox_mode[ns]))) 99 | mode)))
100 { 100 {
101 mu_diag_output (MU_DIAG_ERR, 101 mu_diag_output (MU_DIAG_ERR,
102 _("Cannot open mailbox %s: %s"), 102 _("Cannot open mailbox %s: %s"),
......
...@@ -49,7 +49,7 @@ imap4d_delete (struct imap4d_session *session, ...@@ -49,7 +49,7 @@ imap4d_delete (struct imap4d_session *session,
49 return io_completion_response (command, RESP_NO, "Already exist"); 49 return io_completion_response (command, RESP_NO, "Already exist");
50 50
51 /* Allocates memory. */ 51 /* Allocates memory. */
52 name = namespace_getfullpath (name, NULL); 52 name = namespace_get_url (name, NULL);
53 if (!name) 53 if (!name)
54 return io_completion_response (command, RESP_NO, "Cannot remove"); 54 return io_completion_response (command, RESP_NO, "Cannot remove");
55 55
......
...@@ -27,8 +27,6 @@ int imap4d_transcript; ...@@ -27,8 +27,6 @@ int imap4d_transcript;
27 27
28 mu_mailbox_t mbox; /* Current mailbox */ 28 mu_mailbox_t mbox; /* Current mailbox */
29 char *real_homedir; /* Homedir as returned by user database */ 29 char *real_homedir; /* Homedir as returned by user database */
30 char *imap4d_homedir; /* Homedir as visible for the remote party */
31 char *modify_homedir; /* Expression to produce imap4d_homedir */
32 int state = STATE_NONAUTH; /* Current IMAP4 state */ 30 int state = STATE_NONAUTH; /* Current IMAP4 state */
33 struct mu_auth_data *auth_data; 31 struct mu_auth_data *auth_data;
34 32
...@@ -40,8 +38,6 @@ mu_list_t user_retain_groups; ...@@ -40,8 +38,6 @@ mu_list_t user_retain_groups;
40 38
41 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 39 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
42 40
43 int mailbox_mode[NS_MAX];
44
45 /* Saved command line. */ 41 /* Saved command line. */
46 int imap4d_argc; 42 int imap4d_argc;
47 char **imap4d_argv; 43 char **imap4d_argv;
...@@ -360,6 +356,178 @@ imap_check_group_list (mu_list_t l) ...@@ -360,6 +356,178 @@ imap_check_group_list (mu_list_t l)
360 return rc; 356 return rc;
361 } 357 }
362 358
359 static int
360 cb_prefix_delim (void *data, mu_config_value_t *val)
361 {
362 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
363 return 1;
364 if (val->v.string[0] == 0)
365 mu_error (_("delimiter cannot be empty"));
366 else if (val->v.string[1] != 0)
367 mu_error (_("delimiter must be a single character"));
368 else
369 *(int*) data = val->v.string[0];
370 return 0;
371 }
372
373 static int
374 cb_prefix_scheme (void *data, mu_config_value_t *val)
375 {
376 struct namespace_prefix *pfx = data;
377 char *scheme;
378 mu_record_t rec;
379 int rc;
380 int (*mbx) (mu_mailbox_t);
381
382 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
383 return 1;
384 scheme = mu_strdup (val->v.string);
385 rc = mu_registrar_lookup_scheme (scheme, &rec);
386 if (rc == MU_ERR_NOENT)
387 {
388 mu_error (_("unknown mailbox type"));
389 return 1;
390 }
391 else if (rc)
392 {
393 mu_diag_funcall (MU_DIAG_ERROR, "mu_registrar_lookup_scheme", scheme, rc);
394 return 1;
395 }
396
397 rc = mu_record_get_mailbox (rec, &mbx);
398 if (rc)
399 {
400 mu_diag_funcall (MU_DIAG_ERROR, "mu_record_get_mailbox", scheme, rc);
401 return 1;
402 }
403
404 if (!mbx || !mu_record_is_local (rec))
405 {
406 mu_error (_("not a local mailbox type"));
407 return 1;
408 }
409
410 pfx->scheme = scheme;
411 pfx->record = rec;
412
413 return 0;
414 }
415
416 static struct mu_cfg_param prefix_param[] = {
417 { "directory", mu_c_string,
418 NULL, mu_offsetof (struct namespace_prefix, dir), NULL,
419 N_("Directory in the file system") },
420 { "delimiter", mu_cfg_callback,
421 NULL, mu_offsetof (struct namespace_prefix, delim), cb_prefix_delim,
422 N_("Hierarchy delimiter character") },
423 { "mailbox-type", mu_cfg_callback,
424 NULL, 0, cb_prefix_scheme,
425 N_("Type of mailboxes residing under this prefix") },
426 { NULL }
427 };
428
429 static struct mu_cfg_param namespace_param[] = {
430 { "mailbox-mode", mu_cfg_callback,
431 NULL, mu_offsetof (struct namespace, mode), cb_mailbox_mode,
432 N_("File mode for newly created mailboxes in this namespace"),
433 N_("mode: g(+|=)[wr]+,o(+|=)[wr]+") },
434 { "prefix", mu_cfg_section },
435 { NULL }
436 };
437
438 static int
439 prefix_section_parser (enum mu_cfg_section_stage stage,
440 const mu_cfg_node_t *node,
441 const char *section_label, void **section_data,
442 void *call_data,
443 mu_cfg_tree_t *tree)
444 {
445 struct namespace_prefix *pfx;
446
447 switch (stage)
448 {
449 case mu_cfg_section_start:
450 {
451 struct namespace *nspace = *section_data;
452
453 if (node->label == NULL || node->label->type != MU_CFG_STRING)
454 return 1;
455
456 pfx = mu_zalloc (sizeof (*pfx));
457 pfx->prefix = mu_strdup (node->label->v.string);
458 mu_list_append (nspace->prefixes, pfx);
459 *section_data = pfx;
460 }
461 break;
462
463 case mu_cfg_section_end:
464 pfx = *section_data;
465 if (!pfx->delim)
466 pfx->delim = '/';
467 if (!pfx->dir)
468 {
469 if (pfx->prefix)
470 pfx->dir = mu_strdup (pfx->prefix);
471 else
472 {
473 mu_error (_("bad prefix definition"));
474 return 1;
475 }
476 }
477 else if (!pfx->prefix)
478 {
479 pfx->prefix = mu_alloc (strlen (pfx->dir) + 1);
480 translate_delim (pfx->prefix, pfx->dir, pfx->delim, '/');
481 }
482 }
483 return 0;
484 }
485
486 static int
487 namespace_section_parser (enum mu_cfg_section_stage stage,
488 const mu_cfg_node_t *node,
489 const char *section_label, void **section_data,
490 void *call_data,
491 mu_cfg_tree_t *tree)
492 {
493 if (stage == mu_cfg_section_start)
494 {
495 struct namespace *ns;
496
497 if (node->label == NULL || node->label->type != MU_CFG_STRING)
498 return 1;
499
500 ns = namespace_lookup (node->label->v.string);
501 if (!ns)
502 {
503 mu_error (_("unknown namespace"));
504 return 0;
505 }
506
507 *section_data = ns;
508 }
509 return 0;
510 }
511
512 static void
513 namespace_cfg_init (void)
514 {
515 struct mu_cfg_section *section;
516
517 if (mu_create_canned_section ("prefix", &section))
518 abort ();
519 section->docstring = N_("Define a single prefix");
520 mu_cfg_section_add_params (section, prefix_param);
521 section->parser = prefix_section_parser;
522
523 if (mu_create_canned_section ("namespace", &section))
524 abort ();
525 section->docstring = N_("Define a namespace");
526 section->label = "private | other | shared";
527 section->parser = namespace_section_parser;
528 mu_cfg_section_add_params (section, namespace_param);
529 }
530
363 static struct mu_cfg_param imap4d_srv_param[] = { 531 static struct mu_cfg_param imap4d_srv_param[] = {
364 #ifdef WITH_TLS 532 #ifdef WITH_TLS
365 { "tls", mu_cfg_callback, 533 { "tls", mu_cfg_callback,
...@@ -385,8 +553,12 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -385,8 +553,12 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
385 0, NULL, 553 0, NULL,
386 N_("Deny access if the user group is in this list.") }, 554 N_("Deny access if the user group is in this list.") },
387 555
556 { "namespace", mu_cfg_section },
557
558 #if 0
388 { "homedir", mu_c_string, &modify_homedir, 0, NULL, 559 { "homedir", mu_c_string, &modify_homedir, 0, NULL,
389 N_("Modify home directory.") }, 560 N_("Modify home directory.") },
561
390 { "personal-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_PRIVATE], 562 { "personal-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_PRIVATE],
391 0, NULL, 563 0, NULL,
392 N_("Set personal namespace.") }, 564 N_("Set personal namespace.") },
...@@ -396,6 +568,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -396,6 +568,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
396 { "shared-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_SHARED], 568 { "shared-namespace", MU_CFG_LIST_OF(mu_c_string), &namespace[NS_SHARED],
397 0, NULL, 569 0, NULL,
398 N_("Set shared namespace.") }, 570 N_("Set shared namespace.") },
571 FIXME
399 { "other-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_OTHER], 0, 572 { "other-mailbox-mode", mu_cfg_callback, &mailbox_mode[NS_OTHER], 0,
400 cb_mailbox_mode, 573 cb_mailbox_mode,
401 N_("File mode for mailboxes in other namespace."), 574 N_("File mode for mailboxes in other namespace."),
...@@ -404,6 +577,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -404,6 +577,7 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
404 cb_mailbox_mode, 577 cb_mailbox_mode,
405 N_("File mode for mailboxes in shared namespace."), 578 N_("File mode for mailboxes in shared namespace."),
406 N_("mode: g(+|=)[wr]+,o(+|=)[wr]+") }, 579 N_("mode: g(+|=)[wr]+,o(+|=)[wr]+") },
580 #endif
407 { "login-disabled", mu_c_bool, &login_disabled, 0, NULL, 581 { "login-disabled", mu_c_bool, &login_disabled, 0, NULL,
408 N_("Disable LOGIN command.") }, 582 N_("Disable LOGIN command.") },
409 { "create-home-dir", mu_c_bool, &create_home_dir, 0, NULL, 583 { "create-home-dir", mu_c_bool, &create_home_dir, 0, NULL,
...@@ -531,52 +705,6 @@ imap4d_session_setup0 () ...@@ -531,52 +705,6 @@ imap4d_session_setup0 ()
531 if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid)) 705 if (imap4d_check_home_dir (real_homedir, auth_data->uid, auth_data->gid))
532 return 1; 706 return 1;
533 707
534 if (modify_homedir)
535 {
536 char *expr = mu_tilde_expansion (modify_homedir, MU_HIERARCHY_DELIMITER,
537 real_homedir);
538 struct mu_wordsplit ws;
539 const char *env[5];
540
541 env[0] = "user";
542 env[1] = auth_data->name;
543 env[2] = "home";
544 env[3] = real_homedir;
545 env[4] = NULL;
546
547 ws.ws_env = env;
548 if (mu_wordsplit (expr, &ws,
549 MU_WRDSF_NOSPLIT | MU_WRDSF_NOCMD |
550 MU_WRDSF_ENV | MU_WRDSF_ENV_KV))
551 {
552 mu_error (_("cannot expand line `%s': %s"), expr,
553 mu_wordsplit_strerror (&ws));
554 return 1;
555 }
556 else if (ws.ws_wordc == 0)
557 {
558 mu_error (_("expanding %s yields empty string"), expr);
559 return 1;
560 }
561 imap4d_homedir = mu_strdup (ws.ws_wordv[0]);
562 if (!imap4d_homedir)
563 {
564 mu_error ("%s", mu_strerror (errno));
565 return 1;
566 }
567 }
568 else
569 imap4d_homedir = mu_strdup (real_homedir);
570
571 if (strcmp (imap4d_homedir, real_homedir)
572 && imap4d_check_home_dir (imap4d_homedir,
573 auth_data->uid, auth_data->gid))
574 {
575 free (imap4d_homedir);
576 free (real_homedir);
577 return 1;
578 }
579
580 if (auth_data->change_uid) 708 if (auth_data->change_uid)
581 { 709 {
582 struct group *gr; 710 struct group *gr;
...@@ -591,7 +719,6 @@ imap4d_session_setup0 () ...@@ -591,7 +719,6 @@ imap4d_session_setup0 ()
591 if (rc) 719 if (rc)
592 { 720 {
593 mu_error(_("cannot create list: %s"), mu_strerror (rc)); 721 mu_error(_("cannot create list: %s"), mu_strerror (rc));
594 free (imap4d_homedir);
595 free (real_homedir); 722 free (real_homedir);
596 return 1; 723 return 1;
597 } 724 }
...@@ -603,7 +730,6 @@ imap4d_session_setup0 () ...@@ -603,7 +730,6 @@ imap4d_session_setup0 ()
603 { 730 {
604 /* FIXME: When mu_get_user_groups goes to the library, add a 731 /* FIXME: When mu_get_user_groups goes to the library, add a
605 diag message here */ 732 diag message here */
606 free (imap4d_homedir);
607 free (real_homedir); 733 free (real_homedir);
608 return 1; 734 return 1;
609 } 735 }
...@@ -614,15 +740,13 @@ imap4d_session_setup0 () ...@@ -614,15 +740,13 @@ imap4d_session_setup0 ()
614 { 740 {
615 mu_error (_("can't switch to user %s privileges: %s"), 741 mu_error (_("can't switch to user %s privileges: %s"),
616 auth_data->name, mu_strerror (rc)); 742 auth_data->name, mu_strerror (rc));
617 free (imap4d_homedir);
618 free (real_homedir); 743 free (real_homedir);
619 return 1; 744 return 1;
620 } 745 }
621 } 746 }
622 } 747 }
623 748
624 util_chdir (imap4d_homedir); 749 util_chdir (real_homedir);
625 namespace_init_session (imap4d_homedir);
626 750
627 mu_diag_output (MU_DIAG_INFO, 751 mu_diag_output (MU_DIAG_INFO,
628 _("user `%s' logged in (source: %s)"), auth_data->name, 752 _("user `%s' logged in (source: %s)"), auth_data->name,
...@@ -936,6 +1060,7 @@ main (int argc, char **argv) ...@@ -936,6 +1060,7 @@ main (int argc, char **argv)
936 mu_tcpwrapper_cfg_init (); 1060 mu_tcpwrapper_cfg_init ();
937 manlock_cfg_init (); 1061 manlock_cfg_init ();
938 mu_acl_cfg_init (); 1062 mu_acl_cfg_init ();
1063 namespace_cfg_init ();
939 1064
940 mu_m_server_create (&server, program_version); 1065 mu_m_server_create (&server, program_version);
941 mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config)); 1066 mu_m_server_set_config_size (server, sizeof (struct imap4d_srv_config));
...@@ -960,14 +1085,14 @@ main (int argc, char **argv) ...@@ -960,14 +1085,14 @@ main (int argc, char **argv)
960 exit (EX_USAGE); 1085 exit (EX_USAGE);
961 } 1086 }
962 1087
1088 namespace_init ();
1089
963 if (test_mode) 1090 if (test_mode)
964 mu_m_server_set_mode (server, MODE_INTERACTIVE); 1091 mu_m_server_set_mode (server, MODE_INTERACTIVE);
965 1092
966 if (login_disabled) 1093 if (login_disabled)
967 imap4d_capability_add (IMAP_CAPA_LOGINDISABLED); 1094 imap4d_capability_add (IMAP_CAPA_LOGINDISABLED);
968 1095
969 namespace_init ();
970
971 if (mu_gsasl_enabled ()) 1096 if (mu_gsasl_enabled ())
972 { 1097 {
973 auth_gssapi_init (); 1098 auth_gssapi_init ();
......
...@@ -197,17 +197,13 @@ struct imap4d_session ...@@ -197,17 +197,13 @@ struct imap4d_session
197 197
198 extern struct imap4d_command imap4d_command_table[]; 198 extern struct imap4d_command imap4d_command_table[];
199 extern mu_mailbox_t mbox; 199 extern mu_mailbox_t mbox;
200 extern char *imap4d_homedir;
201 extern char *real_homedir; 200 extern char *real_homedir;
202 extern char *modify_homedir;
203 extern int state; 201 extern int state;
204 extern size_t children; 202 extern size_t children;
205 extern int is_virtual; 203 extern int is_virtual;
206 extern struct mu_auth_data *auth_data; 204 extern struct mu_auth_data *auth_data;
207 extern const char *program_version; 205 extern const char *program_version;
208 206
209 extern int mailbox_mode[NS_MAX];
210
211 extern int login_disabled; 207 extern int login_disabled;
212 extern enum imap4d_preauth preauth_mode; 208 extern enum imap4d_preauth preauth_mode;
213 extern char *preauth_program; 209 extern char *preauth_program;
...@@ -394,15 +390,34 @@ extern int imap4d_bye0 (int reason, struct imap4d_command *command); ...@@ -394,15 +390,34 @@ extern int imap4d_bye0 (int reason, struct imap4d_command *command);
394 void imap4d_enter_critical (void); 390 void imap4d_enter_critical (void);
395 void imap4d_leave_critical (void); 391 void imap4d_leave_critical (void);
396 392
397
398 /* Namespace functions */ 393 /* Namespace functions */
399 extern mu_list_t namespace[NS_MAX]; 394 struct namespace_prefix
395 {
396 char *prefix; /* Prefix string */
397 int delim; /* Delimiter character */
398 char *dir; /* Directory in the file system */
399 char *scheme; /* Mailbox URL scheme (type) */
400 mu_record_t record; /* The corresponding record */
401 int ns; /* Namespace */
402 };
403
404 struct namespace
405 {
406 char const *name;
407 int mode; /* File mode for creating new mailboxes */
408 mu_list_t prefixes; /* List of prefixes (struct namespace_prefix */
409 };
410
411 void namespace_init (void);
412 struct namespace *namespace_lookup (char const *name);
413
414 char *namespace_translate_name (char const *name, int url,
415 struct namespace_prefix const **pfx);
416 char *namespace_get_url (char const *name, int *mode);
417
418 void translate_delim (char *dst, char const *src, int dst_delim, int src_delim);
419
400 420
401 extern int namespace_init_session (char *path);
402 extern void namespace_init (void);
403 extern char *namespace_getfullpath (const char *name, int *pns);
404 extern char *namespace_checkfullpath (const char *name, const char *pattern,
405 int *pns);
406 int imap4d_session_setup (char *username); 421 int imap4d_session_setup (char *username);
407 int imap4d_session_setup0 (void); 422 int imap4d_session_setup0 (void);
408 void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo)); 423 void imap4d_child_signal_setup (RETSIGTYPE (*handler) (int signo));
...@@ -417,7 +432,6 @@ extern void imap4d_capability_init (void); ...@@ -417,7 +432,6 @@ extern void imap4d_capability_init (void);
417 extern int util_start (char *); 432 extern int util_start (char *);
418 extern int util_getstate (void); 433 extern int util_getstate (void);
419 extern int util_do_command (struct imap4d_session *, imap4d_tokbuf_t); 434 extern int util_do_command (struct imap4d_session *, imap4d_tokbuf_t);
420 extern char *util_getfullpath (const char *);
421 extern struct imap4d_command *util_getcommand (char *, 435 extern struct imap4d_command *util_getcommand (char *,
422 struct imap4d_command []); 436 struct imap4d_command []);
423 437
......
...@@ -23,8 +23,9 @@ struct refinfo ...@@ -23,8 +23,9 @@ struct refinfo
23 { 23 {
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 size_t pfxlen; /* Length of the current prefix */ 26 struct namespace_prefix const *pfx;
27 size_t homelen; /* Length of homedir */ 27 size_t pfxlen;
28 size_t dirlen; /* Length of the current directory prefix */
28 char *buf; 29 char *buf;
29 size_t bufsize; 30 size_t bufsize;
30 }; 31 };
...@@ -35,12 +36,15 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -35,12 +36,15 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
35 char *name; 36 char *name;
36 struct refinfo *refinfo = data; 37 struct refinfo *refinfo = data;
37 size_t size; 38 size_t size;
39 char *p;
40
41 if (refinfo->pfx->record && refinfo->pfx->record != resp->format)
42 return 0;
38 43
39 name = resp->name; 44 name = resp->name;
40 size = strlen (name); 45 size = strlen (name);
41 if (size == refinfo->homelen + 6 46 if (size == refinfo->pfxlen + 6
42 && memcmp (name, imap4d_homedir, refinfo->homelen) == 0 47 && memcmp (name + refinfo->pfxlen + 1, "INBOX", 5) == 0)
43 && memcmp (name + refinfo->homelen + 1, "INBOX", 5) == 0)
44 return 0; 48 return 0;
45 49
46 io_sendf ("* %s", "LIST ("); 50 io_sendf ("* %s", "LIST (");
...@@ -52,10 +56,10 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -52,10 +56,10 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
52 else if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY) 56 else if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY)
53 io_sendf ("\\NoSelect"); 57 io_sendf ("\\NoSelect");
54 58
55 io_sendf (") \"%c\" ", resp->separator); 59 io_sendf (") \"%c\" ", refinfo->pfx->delim);
56 60
57 name = resp->name + refinfo->pfxlen; 61 name = resp->name + refinfo->dirlen + 1;
58 size = strlen (name) + refinfo->reflen + 1; 62 size = strlen (name) + refinfo->pfxlen + 2;
59 if (size > refinfo->bufsize) 63 if (size > refinfo->bufsize)
60 { 64 {
61 if (refinfo->buf == NULL) 65 if (refinfo->buf == NULL)
...@@ -82,10 +86,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) ...@@ -82,10 +86,17 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data)
82 } 86 }
83 } 87 }
84 88
85 if ((refinfo->reflen == 0 || refinfo->refptr[refinfo->reflen - 1] == '/') 89 if (refinfo->pfxlen)
86 && name[0] == '/') 90 {
87 name++; 91 p = mu_stpcpy (refinfo->buf, refinfo->pfx->prefix);
88 strcpy (refinfo->buf + refinfo->reflen, name); 92 if (*name)
93 *p++ = refinfo->pfx->delim;
94 }
95 else
96 p = refinfo->buf;
97 if (*name)
98 translate_delim (p, name, refinfo->pfx->delim, resp->separator);
99
89 name = refinfo->buf; 100 name = refinfo->buf;
90 101
91 if (strpbrk (name, "\"{}")) 102 if (strpbrk (name, "\"{}"))
...@@ -168,62 +179,65 @@ imap4d_list (struct imap4d_session *session, ...@@ -168,62 +179,65 @@ imap4d_list (struct imap4d_session *session,
168 { 179 {
169 int status; 180 int status;
170 mu_folder_t folder; 181 mu_folder_t folder;
182 mu_url_t url;
171 char *cwd; 183 char *cwd;
184 char const *dir;
172 struct refinfo refinfo; 185 struct refinfo refinfo;
173 size_t i; 186 size_t i;
187 struct namespace_prefix const *pfx;
174 188
175 switch (*wcard) 189 if (*wcard == '~')
176 {
177 /* Absolute Path in wcard, dump the old ref. */
178 case '/':
179 ref = mu_strdup ("/");
180 wcard++;
181 break;
182
183 /* Absolute Path, but take care of things like ~guest/Mail,
184 ref becomes ref = ~guest. */
185 case '~':
186 { 190 {
187 char *s = strchr (wcard, '/'); 191 for (i = 1;
188 if (s) 192 mu_c_is_class (wcard[i], MU_CTYPE_ALPHA|MU_CTYPE_DIGIT)
189 { 193 || wcard[i] == '_'; i++)
190 ref = calloc (s - wcard + 1, 1); 194 ;
191 memcpy (ref, wcard, s - wcard); 195 ref = mu_alloc (i + 1);
192 ref [s - wcard] = '\0'; 196 memcpy (ref, wcard, i);
193 wcard = s + 1; 197 ref[i] = 0;
198 wcard += i;
194 } 199 }
195 else 200 else
201 ref = mu_strdup (ref);
202
203 cwd = namespace_translate_name (ref, 0, &pfx);
204 if (!cwd)
196 { 205 {
197 ref = mu_strdup (wcard); 206 free (ref);
198 wcard += strlen (wcard); 207 return io_completion_response (command, RESP_NO,
199 } 208 "The requested item could not be found.");
200 } 209 }
201 break; 210 free (cwd);
202 211
203 default: 212 if (*wcard == pfx->delim && ref[0] != '~')
204 ref = mu_strdup (ref); 213 {
214 /* Absolute Path in wcard, dump the old ref. */
215 ref[0] = 0;
205 } 216 }
206 217
207 /* Find the longest directory prefix */ 218 /* Find the longest directory prefix */
208 i = strcspn (wcard, "%*"); 219 i = strcspn (wcard, "%*");
209 while (i > 0 && wcard[i - 1] != '/') 220 while (i > 0 && wcard[i - 1] != pfx->delim)
210 i--; 221 i--;
211 /* Append it to the reference */ 222 /* Append it to the reference */
212 if (i) 223 if (i)
213 { 224 {
214 size_t reflen = strlen (ref); 225 size_t reflen = strlen (ref);
215 int addslash = (reflen > 0 && ref[reflen-1] != '/'); 226 int addslash = (reflen > 0
227 && ref[reflen-1] != pfx->delim
228 && *wcard != pfx->delim);
216 size_t len = i + reflen + addslash; 229 size_t len = i + reflen + addslash;
217 230
218 ref = mu_realloc (ref, len); 231 ref = mu_realloc (ref, len);
219 if (addslash) 232 if (addslash)
220 ref[reflen++] = '/'; 233 ref[reflen++] = pfx->delim;
221 memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ 234 memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */
222 ref[len-1] = 0; 235 ref[len-1] = 0;
236
237 wcard += i;
223 } 238 }
224 239
225 /* Allocates. */ 240 cwd = namespace_translate_name (ref, 0, &pfx);
226 cwd = namespace_checkfullpath (ref, wcard, NULL);
227 if (!cwd) 241 if (!cwd)
228 { 242 {
229 free (ref); 243 free (ref);
...@@ -231,6 +245,18 @@ imap4d_list (struct imap4d_session *session, ...@@ -231,6 +245,18 @@ imap4d_list (struct imap4d_session *session,
231 "The requested item could not be found."); 245 "The requested item could not be found.");
232 } 246 }
233 247
248 if (pfx->ns == NS_OTHER
249 && strcmp (ref, pfx->prefix) == 0
250 && *mu_str_skip_cset_comp (wcard, "*%"))
251 {
252 /* [A] server MAY return NO to such a LIST command, requiring that a
253 user name be included with the Other Users' Namespace prefix
254 before listing any other user's mailboxes */
255 free (ref);
256 return io_completion_response (command, RESP_NO,
257 "The requested item could not be found.");
258 }
259
234 status = mu_folder_create (&folder, cwd); 260 status = mu_folder_create (&folder, cwd);
235 if (status) 261 if (status)
236 { 262 {
...@@ -246,8 +272,13 @@ imap4d_list (struct imap4d_session *session, ...@@ -246,8 +272,13 @@ imap4d_list (struct imap4d_session *session,
246 272
247 refinfo.refptr = ref; 273 refinfo.refptr = ref;
248 refinfo.reflen = strlen (ref); 274 refinfo.reflen = strlen (ref);
249 refinfo.pfxlen = strlen (cwd); 275 refinfo.pfx = pfx;
250 refinfo.homelen = strlen (imap4d_homedir); 276
277 mu_folder_get_url (folder, &url);
278 mu_url_sget_path (url, &dir);
279 refinfo.dirlen = strlen (dir);
280
281 refinfo.pfxlen = strlen (pfx->prefix);
251 282
252 /* The special name INBOX is included in the output from LIST, if 283 /* The special name INBOX is included in the output from LIST, if
253 INBOX is supported by this server for this user and if the 284 INBOX is supported by this server for this user and if the
......
...@@ -120,9 +120,9 @@ directory_size (const char *dirname, mu_off_t *size) ...@@ -120,9 +120,9 @@ directory_size (const char *dirname, mu_off_t *size)
120 mu_off_t used_size; 120 mu_off_t used_size;
121 121
122 void 122 void
123 quota_setup () 123 quota_setup (void)
124 { 124 {
125 directory_size (imap4d_homedir, &used_size); 125 directory_size (real_homedir, &used_size);
126 } 126 }
127 127
128 int 128 int
...@@ -138,7 +138,7 @@ quota_check (mu_off_t size) ...@@ -138,7 +138,7 @@ quota_check (mu_off_t size)
138 138
139 total = used_size; 139 total = used_size;
140 140
141 mailbox_name = namespace_getfullpath ("INBOX", NULL); 141 mailbox_name = namespace_get_url ("INBOX", NULL);
142 rc = mu_mailbox_create (&mbox, mailbox_name); 142 rc = mu_mailbox_create (&mbox, mailbox_name);
143 if (rc) 143 if (rc)
144 { 144 {
......
...@@ -109,7 +109,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -109,7 +109,7 @@ imap4d_rename (struct imap4d_session *session,
109 int rc = RESP_OK; 109 int rc = RESP_OK;
110 const char *msg = "Completed"; 110 const char *msg = "Completed";
111 struct stat newst; 111 struct stat newst;
112 int ns; 112 int mode = 0;
113 113
114 if (imap4d_tokbuf_argc (tok) != 4) 114 if (imap4d_tokbuf_argc (tok) != 4)
115 return io_completion_response (command, RESP_BAD, "Invalid arguments"); 115 return io_completion_response (command, RESP_BAD, "Invalid arguments");
...@@ -121,7 +121,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -121,7 +121,7 @@ imap4d_rename (struct imap4d_session *session,
121 return io_completion_response (command, RESP_NO, "Name Inbox is reservered"); 121 return io_completion_response (command, RESP_NO, "Name Inbox is reservered");
122 122
123 /* Allocates memory. */ 123 /* Allocates memory. */
124 newname = namespace_getfullpath (newname, &ns); 124 newname = namespace_get_url (newname, &mode);
125 if (!newname) 125 if (!newname)
126 return io_completion_response (command, RESP_NO, "Permission denied"); 126 return io_completion_response (command, RESP_NO, "Permission denied");
127 127
...@@ -160,8 +160,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -160,8 +160,7 @@ imap4d_rename (struct imap4d_session *session,
160 } 160 }
161 if (mu_mailbox_create (&newmbox, newname) != 0 161 if (mu_mailbox_create (&newmbox, newname) != 0
162 || mu_mailbox_open (newmbox, 162 || mu_mailbox_open (newmbox,
163 MU_STREAM_CREAT | MU_STREAM_RDWR 163 MU_STREAM_CREAT | MU_STREAM_RDWR | mode) != 0)
164 | mailbox_mode[ns]) != 0)
165 { 164 {
166 free (newname); 165 free (newname);
167 return io_completion_response (command, RESP_NO, 166 return io_completion_response (command, RESP_NO,
...@@ -200,7 +199,7 @@ imap4d_rename (struct imap4d_session *session, ...@@ -200,7 +199,7 @@ imap4d_rename (struct imap4d_session *session,
200 return io_completion_response (command, RESP_OK, "Rename successful"); 199 return io_completion_response (command, RESP_OK, "Rename successful");
201 } 200 }
202 201
203 oldname = namespace_getfullpath (oldname, NULL); 202 oldname = namespace_get_url (oldname, NULL);
204 203
205 /* It must exist. */ 204 /* It must exist. */
206 /* FIXME: 1. What if odlname or newname is a remote mailbox? 205 /* FIXME: 1. What if odlname or newname is a remote mailbox?
......
...@@ -59,7 +59,7 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname, ...@@ -59,7 +59,7 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname,
59 59
60 if (strcmp (mboxname, "INBOX") == 0) 60 if (strcmp (mboxname, "INBOX") == 0)
61 flags |= MU_STREAM_CREAT; 61 flags |= MU_STREAM_CREAT;
62 mailbox_name = namespace_getfullpath (mboxname, NULL); 62 mailbox_name = namespace_translate_name (mboxname, 1, NULL);
63 63
64 if (!mailbox_name) 64 if (!mailbox_name)
65 return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); 65 return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
......
...@@ -81,7 +81,7 @@ imap4d_status (struct imap4d_session *session, ...@@ -81,7 +81,7 @@ imap4d_status (struct imap4d_session *session,
81 81
82 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); 82 name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
83 83
84 mailbox_name = namespace_getfullpath (name, NULL); 84 mailbox_name = namespace_get_url (name, NULL);
85 85
86 if (!mailbox_name) 86 if (!mailbox_name)
87 return io_completion_response (command, RESP_NO, "Error opening mailbox"); 87 return io_completion_response (command, RESP_NO, "Error opening mailbox");
......
...@@ -28,7 +28,11 @@ EOT ...@@ -28,7 +28,11 @@ EOT
28 28
29 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1,INBOX) 29 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox1,INBOX)
30 30
31 imap4d IMAP4D_OPTIONS < input | remove_uidvalidity | tr -d '\r' 31 IMAP4D_RUN([1 select INBOX
32 2 FETCH 1:$MU_ULONG_MAX_1 FLAGS
33 3 UID FETCH 1:$MU_ULONG_MAX_1 FLAGS
34 X LOGOUT
35 ],[expand]) | remove_uidvalidity
32 ], 36 ],
33 [0], 37 [0],
34 [* PREAUTH IMAP4rev1 Test mode 38 [* PREAUTH IMAP4rev1 Test mode
......
...@@ -20,14 +20,14 @@ AT_CHECK([ ...@@ -20,14 +20,14 @@ AT_CHECK([
20 test "$MU_ULONG_MAX_1" = 0 && AT_SKIP_TEST 20 test "$MU_ULONG_MAX_1" = 0 && AT_SKIP_TEST
21 21
22 cat > input <<EOT 22 cat > input <<EOT
23 1 select INBOX
24 2 FETCH 1 BODY[[TEXT]]<0.$MU_ULONG_MAX_1>
25 X LOGOUT
26 EOT 23 EOT
27 24
28 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/search.mbox,INBOX) 25 MUT_MBCOPY($abs_top_srcdir/testsuite/spool/search.mbox,INBOX)
29 26
30 imap4d IMAP4D_OPTIONS < input | remove_uidvalidity | tr -d '\r' 27 IMAP4D_RUN([1 select INBOX
28 2 FETCH 1 BODY[[TEXT]]<0.$MU_ULONG_MAX_1>
29 X LOGOUT
30 ],[expand]) | remove_uidvalidity
31 ], 31 ],
32 [0], 32 [0],
33 [* PREAUTH IMAP4rev1 Test mode 33 [* PREAUTH IMAP4rev1 Test mode
......
...@@ -17,8 +17,9 @@ ...@@ -17,8 +17,9 @@
17 AT_SETUP([append with flags]) 17 AT_SETUP([append with flags])
18 AT_KEYWORDS([append00]) 18 AT_KEYWORDS([append00])
19 19
20 AT_DATA([input], 20 AT_CHECK([
21 [1 APPEND mbox (\Seen) {300+} 21 > mbox
22 IMAP4D_RUN([1 APPEND mbox (\Seen) {300+}
22 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) 23 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
23 From: Fred Foobar <foobar@Blurdybloop.COM> 24 From: Fred Foobar <foobar@Blurdybloop.COM>
24 Subject: afternoon meeting 25 Subject: afternoon meeting
...@@ -31,10 +32,6 @@ Hello Joe, do you think we can meet at 3:30 tomorrow ...@@ -31,10 +32,6 @@ Hello Joe, do you think we can meet at 3:30 tomorrow
31 32
32 X LOGOUT 33 X LOGOUT
33 ]) 34 ])
34
35 AT_CHECK([
36 > mbox
37 imap4d IMAP4D_OPTIONS < input | tr -d '\r'
38 echo "==" 35 echo "=="
39 awk 'NR==1 {print "1:",$1,$2; next} NF==0 {print NR":"; next} {print NR":",$0}' mbox 36 awk 'NR==1 {print "1:",$1,$2; next} NF==0 {print NR":"; next} {print NR":",$0}' mbox
40 ], 37 ],
......
...@@ -17,8 +17,9 @@ ...@@ -17,8 +17,9 @@
17 AT_SETUP([append with envelope date]) 17 AT_SETUP([append with envelope date])
18 AT_KEYWORDS([append01]) 18 AT_KEYWORDS([append01])
19 19
20 AT_DATA([input], 20 AT_CHECK([
21 [1 APPEND mbox "25-Aug-2002 18:00:00 +0200" {274+} 21 > mbox
22 IMAP4D_RUN([1 APPEND mbox "25-Aug-2002 18:00:00 +0200" {274+}
22 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) 23 Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
23 From: Fred Foobar <foobar@Blurdybloop.COM> 24 From: Fred Foobar <foobar@Blurdybloop.COM>
24 Subject: afternoon meeting again 25 Subject: afternoon meeting again
...@@ -31,10 +32,6 @@ Better yet at 04:00? ...@@ -31,10 +32,6 @@ Better yet at 04:00?
31 32
32 X LOGOUT 33 X LOGOUT
33 ]) 34 ])
34
35 AT_CHECK([
36 > mbox
37 imap4d IMAP4D_OPTIONS < input | tr -d '\r'
38 echo "==" 35 echo "=="
39 awk 'NF==0 {print NR":"; next} {print NR":",$0}' mbox 36 awk 'NF==0 {print NR":"; next} {print NR":",$0}' mbox
40 ], 37 ],
......
...@@ -5,6 +5,35 @@ ...@@ -5,6 +5,35 @@
5 PATH=@abs_builddir@:@abs_top_builddir@/imap4d:$top_srcdir:$srcdir:$PATH 5 PATH=@abs_builddir@:@abs_top_builddir@/imap4d:$top_srcdir:$srcdir:$PATH
6 MU_ULONG_MAX_1=@MU_ULONG_MAX_1@ 6 MU_ULONG_MAX_1=@MU_ULONG_MAX_1@
7 7
8 make_config() {
9 CWD=`pwd`
10 HOMEDIR=${CWD}${1:+/}$1
11 cat > imap4d.conf <<EOT
12 logging {
13 syslog off;
14 severity notice;
15 }
16
17 gsasl {
18 enable off;
19 }
20
21 namespace private {
22 prefix "" {
23 directory "$HOMEDIR";
24 }
25 prefix "~" {
26 directory "$HOMEDIR";
27 }
28 }
29
30 mailbox {
31 folder "$CWD";
32 mailbox-pattern "$CWD/INBOX";
33 }
34 EOT
35 }
36
8 remove_untagged() { 37 remove_untagged() {
9 sed '/^\*/d' 38 sed '/^\*/d'
10 } 39 }
......
...@@ -18,12 +18,9 @@ AT_SETUP([create]) ...@@ -18,12 +18,9 @@ AT_SETUP([create])
18 AT_KEYWORDS([create create00]) 18 AT_KEYWORDS([create create00])
19 19
20 AT_CHECK([ 20 AT_CHECK([
21 AT_DATA([input],[dnl 21 IMAP4D_RUN([1 create flat
22 1 create flat
23 X LOGOUT 22 X LOGOUT
24 ]) 23 ])
25
26 imap4d IMAP4D_OPTIONS < input | tr -d '\r'
27 find . -name flat 24 find . -name flat
28 ], 25 ],
29 [0], 26 [0],
......
...@@ -18,12 +18,9 @@ AT_SETUP([create nested]) ...@@ -18,12 +18,9 @@ AT_SETUP([create nested])
18 AT_KEYWORDS([create create01]) 18 AT_KEYWORDS([create create01])
19 19
20 AT_CHECK([ 20 AT_CHECK([
21 AT_DATA([input],[dnl 21 IMAP4D_RUN([1 create en/to/tre
22 1 create en/to/tre
23 X LOGOUT 22 X LOGOUT
24 ]) 23 ])
25
26 imap4d IMAP4D_OPTIONS < input | tr -d '\r'
27 find . -name tre 24 find . -name tre
28 ], 25 ],
29 [0], 26 [0],
......
...@@ -79,55 +79,35 @@ LIST_CHECK([empty ref + asterisk],[list02], ...@@ -79,55 +79,35 @@ LIST_CHECK([empty ref + asterisk],[list02],
79 LIST_CHECK([root ref + asterisk],[list03], 79 LIST_CHECK([root ref + asterisk],[list03],
80 ["/" "*"], 80 ["/" "*"],
81 [dnl 81 [dnl
82 1 NO LIST The requested item could not be found. 82 * LIST (\NoInferiors) "/" bigto.mbox
83 * LIST (\NoInferiors) "/" mbox
84 * LIST (\NoInferiors) "/" mbox1
85 * LIST (\NoInferiors) "/" relational.mbox
86 * LIST (\NoInferiors) "/" search.mbox
87 * LIST (\NoInferiors) "/" sieve.mbox
88 * LIST (\NoInferiors) "/" teaparty.mbox
83 ]) 89 ])
84 90
85 LIST_CHECK([absolute reference + asterisk],[list04], 91 LIST_CHECK([absolute reference + asterisk],[list04],
86 ["$cwd/spool" "*"], 92 ["/foo/bar/baz" "*"],
87 [dnl 93 [],
88 * LIST (\NoInferiors) "/" ////bigto.mbox
89 * LIST (\NoInferiors) "/" ////folder/one
90 * LIST (\NoInferiors) "/" ////folder/two
91 * LIST (\NoInferiors) "/" ////mbox
92 * LIST (\NoInferiors) "/" ////mbox1
93 * LIST (\NoInferiors) "/" ////relational.mbox
94 * LIST (\NoInferiors) "/" ////search.mbox
95 * LIST (\NoInferiors) "/" ////sieve.mbox
96 * LIST (\NoInferiors) "/" ////teaparty.mbox
97 * LIST (\NoSelect) "/" ////folder
98 ],
99 [mkdir IMAP4D_HOMEDIR/folder 94 [mkdir IMAP4D_HOMEDIR/folder
100 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder) 95 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
101 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)], 96 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
102 [sed "s|$cwd/IMAP4D_HOMEDIR|///|"],
103 [expand])
104 97
105 LIST_CHECK([absolute reference + percent],[list05], 98 LIST_CHECK([absolute reference + percent],[list05],
106 ["$cwd/spool" "%"], 99 ["/foo/bar/baz" "%"],
107 [dnl 100 [],
108 * LIST (\NoInferiors) "/" ////bigto.mbox
109 * LIST (\NoInferiors) "/" ////mbox
110 * LIST (\NoInferiors) "/" ////mbox1
111 * LIST (\NoInferiors) "/" ////relational.mbox
112 * LIST (\NoInferiors) "/" ////search.mbox
113 * LIST (\NoInferiors) "/" ////sieve.mbox
114 * LIST (\NoInferiors) "/" ////teaparty.mbox
115 * LIST (\NoSelect) "/" ////folder
116 ],
117 [mkdir IMAP4D_HOMEDIR/folder 101 [mkdir IMAP4D_HOMEDIR/folder
118 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder) 102 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
119 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)], 103 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
120 [sed "s|$cwd/IMAP4D_HOMEDIR|///|"],
121 [expand])
122 104
123 LIST_CHECK([absolute reference + mailbox],[list06], 105 LIST_CHECK([absolute reference + mailbox],[list06],
124 ["$cwd/spool" "search.mbox"], 106 ["/foo/bar/baz" "mbox"],
125 [dnl
126 * LIST (\NoInferiors) "/" ////search.mbox
127 ],
128 [], 107 [],
129 [sed "s|$cwd/IMAP4D_HOMEDIR|///|"], 108 [mkdir IMAP4D_HOMEDIR/folder
130 [expand]) 109 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/one,IMAP4D_HOMEDIR/folder)
110 MUT_MBCOPY($abs_top_srcdir/testsuite/folder/two,IMAP4D_HOMEDIR/folder)])
131 111
132 LIST_CHECK([empty reference + INBOX],[list07], 112 LIST_CHECK([empty reference + INBOX],[list07],
133 ["" INBOX], 113 ["" INBOX],
......
...@@ -19,14 +19,9 @@ m4_include([testsuite.inc]) ...@@ -19,14 +19,9 @@ m4_include([testsuite.inc])
19 m4_define([IMAP4D_HOMEDIR]) 19 m4_define([IMAP4D_HOMEDIR])
20 20
21 m4_define([IMAP4D_DEFAULT_OPTIONS],[dnl 21 m4_define([IMAP4D_DEFAULT_OPTIONS],[dnl
22 --no-site-config dnl 22 --no-config dnl
23 --config-file=imap4d.conf dnl
23 --test dnl 24 --test dnl
24 --set logging.syslog=0 dnl
25 --set logging.severity=notice dnl
26 --set .gsasl.enable=0 dnl
27 --set '|homedir='`pwd`m4_if([IMAP4D_HOMEDIR],,,/[IMAP4D_HOMEDIR]) dnl
28 --set '|mailbox|folder='`pwd` dnl
29 --set '|mailbox|mailbox-pattern='`pwd`/INBOX dnl
30 ]) 25 ])
31 26
32 m4_define([IMAP4D_PREAUTH_OPTIONS],[dnl 27 m4_define([IMAP4D_PREAUTH_OPTIONS],[dnl
...@@ -36,22 +31,27 @@ IMAP4D_DEFAULT_OPTIONS dnl ...@@ -36,22 +31,27 @@ IMAP4D_DEFAULT_OPTIONS dnl
36 31
37 m4_define([IMAP4D_OPTIONS],[IMAP4D_PREAUTH_OPTIONS]) 32 m4_define([IMAP4D_OPTIONS],[IMAP4D_PREAUTH_OPTIONS])
38 33
34 m4_define([IMAP4D_CONFIG],[make_config IMAP4D_HOMEDIR])
35
36 m4_define([IMAP4D_RUN],[IMAP4D_CONFIG
37 m4_if([$2],[expand],
38 [cat > input <<EOT
39 $1
40 EOT
41 ],[dnl
42 AT_DATA([input],[$1])dnl
43 ])
44 imap4d IMAP4D_OPTIONS < input | tr -d '\r'])
45
39 dnl ------------------------------------------------------------ 46 dnl ------------------------------------------------------------
40 dnl IMAP4D_CHECK([PREP], [INPUT], [STDOUT = `'], [STDERR = `'], 47 dnl IMAP4D_CHECK([PREP], [INPUT], [STDOUT = `'], [STDERR = `'],
41 dnl [FILTER = `'],[expand]) 48 dnl [FILTER = `'],[expand])
42 dnl 49 dnl
43 m4_pushdef([IMAP4D_CHECK],[ 50 m4_pushdef([IMAP4D_CHECK],[
44 cwd=`pwd` 51 cwd=`pwd`
45 m4_if([$6],,[dnl
46 AT_DATA([input],[$2])dnl
47 ],[cat > input <<EOT
48 [$2]
49 EOT
50 ])
51 $1 52 $1
52 AT_CHECK([ 53 AT_CHECK([
53 imap4d IMAP4D_OPTIONS < input | tr -d '\r' | dnl 54 IMAP4D_RUN([$2],[$6]) | m4_if([$5],,[remove_uidvalidity],[$5])
54 m4_if([$5],,[remove_uidvalidity],[$5])
55 ], 55 ],
56 [0], 56 [0],
57 [$3], 57 [$3],
......
...@@ -17,26 +17,6 @@ ...@@ -17,26 +17,6 @@
17 17
18 #include "imap4d.h" 18 #include "imap4d.h"
19 19
20 /* Get the absolute path. */
21 /* NOTE: Path is allocated and must be free()d by the caller. */
22 char *
23 util_getfullpath (const char *name)
24 {
25 char *exp = mu_tilde_expansion (name, MU_HIERARCHY_DELIMITER,
26 imap4d_homedir);
27 if (*exp != MU_HIERARCHY_DELIMITER)
28 {
29 char *p, *s =
30 mu_alloc (strlen (imap4d_homedir) + 1 + strlen (exp) + 1);
31 p = mu_stpcpy (s, imap4d_homedir);
32 *p++ = MU_HIERARCHY_DELIMITER;
33 strcpy (p, exp);
34 free (exp);
35 exp = s;
36 }
37 return mu_normalize_path (exp);
38 }
39
40 int 20 int
41 util_do_command (struct imap4d_session *session, imap4d_tokbuf_t tok) 21 util_do_command (struct imap4d_session *session, imap4d_tokbuf_t tok)
42 { 22 {
......