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.
Showing
22 changed files
with
385 additions
and
235 deletions
... | @@ -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; |
... | @@ -359,7 +355,179 @@ imap_check_group_list (mu_list_t l) | ... | @@ -359,7 +355,179 @@ imap_check_group_list (mu_list_t l) |
359 | return MU_ERR_NOENT; | 355 | return MU_ERR_NOENT; |
360 | return rc; | 356 | return rc; |
361 | } | 357 | } |
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 | }; | ||
362 | 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", §ion)) | ||
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", §ion)) | ||
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, |
... | @@ -530,52 +704,6 @@ imap4d_session_setup0 () | ... | @@ -530,52 +704,6 @@ imap4d_session_setup0 () |
530 | real_homedir = mu_normalize_path (mu_strdup (auth_data->dir)); | 704 | real_homedir = mu_normalize_path (mu_strdup (auth_data->dir)); |
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 | |||
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 | 707 | ||
580 | if (auth_data->change_uid) | 708 | if (auth_data->change_uid) |
581 | { | 709 | { |
... | @@ -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)); |
... | @@ -959,6 +1084,8 @@ main (int argc, char **argv) | ... | @@ -959,6 +1084,8 @@ main (int argc, char **argv) |
959 | mu_error (_("too many arguments")); | 1084 | mu_error (_("too many arguments")); |
960 | exit (EX_USAGE); | 1085 | exit (EX_USAGE); |
961 | } | 1086 | } |
1087 | |||
1088 | namespace_init (); | ||
962 | 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); |
... | @@ -966,8 +1093,6 @@ main (int argc, char **argv) | ... | @@ -966,8 +1093,6 @@ main (int argc, char **argv) |
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 |
400 | 395 | { | |
401 | extern int namespace_init_session (char *path); | 396 | char *prefix; /* Prefix string */ |
402 | extern void namespace_init (void); | 397 | int delim; /* Delimiter character */ |
403 | extern char *namespace_getfullpath (const char *name, int *pns); | 398 | char *dir; /* Directory in the file system */ |
404 | extern char *namespace_checkfullpath (const char *name, const char *pattern, | 399 | char *scheme; /* Mailbox URL scheme (type) */ |
405 | int *pns); | 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 | |||
420 | |||
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,69 +179,84 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -168,69 +179,84 @@ 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; | ||
188 | |||
189 | if (*wcard == '~') | ||
190 | { | ||
191 | for (i = 1; | ||
192 | mu_c_is_class (wcard[i], MU_CTYPE_ALPHA|MU_CTYPE_DIGIT) | ||
193 | || wcard[i] == '_'; i++) | ||
194 | ; | ||
195 | ref = mu_alloc (i + 1); | ||
196 | memcpy (ref, wcard, i); | ||
197 | ref[i] = 0; | ||
198 | wcard += i; | ||
199 | } | ||
200 | else | ||
201 | ref = mu_strdup (ref); | ||
202 | |||
203 | cwd = namespace_translate_name (ref, 0, &pfx); | ||
204 | if (!cwd) | ||
205 | { | ||
206 | free (ref); | ||
207 | return io_completion_response (command, RESP_NO, | ||
208 | "The requested item could not be found."); | ||
209 | } | ||
210 | free (cwd); | ||
174 | 211 | ||
175 | switch (*wcard) | 212 | if (*wcard == pfx->delim && ref[0] != '~') |
176 | { | 213 | { |
177 | /* Absolute Path in wcard, dump the old ref. */ | 214 | /* Absolute Path in wcard, dump the old ref. */ |
178 | case '/': | 215 | ref[0] = 0; |
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 | { | ||
187 | char *s = strchr (wcard, '/'); | ||
188 | if (s) | ||
189 | { | ||
190 | ref = calloc (s - wcard + 1, 1); | ||
191 | memcpy (ref, wcard, s - wcard); | ||
192 | ref [s - wcard] = '\0'; | ||
193 | wcard = s + 1; | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | ref = mu_strdup (wcard); | ||
198 | wcard += strlen (wcard); | ||
199 | } | ||
200 | } | ||
201 | break; | ||
202 | |||
203 | default: | ||
204 | ref = mu_strdup (ref); | ||
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); |
230 | return io_completion_response (command, RESP_NO, | 244 | return io_completion_response (command, RESP_NO, |
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 | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -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 | { | ... | ... |
-
Please register or sign in to post a comment