Commit 36868ac9 36868ac9ddc6b4e521913858b04ace62d8edfa5a by Sergey Poznyakoff

Additional mailbox URL parameters `type', `user' and `param' can

appear in any local URLs.

* TODO, NEWS: Update.

* examples/url-parse.c: Print field/value pairs.
* include/mailutils/argcv.h (MU_ARGCV_RETURN_DELIMS): New macro.
(mu_argcv_get_np): New function.
(mu_argcv_remove): New function.
* include/mailutils/mutil.h (mu_scheme_autodetect_p): Change
prototype.
* include/mailutils/registrar.h (mu_registrar_lookup_url): New
function.
(struct _mu_record._is_scheme): Change signature.
* include/mailutils/url.h (mu_url_sget_fvpairs)
(mu_url_aget_fvpairs): New functions.
(mu_url_expand_path): New function.

* libproto/imap/folder.c (folder_imap_list): Fix signature.
* libproto/nntp/folder.c (nntp_folder_list): Fix signature.
* libproto/include/amd.h (amd_url_init): Remove.
* libproto/include/registrar0.h: Fix scheme defines.
* libproto/include/url0.h (struct _mu_url.fvpairs,fvcount): New
members.
* libproto/maildir/folder.c (_maildir_is_scheme): Change
signature.
(_maildir_url_init): Remove
(_maildir_record): Remove url_init.
* libproto/mbox/folder.c (_path_record): Remove url_init.
(_mbox_record): Use mu_url_expand_path as url_init.
(_path_is_scheme): Change signature.
* libproto/mh/folder.c (_mh_is_scheme): Change signature.
(_mh_url_init): Remove.
(_mh_record): Use mu_url_expand_path as url_init.
* libproto/mbox/Makefile.am (libmu_mbox_la_SOURCES): Remove url.c
* libproto/mbox/url.c: Remove.

* mail/mail.h, mail/util.c (util_url_to_string): New function.
* mail/quit.c, mail/summary.c: Use util_url_to_string where
appropriate.
* mailbox/amd.c (amd_url_destroy, amd_url_init): Remove.
* mailbox/argcv.c (mu_argcv_get_np): New function.
(argcv_scan): Change signature. All callers updated.
(argcv_get_n): Rewrite using argcv_get_np.
(mu_argcv_remove): New function.

* mailbox/file_stream.c (struct _prog_stream.argc): Fix data type.
* mailbox/folder.c (mu_folder_create_from_record): URL initializer
is optional.
* mailbox/gdebug.c (mu_global_debug_from_string): Fix datatype of
argc.
* mailbox/mailbox.c (mailbox_folder_create): Rewrite.
(_create_mailbox): Split off _create_mailbox0 function.
Make URL initializer optional.
* mailbox/mutil.c (mu_scheme_autodetect_p): Rewrite.
* mailbox/registrar.c (mu_registrar_lookup_url): New function.
(mu_registrar_lookup): Rewrite using mu_registrar_lookup_url.
(mu_record_is_scheme,mu_record_set_is_scheme): Change signature.
* mailbox/url.c (mu_url_destroy): Destroy fvpairs.
(url_parse0): Use scheme "file" for URLs beginning with a /.
Parse parameters.
(mu_url_sget_fvpairs, mu_url_aget_fvpairs): New functions.
(mu_url_expand_path): New function.
* mailbox/testsuite/Urls: Update.

* pop3d/bulletin.c (set_bulletin_db,set_bulletin_source): Allocate
string storage.
(read_bulletin_db): Return 0 if no record was found.
(get_last_delivered_num): Return error code.
(deliver_pending_bulletins): Rewrite.
* pop3d/capa.c (pop3d_capa): Bugfix.
1 parent 7b123e22
1 2007-12-28 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 Additional mailbox URL parameters `type', `user' and `param' can
4 appear in any local URLs.
5
6 * TODO, NEWS: Update.
7
8 * examples/url-parse.c: Print field/value pairs.
9 * include/mailutils/argcv.h (MU_ARGCV_RETURN_DELIMS): New macro.
10 (mu_argcv_get_np): New function.
11 (mu_argcv_remove): New function.
12 * include/mailutils/mutil.h (mu_scheme_autodetect_p): Change
13 prototype.
14 * include/mailutils/registrar.h (mu_registrar_lookup_url): New
15 function.
16 (struct _mu_record._is_scheme): Change signature.
17 * include/mailutils/url.h (mu_url_sget_fvpairs)
18 (mu_url_aget_fvpairs): New functions.
19 (mu_url_expand_path): New function.
20
21 * libproto/imap/folder.c (folder_imap_list): Fix signature.
22 * libproto/nntp/folder.c (nntp_folder_list): Fix signature.
23 * libproto/include/amd.h (amd_url_init): Remove.
24 * libproto/include/registrar0.h: Fix scheme defines.
25 * libproto/include/url0.h (struct _mu_url.fvpairs,fvcount): New
26 members.
27 * libproto/maildir/folder.c (_maildir_is_scheme): Change
28 signature.
29 (_maildir_url_init): Remove
30 (_maildir_record): Remove url_init.
31 * libproto/mbox/folder.c (_path_record): Remove url_init.
32 (_mbox_record): Use mu_url_expand_path as url_init.
33 (_path_is_scheme): Change signature.
34 * libproto/mh/folder.c (_mh_is_scheme): Change signature.
35 (_mh_url_init): Remove.
36 (_mh_record): Use mu_url_expand_path as url_init.
37 * libproto/mbox/Makefile.am (libmu_mbox_la_SOURCES): Remove url.c
38 * libproto/mbox/url.c: Remove.
39
40 * mail/mail.h, mail/util.c (util_url_to_string): New function.
41 * mail/quit.c, mail/summary.c: Use util_url_to_string where
42 appropriate.
43 * mailbox/amd.c (amd_url_destroy, amd_url_init): Remove.
44 * mailbox/argcv.c (mu_argcv_get_np): New function.
45 (argcv_scan): Change signature. All callers updated.
46 (argcv_get_n): Rewrite using argcv_get_np.
47 (mu_argcv_remove): New function.
48
49 * mailbox/file_stream.c (struct _prog_stream.argc): Fix data type.
50 * mailbox/folder.c (mu_folder_create_from_record): URL initializer
51 is optional.
52 * mailbox/gdebug.c (mu_global_debug_from_string): Fix datatype of
53 argc.
54 * mailbox/mailbox.c (mailbox_folder_create): Rewrite.
55 (_create_mailbox): Split off _create_mailbox0 function.
56 Make URL initializer optional.
57 * mailbox/mutil.c (mu_scheme_autodetect_p): Rewrite.
58 * mailbox/registrar.c (mu_registrar_lookup_url): New function.
59 (mu_registrar_lookup): Rewrite using mu_registrar_lookup_url.
60 (mu_record_is_scheme,mu_record_set_is_scheme): Change signature.
61 * mailbox/url.c (mu_url_destroy): Destroy fvpairs.
62 (url_parse0): Use scheme "file" for URLs beginning with a /.
63 Parse parameters.
64 (mu_url_sget_fvpairs, mu_url_aget_fvpairs): New functions.
65 (mu_url_expand_path): New function.
66 * mailbox/testsuite/Urls: Update.
67
68 * pop3d/bulletin.c (set_bulletin_db,set_bulletin_source): Allocate
69 string storage.
70 (read_bulletin_db): Return 0 if no record was found.
71 (get_last_delivered_num): Return error code.
72 (deliver_pending_bulletins): Rewrite.
73 * pop3d/capa.c (pop3d_capa): Bugfix.
74
1 2007-12-21 Sergey Poznyakoff <gray@gnu.org.ua> 75 2007-12-21 Sergey Poznyakoff <gray@gnu.org.ua>
2 76
3 * examples/lsf.c: Use mu_folder_enumerate + callback function, for 77 * examples/lsf.c: Use mu_folder_enumerate + callback function, for
......
1 GNU mailutils NEWS -- history of user-visible changes. 2007-12-19 1 GNU mailutils NEWS -- history of user-visible changes. 2007-12-28
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
3 See the end of file for copying conditions. 3 See the end of file for copying conditions.
4 4
...@@ -26,6 +26,11 @@ The programs using configuration file facility also understand the ...@@ -26,6 +26,11 @@ The programs using configuration file facility also understand the
26 output the detailed description of configuration file statements that 26 output the detailed description of configuration file statements that
27 affect the given program. 27 affect the given program.
28 28
29 ** URL parameters.
30
31 Additional mailbox URL parameters `type', `user' and `param' can
32 appear in any local URLs.
33
29 ** New utility `maidag' 34 ** New utility `maidag'
30 35
31 Maidag is a MAIl Delivery AGent. It is a general-purpose MDA able to 36 Maidag is a MAIl Delivery AGent. It is a general-purpose MDA able to
...@@ -185,6 +190,9 @@ extern int mu_url_aget_path (const mu_url_t, char **); ...@@ -185,6 +190,9 @@ extern int mu_url_aget_path (const mu_url_t, char **);
185 extern int mu_url_sget_query (const mu_url_t, const char **); 190 extern int mu_url_sget_query (const mu_url_t, const char **);
186 extern int mu_url_aget_query (const mu_url_t, char **); 191 extern int mu_url_aget_query (const mu_url_t, char **);
187 192
193 int mu_url_sget_fvpairs (const mu_url_t, size_t *, char ***);
194 int mu_url_aget_fvpairs (const mu_url_t, size_t *, char ***);
195
188 ** ACL 196 ** ACL
189 197
190 A set of functions implements general-purpose access control lists. 198 A set of functions implements general-purpose access control lists.
...@@ -227,6 +235,29 @@ that can be done over them is mu_mailbox_append_message. E.g., ...@@ -227,6 +235,29 @@ that can be done over them is mu_mailbox_append_message. E.g.,
227 appending to the URL `remote+smtp://127.0.0.1:24' is equivalent to 235 appending to the URL `remote+smtp://127.0.0.1:24' is equivalent to
228 sending a message using mailer `smtp://127.0.0.1:24'. 236 sending a message using mailer `smtp://127.0.0.1:24'.
229 237
238 ** New argcv functions.
239
240 - int mu_argcv_get_np (const char *command, int len,
241 const char *delim, const char *cmnt,
242 int flags,
243 int *pargc, char ***pargv, char **endp);
244
245 This function is an alternative entry point to
246 mu_argcv_get/mu_argcv_get_n functions. The resulting argv will contain
247 non-whitespace delimiters only if flags contains the bit
248 MU_ARGCV_RETURN_DELIMS.
249
250 - void mu_argcv_remove (int *pargc, char ***pargv,
251 int (*sel) (const char *, void *), void *);
252
253 Removes from pargc/pargv all elements for which the sel function
254 returns true.
255
256 ** New registry functions.
257
258 - int mu_registrar_lookup_url (mu_url_t url, int flags,
259 mu_record_t *precord, int *pflags);
260
230 ** Fixed parsing of URLs similar to file:///a/b. 261 ** Fixed parsing of URLs similar to file:///a/b.
231 262
232 It is parsed as an absolute file name `/a/b'. 263 It is parsed as an absolute file name `/a/b'.
......
1 GNU mailutils TODO list. 2007-12-07 1 GNU mailutils TODO list. 2007-12-28
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
3 2007 Free Software Foundation, Inc. 3 2007 Free Software Foundation, Inc.
4 4
5 * Fix folder_imap_list in libproto/imap/folder.c
6
5 * Documentation 7 * Documentation
6 8
7 * Review the code and use mu_vartab_* and mu_kwd_* functions where 9 * Review the code and use mu_vartab_* and mu_kwd_* functions where
......
...@@ -39,6 +39,22 @@ ...@@ -39,6 +39,22 @@
39 } \ 39 } \
40 printf ("\t" #field " <%s>\n", buf) 40 printf ("\t" #field " <%s>\n", buf)
41 41
42 static void
43 print_fvpairs (mu_url_t url)
44 {
45 size_t fvc, i;
46 char **fvp;
47 int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
48 if (rc)
49 {
50 mu_error ("cannot get F/V pairs: %s", mu_strerror (rc));
51 exit (1);
52 }
53 if (fvc == 0)
54 return;
55 for (i = 0; i < fvc; i++)
56 printf ("\tparam[%d] <%s>\n", i, fvp[i]);
57 }
42 58
43 int 59 int
44 main () 60 main ()
...@@ -84,6 +100,7 @@ main () ...@@ -84,6 +100,7 @@ main ()
84 printf ("\tport %ld\n", port); 100 printf ("\tport %ld\n", port);
85 101
86 GET_AND_PRINT (path, u, buf, rc); 102 GET_AND_PRINT (path, u, buf, rc);
103 print_fvpairs (u);
87 GET_AND_PRINT (query, u, buf, rc); 104 GET_AND_PRINT (query, u, buf, rc);
88 105
89 mu_url_destroy (&u); 106 mu_url_destroy (&u);
......
...@@ -28,12 +28,18 @@ ...@@ -28,12 +28,18 @@
28 extern "C" { 28 extern "C" {
29 #endif 29 #endif
30 30
31 #define MU_ARGCV_RETURN_DELIMS 0x01
32
31 extern int mu_argcv_get (const char *command, const char *delim, 33 extern int mu_argcv_get (const char *command, const char *delim,
32 const char* cmnt, 34 const char* cmnt,
33 int *argc, char ***argv); 35 int *argc, char ***argv);
34 extern int mu_argcv_get_n (const char *command, int len, 36 extern int mu_argcv_get_n (const char *command, int len,
35 const char *delim, const char *cmnt, 37 const char *delim, const char *cmnt,
36 int *argc, char ***argv); 38 int *argc, char ***argv);
39 extern int mu_argcv_get_np (const char *command, int len,
40 const char *delim, const char *cmnt,
41 int flags,
42 int *pargc, char ***pargv, char **endp);
37 43
38 extern int mu_argcv_string (int argc, char **argv, char **string); 44 extern int mu_argcv_string (int argc, char **argv, char **string);
39 extern int mu_argcv_free (int argc, char **argv); 45 extern int mu_argcv_free (int argc, char **argv);
...@@ -42,6 +48,8 @@ extern int mu_argcv_quote_char (int c); ...@@ -42,6 +48,8 @@ extern int mu_argcv_quote_char (int c);
42 extern size_t mu_argcv_quoted_length (const char *str, int *quote); 48 extern size_t mu_argcv_quoted_length (const char *str, int *quote);
43 extern void mu_argcv_unquote_copy (char *dst, const char *src, size_t n); 49 extern void mu_argcv_unquote_copy (char *dst, const char *src, size_t n);
44 extern void mu_argcv_quote_copy (char *dst, const char *src); 50 extern void mu_argcv_quote_copy (char *dst, const char *src);
51 extern void mu_argcv_remove (int *pargc, char ***pargv,
52 int (*sel) (const char *, void *), void *);
45 53
46 #ifdef __cplusplus 54 #ifdef __cplusplus
47 } 55 }
......
...@@ -128,7 +128,7 @@ extern int mu_unre_subject (const char *subject, const char **new_subject); ...@@ -128,7 +128,7 @@ extern int mu_unre_subject (const char *subject, const char **new_subject);
128 extern char *mu_charset_lookup (char *lang, char *terr); 128 extern char *mu_charset_lookup (char *lang, char *terr);
129 129
130 extern int mu_true_answer_p (const char *p); 130 extern int mu_true_answer_p (const char *p);
131 extern int mu_scheme_autodetect_p (const char *scheme, const char **path); 131 extern int mu_scheme_autodetect_p (mu_url_t);
132 132
133 struct timeval; 133 struct timeval;
134 134
......
...@@ -38,7 +38,7 @@ struct _mu_record ...@@ -38,7 +38,7 @@ struct _mu_record
38 void *data; /* back pointer. */ 38 void *data; /* back pointer. */
39 39
40 /* Stub functions to override. The default is to return the fields. */ 40 /* Stub functions to override. The default is to return the fields. */
41 int (*_is_scheme) (mu_record_t, const char *, int); 41 int (*_is_scheme) (mu_record_t, mu_url_t, int);
42 int (*_get_url) (mu_record_t, int (*(*_mu_url)) (mu_url_t)); 42 int (*_get_url) (mu_record_t, int (*(*_mu_url)) (mu_url_t));
43 int (*_get_mailbox) (mu_record_t, int (*(*_mu_mailbox)) (mu_mailbox_t)); 43 int (*_get_mailbox) (mu_record_t, int (*(*_mu_mailbox)) (mu_mailbox_t));
44 int (*_get_mailer) (mu_record_t, int (*(*_mu_mailer)) (mu_mailer_t)); 44 int (*_get_mailer) (mu_record_t, int (*(*_mu_mailer)) (mu_mailer_t));
...@@ -51,14 +51,16 @@ extern int mu_registrar_get_list (mu_list_t *) __attribute__ ((deprecated)); ...@@ -51,14 +51,16 @@ extern int mu_registrar_get_list (mu_list_t *) __attribute__ ((deprecated));
51 51
52 extern int mu_registrar_lookup (const char *name, int flags, 52 extern int mu_registrar_lookup (const char *name, int flags,
53 mu_record_t *precord, int *pflags); 53 mu_record_t *precord, int *pflags);
54 extern int mu_registrar_lookup_url (mu_url_t url, int flags,
55 mu_record_t *precord, int *pflags);
54 extern int mu_registrar_record (mu_record_t); 56 extern int mu_registrar_record (mu_record_t);
55 extern int mu_unregistrar_record (mu_record_t); 57 extern int mu_unregistrar_record (mu_record_t);
56 58
57 /* Scheme. */ 59 /* Scheme. */
58 extern int mu_record_is_scheme (mu_record_t, const char *, int flags); 60 extern int mu_record_is_scheme (mu_record_t, mu_url_t, int flags);
59 extern int mu_record_set_scheme (mu_record_t, const char *); 61 extern int mu_record_set_scheme (mu_record_t, const char *);
60 extern int mu_record_set_is_scheme (mu_record_t, 62 extern int mu_record_set_is_scheme (mu_record_t,
61 int (*_is_scheme) (mu_record_t, const char *, int)); 63 int (*_is_scheme) (mu_record_t, mu_url_t, int));
62 64
63 /* Url. */ 65 /* Url. */
64 extern int mu_record_get_url (mu_record_t, int (*(*)) (mu_url_t)); 66 extern int mu_record_get_url (mu_record_t, int (*(*)) (mu_url_t));
......
...@@ -59,9 +59,13 @@ extern int mu_url_get_query (const mu_url_t, char *, size_t, size_t *); ...@@ -59,9 +59,13 @@ extern int mu_url_get_query (const mu_url_t, char *, size_t, size_t *);
59 59
60 extern int mu_url_get_port (const mu_url_t, long *); 60 extern int mu_url_get_port (const mu_url_t, long *);
61 61
62 int mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp);
63 int mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp);
64
65 extern int mu_url_expand_path (mu_url_t url);
62 extern const char *mu_url_to_string (const mu_url_t); 66 extern const char *mu_url_to_string (const mu_url_t);
63 67
64 extern int mu_url_is_scheme (mu_url_t, const char* scheme); 68 extern int mu_url_is_scheme (mu_url_t, const char *scheme);
65 69
66 extern int mu_url_is_same_scheme (mu_url_t, mu_url_t); 70 extern int mu_url_is_same_scheme (mu_url_t, mu_url_t);
67 extern int mu_url_is_same_user (mu_url_t, mu_url_t); 71 extern int mu_url_is_same_user (mu_url_t, mu_url_t);
...@@ -69,7 +73,7 @@ extern int mu_url_is_same_path (mu_url_t, mu_url_t); ...@@ -69,7 +73,7 @@ extern int mu_url_is_same_path (mu_url_t, mu_url_t);
69 extern int mu_url_is_same_host (mu_url_t, mu_url_t); 73 extern int mu_url_is_same_host (mu_url_t, mu_url_t);
70 extern int mu_url_is_same_port (mu_url_t, mu_url_t); 74 extern int mu_url_is_same_port (mu_url_t, mu_url_t);
71 75
72 extern char* mu_url_decode (const char *s); 76 extern char *mu_url_decode (const char *s);
73 77
74 extern int mu_url_is_ticket (mu_url_t ticket, mu_url_t url); 78 extern int mu_url_is_ticket (mu_url_t ticket, mu_url_t url);
75 extern int mu_url_init (mu_url_t url, int port, const char *scheme); 79 extern int mu_url_init (mu_url_t url, int port, const char *scheme);
......
...@@ -143,6 +143,8 @@ streq.h ...@@ -143,6 +143,8 @@ streq.h
143 strerror.c 143 strerror.c
144 string.h 144 string.h
145 string.in.h 145 string.in.h
146 strings.h
147 strings.in.h
146 stripslash.c 148 stripslash.c
147 strncasecmp.c 149 strncasecmp.c
148 strndup.c 150 strndup.c
......
...@@ -112,7 +112,7 @@ static int folder_imap_close (mu_folder_t); ...@@ -112,7 +112,7 @@ static int folder_imap_close (mu_folder_t);
112 static void folder_imap_destroy (mu_folder_t); 112 static void folder_imap_destroy (mu_folder_t);
113 static int folder_imap_delete (mu_folder_t, const char *); 113 static int folder_imap_delete (mu_folder_t, const char *);
114 static int folder_imap_list (mu_folder_t, const char *, void *, 114 static int folder_imap_list (mu_folder_t, const char *, void *,
115 size_t, 115 int, size_t,
116 mu_list_t, 116 mu_list_t,
117 mu_folder_enumerate_fp efp, void *edp); 117 mu_folder_enumerate_fp efp, void *edp);
118 static int folder_imap_lsub (mu_folder_t, const char *, const char *, 118 static int folder_imap_lsub (mu_folder_t, const char *, const char *,
...@@ -975,9 +975,10 @@ glob_to_imap (const char *pat, int recursive) ...@@ -975,9 +975,10 @@ glob_to_imap (const char *pat, int recursive)
975 return ret; 975 return ret;
976 } 976 }
977 977
978 /* FIXME: Flags unused */
978 static int 979 static int
979 folder_imap_list (mu_folder_t folder, const char *ref, void *name, 980 folder_imap_list (mu_folder_t folder, const char *ref, void *name,
980 size_t max_level, 981 int flags, size_t max_level,
981 mu_list_t flist, 982 mu_list_t flist,
982 mu_folder_enumerate_fp efp, void *edp) 983 mu_folder_enumerate_fp efp, void *edp)
983 { 984 {
......
...@@ -99,7 +99,6 @@ int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg); ...@@ -99,7 +99,6 @@ int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg);
99 int amd_message_stream_open (struct _amd_message *mhm); 99 int amd_message_stream_open (struct _amd_message *mhm);
100 void amd_message_stream_close (struct _amd_message *mhm); 100 void amd_message_stream_close (struct _amd_message *mhm);
101 void amd_cleanup (void *arg); 101 void amd_cleanup (void *arg);
102 int amd_url_init (mu_url_t url, const char *scheme);
103 struct _amd_message *_amd_get_message (struct _amd_data *amd, size_t msgno); 102 struct _amd_message *_amd_get_message (struct _amd_data *amd, size_t msgno);
104 int amd_msg_lookup (struct _amd_data *amd, struct _amd_message *msg, 103 int amd_msg_lookup (struct _amd_data *amd, struct _amd_message *msg,
105 size_t *pret); 104 size_t *pret);
......
...@@ -36,62 +36,60 @@ extern "C" { ...@@ -36,62 +36,60 @@ extern "C" {
36 Perhaps they can be changed? 36 Perhaps they can be changed?
37 */ 37 */
38 #define MU_POP_PORT 110 38 #define MU_POP_PORT 110
39 #define MU_POP_SCHEME "pop://" 39 #define MU_POP_SCHEME "pop"
40 #define MU_POP_SCHEME_LEN (sizeof (MU_POP_SCHEME) - 1) 40 #define MU_POP_SCHEME_LEN (sizeof (MU_POP_SCHEME) - 1)
41 extern int _url_pop_init (mu_url_t); 41 extern int _url_pop_init (mu_url_t);
42 extern int _mailbox_pop_init (mu_mailbox_t); 42 extern int _mailbox_pop_init (mu_mailbox_t);
43 extern int _folder_pop_init (mu_folder_t); 43 extern int _folder_pop_init (mu_folder_t);
44 44
45 #define MU_POPS_PORT 995 45 #define MU_POPS_PORT 995
46 #define MU_POPS_SCHEME "pops://" 46 #define MU_POPS_SCHEME "pops"
47 #define MU_POPS_SCHEME_LEN (sizeof (MU_POPS_SCHEME) - 1) 47 #define MU_POPS_SCHEME_LEN (sizeof (MU_POPS_SCHEME) - 1)
48 extern int _url_pops_init (mu_url_t); 48 extern int _url_pops_init (mu_url_t);
49 extern int _mailbox_pops_init (mu_mailbox_t); 49 extern int _mailbox_pops_init (mu_mailbox_t);
50 50
51 #define MU_IMAP_PORT 143 51 #define MU_IMAP_PORT 143
52 #define MU_IMAP_SCHEME "imap://" 52 #define MU_IMAP_SCHEME "imap"
53 #define MU_IMAP_SCHEME_LEN (sizeof (MU_IMAP_SCHEME) - 1) 53 #define MU_IMAP_SCHEME_LEN (sizeof (MU_IMAP_SCHEME) - 1)
54 extern int _url_imap_init (mu_url_t); 54 extern int _url_imap_init (mu_url_t);
55 extern int _mailbox_imap_init (mu_mailbox_t); 55 extern int _mailbox_imap_init (mu_mailbox_t);
56 extern int _folder_imap_init (mu_folder_t); 56 extern int _folder_imap_init (mu_folder_t);
57 57
58 #define MU_IMAPS_PORT 993 58 #define MU_IMAPS_PORT 993
59 #define MU_IMAPS_SCHEME "imaps://" 59 #define MU_IMAPS_SCHEME "imaps"
60 #define MU_IMAPS_SCHEME_LEN (sizeof (MU_IMAPS_SCHEME) - 1) 60 #define MU_IMAPS_SCHEME_LEN (sizeof (MU_IMAPS_SCHEME) - 1)
61 extern int _url_imaps_init (mu_url_t); 61 extern int _url_imaps_init (mu_url_t);
62 extern int _mailbox_imaps_init (mu_mailbox_t); 62 extern int _mailbox_imaps_init (mu_mailbox_t);
63 63
64 #define MU_MBOX_SCHEME "mbox:" 64 #define MU_MBOX_SCHEME "mbox"
65 #define MU_MBOX_SCHEME_LEN (sizeof (MU_MBOX_SCHEME) - 1) 65 #define MU_MBOX_SCHEME_LEN (sizeof (MU_MBOX_SCHEME) - 1)
66 extern int _url_mbox_init (mu_url_t);
67 extern int _mailbox_mbox_init (mu_mailbox_t); 66 extern int _mailbox_mbox_init (mu_mailbox_t);
68 extern int _folder_mbox_init (mu_folder_t); 67 extern int _folder_mbox_init (mu_folder_t);
69 68
70 #define MU_FILE_SCHEME "file:" 69 #define MU_FILE_SCHEME "file"
71 #define MU_FILE_SCHEME_LEN (sizeof (MU_FILE_SCHEME) - 1) 70 #define MU_FILE_SCHEME_LEN (sizeof (MU_FILE_SCHEME) - 1)
72 71
73 #define MU_PATH_SCHEME "/" 72 #define MU_PATH_SCHEME "/"
74 #define MU_PATH_SCHEME_LEN (sizeof (MU_PATH_SCHEME) - 1) 73 #define MU_PATH_SCHEME_LEN (sizeof (MU_PATH_SCHEME) - 1)
75 extern int _url_path_init (mu_url_t);
76 extern int _mailbox_path_init (mu_mailbox_t); 74 extern int _mailbox_path_init (mu_mailbox_t);
77 extern int _folder_path_init (mu_folder_t); 75 extern int _folder_path_init (mu_folder_t);
78 76
79 #define MU_SMTP_SCHEME "smtp://" 77 #define MU_SMTP_SCHEME "smtp"
80 #define MU_SMTP_SCHEME_LEN (sizeof (MU_SMTP_SCHEME) - 1) 78 #define MU_SMTP_SCHEME_LEN (sizeof (MU_SMTP_SCHEME) - 1)
81 #define MU_SMTP_PORT 25 79 #define MU_SMTP_PORT 25
82 extern int _url_smtp_init (mu_url_t); 80 extern int _url_smtp_init (mu_url_t);
83 extern int _mailer_smtp_init (mu_mailer_t); 81 extern int _mailer_smtp_init (mu_mailer_t);
84 82
85 #define MU_SENDMAIL_SCHEME "sendmail:" 83 #define MU_SENDMAIL_SCHEME "sendmail"
86 #define MU_SENDMAIL_SCHEME_LEN (sizeof (MU_SENDMAIL_SCHEME) - 1) 84 #define MU_SENDMAIL_SCHEME_LEN (sizeof (MU_SENDMAIL_SCHEME) - 1)
87 extern int _url_sendmail_init (mu_url_t); 85 extern int _url_sendmail_init (mu_url_t);
88 extern int _mailer_sendmail_init (mu_mailer_t); 86 extern int _mailer_sendmail_init (mu_mailer_t);
89 87
90 #define MU_MH_SCHEME "mh:" 88 #define MU_MH_SCHEME "mh"
91 #define MU_MH_SCHEME_LEN (sizeof (MU_MH_SCHEME) - 1) 89 #define MU_MH_SCHEME_LEN (sizeof (MU_MH_SCHEME) - 1)
92 extern int _mailbox_mh_init (mu_mailbox_t mailbox); 90 extern int _mailbox_mh_init (mu_mailbox_t mailbox);
93 91
94 #define MU_MAILDIR_SCHEME "maildir:" 92 #define MU_MAILDIR_SCHEME "maildir"
95 #define MU_MAILDIR_SCHEME_LEN (sizeof (MU_MAILDIR_SCHEME) - 1) 93 #define MU_MAILDIR_SCHEME_LEN (sizeof (MU_MAILDIR_SCHEME) - 1)
96 extern int _mailbox_maildir_init (mu_mailbox_t mailbox); 94 extern int _mailbox_maildir_init (mu_mailbox_t mailbox);
97 95
......
...@@ -40,9 +40,10 @@ struct _mu_url ...@@ -40,9 +40,10 @@ struct _mu_url
40 char *host; 40 char *host;
41 long port; 41 long port;
42 char *path; 42 char *path;
43 char **fvpairs;
44 int fvcount;
43 char *query; 45 char *query;
44 46
45
46 void *data; 47 void *data;
47 48
48 void (*_destroy) (mu_url_t url); 49 void (*_destroy) (mu_url_t url);
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
33 33
34 #include <maildir.h> 34 #include <maildir.h>
35 #include <mailutils/mutil.h> 35 #include <mailutils/mutil.h>
36 #include <mailutils/url.h>
36 #include <amd.h> 37 #include <amd.h>
37 38
38 static int 39 static int
...@@ -56,22 +57,21 @@ dir_exists (const char *name, const char *suf) ...@@ -56,22 +57,21 @@ dir_exists (const char *name, const char *suf)
56 } 57 }
57 58
58 static int 59 static int
59 _maildir_is_scheme (mu_record_t record, const char *url, int flags) 60 _maildir_is_scheme (mu_record_t record, mu_url_t url, int flags)
60 { 61 {
61 const char *path; 62 if (mu_url_is_scheme (url, record->scheme))
62
63 if (!url || !record->scheme)
64 return 0;
65
66 if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
67 return MU_FOLDER_ATTRIBUTE_ALL & flags; 63 return MU_FOLDER_ATTRIBUTE_ALL & flags;
68 64
69 if (mu_scheme_autodetect_p (url, &path)) 65 if (mu_scheme_autodetect_p (url))
70 { 66 {
71 /* Attemp auto-detection */ 67 /* Attemp auto-detection */
68 const char *path;
72 struct stat st; 69 struct stat st;
73 int rc = 0; 70 int rc = 0;
74 71
72 if (mu_url_sget_path (url, &path))
73 return 0;
74
75 if (stat (path, &st) < 0) 75 if (stat (path, &st) < 0)
76 return 0; 76 return 0;
77 77
...@@ -89,21 +89,11 @@ _maildir_is_scheme (mu_record_t record, const char *url, int flags) ...@@ -89,21 +89,11 @@ _maildir_is_scheme (mu_record_t record, const char *url, int flags)
89 return 0; 89 return 0;
90 } 90 }
91 91
92 /*
93 MAILDIR url
94 maildir:path
95 */
96 int
97 _maildir_url_init (mu_url_t url)
98 {
99 return amd_url_init (url, MU_MAILDIR_SCHEME);
100 }
101
102 static struct _mu_record _maildir_record = 92 static struct _mu_record _maildir_record =
103 { 93 {
104 MU_MAILDIR_PRIO, 94 MU_MAILDIR_PRIO,
105 MU_MAILDIR_SCHEME, 95 MU_MAILDIR_SCHEME,
106 _maildir_url_init, /* Url init. */ 96 mu_url_expand_path, /* Url init. */
107 _mailbox_maildir_init, /* Mailbox init. */ 97 _mailbox_maildir_init, /* Mailbox init. */
108 NULL, /* Mailer init. */ 98 NULL, /* Mailer init. */
109 _maildir_folder_init, /* Folder init. */ 99 _maildir_folder_init, /* Folder init. */
......
...@@ -26,6 +26,5 @@ libmu_mbox_la_SOURCES = \ ...@@ -26,6 +26,5 @@ libmu_mbox_la_SOURCES = \
26 folder.c\ 26 folder.c\
27 mbox.c\ 27 mbox.c\
28 mboxscan.c\ 28 mboxscan.c\
29 mbox0.h\ 29 mbox0.h
30 url.c
31 30
......
...@@ -50,7 +50,7 @@ static struct _mu_record _mbox_record = ...@@ -50,7 +50,7 @@ static struct _mu_record _mbox_record =
50 { 50 {
51 MU_MBOX_PRIO, 51 MU_MBOX_PRIO,
52 MU_MBOX_SCHEME, 52 MU_MBOX_SCHEME,
53 _url_mbox_init, /* Mailbox init. */ 53 mu_url_expand_path, /* URL init. */
54 _mailbox_mbox_init, /* Mailbox init. */ 54 _mailbox_mbox_init, /* Mailbox init. */
55 NULL, /* Mailer init. */ 55 NULL, /* Mailer init. */
56 _folder_mbox_init, /* Folder init. */ 56 _folder_mbox_init, /* Folder init. */
...@@ -64,19 +64,18 @@ static struct _mu_record _mbox_record = ...@@ -64,19 +64,18 @@ static struct _mu_record _mbox_record =
64 mu_record_t mu_mbox_record = &_mbox_record; 64 mu_record_t mu_mbox_record = &_mbox_record;
65 65
66 static int 66 static int
67 _path_is_scheme (mu_record_t record, const char *url, int flags) 67 _path_is_scheme (mu_record_t record, mu_url_t url, int flags)
68 { 68 {
69 int rc = 0; 69 int rc = 0;
70 const char *path;
71 70
72 if (url && record->scheme) 71 if (url && record->scheme)
73 { 72 {
74 if (mu_scheme_autodetect_p (url, &path)) 73 if (mu_scheme_autodetect_p (url))
75 /* implies:
76 if (strncmp (record->scheme, url, strlen(record->scheme)) == 0) */
77 { 74 {
78 struct stat st; 75 struct stat st;
76 const char *path;
79 77
78 mu_url_sget_path (url, &path);
80 if (stat (path, &st) < 0) 79 if (stat (path, &st) < 0)
81 { 80 {
82 if (errno == ENOENT) 81 if (errno == ENOENT)
...@@ -92,6 +91,10 @@ _path_is_scheme (mu_record_t record, const char *url, int flags) ...@@ -92,6 +91,10 @@ _path_is_scheme (mu_record_t record, const char *url, int flags)
92 } 91 }
93 else if (flags & MU_FOLDER_ATTRIBUTE_FILE) 92 else if (flags & MU_FOLDER_ATTRIBUTE_FILE)
94 { 93 {
94 #if 0
95 /* This effectively sieves out all non-mailbox files,
96 but it makes mu_folder_enumerate crawl, which is
97 intolerable for imap4d LIST command. */
95 int fd = open (path, O_RDONLY); 98 int fd = open (path, O_RDONLY);
96 if (fd != -1) 99 if (fd != -1)
97 { 100 {
...@@ -101,6 +104,9 @@ _path_is_scheme (mu_record_t record, const char *url, int flags) ...@@ -101,6 +104,9 @@ _path_is_scheme (mu_record_t record, const char *url, int flags)
101 rc |= MU_FOLDER_ATTRIBUTE_FILE; 104 rc |= MU_FOLDER_ATTRIBUTE_FILE;
102 close (fd); 105 close (fd);
103 } 106 }
107 #else
108 rc |= MU_FOLDER_ATTRIBUTE_FILE;
109 #endif
104 } 110 }
105 } 111 }
106 112
...@@ -116,7 +122,7 @@ static struct _mu_record _path_record = ...@@ -116,7 +122,7 @@ static struct _mu_record _path_record =
116 { 122 {
117 MU_PATH_PRIO, 123 MU_PATH_PRIO,
118 MU_PATH_SCHEME, 124 MU_PATH_SCHEME,
119 _url_path_init, /* Mailbox init. */ 125 NULL, /* URL init. */
120 _mailbox_mbox_init, /* Mailbox init. */ 126 _mailbox_mbox_init, /* Mailbox init. */
121 NULL, /* Mailer init. */ 127 NULL, /* Mailer init. */
122 _folder_mbox_init, /* Folder init. */ 128 _folder_mbox_init, /* Folder init. */
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2003, 2007 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27
28 #ifdef HAVE_STRINGS_H
29 # include <strings.h>
30 #endif
31
32 #include <registrar0.h>
33 #include <url0.h>
34 #include <mailutils/errno.h>
35 #include <mailutils/mutil.h>
36
37 static void url_mbox_destroy (mu_url_t purl);
38
39 static void
40 url_mbox_destroy (mu_url_t url MU_ARG_UNUSED)
41 {
42 }
43
44 /* Default mailbox path generator */
45 static char *
46 _url_path_default (const char *spooldir, const char *user, int unused)
47 {
48 char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2);
49 if (!mbox)
50 errno = ENOMEM;
51 else
52 sprintf (mbox, "%s/%s", spooldir, user);
53 return mbox;
54 }
55
56 /* Hashed indexing */
57 static char *
58 _url_path_hashed (const char *spooldir, const char *user, int param)
59 {
60 int i;
61 int ulen = strlen (user);
62 char *mbox;
63 unsigned hash;
64
65 if (param > ulen)
66 param = ulen;
67 for (i = 0, hash = 0; i < param; i++)
68 hash += user[i];
69
70 mbox = malloc (ulen + strlen (spooldir) + 5);
71 sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
72 return mbox;
73 }
74
75 static int transtab[] = {
76 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
77 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
78 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
79 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
80 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
81 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
82 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
83 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
84 'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
85 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
86 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
87 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
88 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
89 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
90 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
91 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
92 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
93 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
94 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
95 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
96 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
97 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
98 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
99 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
100 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
101 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
102 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
103 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
104 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
105 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
106 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
107 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
108 };
109
110 /* Forward Indexing */
111 static char *
112 _url_path_index (const char *spooldir, const char *iuser, int index_depth)
113 {
114 const unsigned char* user = (const unsigned char*) iuser;
115 int i, ulen = strlen (iuser);
116 char *mbox, *p;
117
118 if (ulen == 0)
119 return NULL;
120
121 mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
122 strcpy (mbox, spooldir);
123 p = mbox + strlen (mbox);
124 for (i = 0; i < index_depth && i < ulen; i++)
125 {
126 *p++ = '/';
127 *p++ = transtab[ user[i] ];
128 }
129 for (; i < index_depth; i++)
130 {
131 *p++ = '/';
132 *p++ = transtab[ user[ulen-1] ];
133 }
134 *p++ = '/';
135 strcpy (p, iuser);
136 return mbox;
137 }
138
139 /* Reverse Indexing */
140 static char *
141 _url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
142 {
143 const unsigned char* user = (const unsigned char*) iuser;
144 int i, ulen = strlen (iuser);
145 char *mbox, *p;
146
147 if (ulen == 0)
148 return NULL;
149
150 mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
151 strcpy (mbox, spooldir);
152 p = mbox + strlen (mbox);
153 for (i = 0; i < index_depth && i < ulen; i++)
154 {
155 *p++ = '/';
156 *p++ = transtab[ user[ulen - i - 1] ];
157 }
158 for (; i < index_depth; i++)
159 {
160 *p++ = '/';
161 *p++ = transtab[ user[0] ];
162 }
163 *p++ = '/';
164 strcpy (p, iuser);
165 return mbox;
166 }
167
168 /*
169 UNIX Mbox
170 mbox:path[;type=TYPE][;param=PARAM][;user=USERNAME]
171 */
172 int
173 _url_mbox_init (mu_url_t url)
174 {
175 const char *name = mu_url_to_string (url);
176 size_t len = strlen (name);
177 char *p;
178
179 /* reject the obvious */
180 if (name == NULL || strncmp (MU_MBOX_SCHEME, name, MU_MBOX_SCHEME_LEN) != 0
181 || len < (MU_MBOX_SCHEME_LEN + 1) /* (scheme)+1+(path)*/)
182 return EINVAL;
183
184 /* do I need to decode url encoding '% hex hex' ? */
185
186 /* TYPE */
187 url->_destroy = url_mbox_destroy;
188
189 /* SCHEME */
190 url->scheme = strdup (MU_MBOX_SCHEME);
191 if (url->scheme == NULL)
192 {
193 url_mbox_destroy (url);
194 return ENOMEM;
195 }
196
197 /* PATH */
198 name += MU_MBOX_SCHEME_LEN; /* pass the scheme */
199 url->path = strdup (name);
200 if (url->path == NULL)
201 {
202 url_mbox_destroy (url);
203 return ENOMEM;
204 }
205 p = strchr (url->path, ';');
206 if (p)
207 {
208 char *(*fun)() = _url_path_default;
209 char *user = NULL;
210 int param = 0;
211
212 *p++ = 0;
213 while (p)
214 {
215 char *q = strchr (p, ';');
216 if (q)
217 *q++ = 0;
218 if (strncasecmp (p, "type=", 5) == 0)
219 {
220 char *type = p + 5;
221
222 if (strcmp (type, "hash") == 0)
223 fun = _url_path_hashed;
224 else if (strcmp (type, "index") == 0)
225 fun = _url_path_index;
226 else if (strcmp (type, "rev-index") == 0)
227 fun = _url_path_rev_index;
228 else
229 {
230 url_mbox_destroy (url);
231 return MU_ERR_NOENT;
232 }
233 }
234 else if (strncasecmp (p, "user=", 5) == 0)
235 {
236 user = p + 5;
237 }
238 else if (strncasecmp (p, "param=", 6) == 0)
239 {
240 param = strtoul (p+6, NULL, 0);
241 }
242 p = q;
243 }
244
245 if (user)
246 {
247 p = fun (url->path, user, param);
248 free (url->path);
249 url->path = p;
250 }
251 else
252 {
253 url_mbox_destroy (url);
254 return MU_ERR_NOENT;
255 }
256 }
257
258 return 0;
259 }
260
261 static void
262 url_path_destroy (mu_url_t url MU_ARG_UNUSED)
263 {
264 }
265
266 int
267 _url_path_init (mu_url_t url)
268 {
269 const char *name = mu_url_to_string (url);
270 const char *path;
271
272 /* reject the obvious */
273 if (name == NULL || *name == '\0')
274 return EINVAL;
275
276 mu_scheme_autodetect_p (name, &path);
277 name = strdup (path);
278 free (url->name);
279 url->name = (char*) name;
280
281 /* TYPE */
282 url->_destroy = url_path_destroy;
283
284 /* SCHEME */
285 url->scheme = strdup (MU_PATH_SCHEME);
286 if (url->scheme == NULL)
287 {
288 url_path_destroy (url);
289 return ENOMEM;
290 }
291
292 /* PATH */
293 url->path = strdup (name);
294 if (url->path == NULL)
295 {
296 url_path_destroy (url);
297 return ENOMEM;
298 }
299
300 return 0;
301 }
...@@ -88,22 +88,22 @@ mh_dir_p (const char *name) ...@@ -88,22 +88,22 @@ mh_dir_p (const char *name)
88 } 88 }
89 89
90 static int 90 static int
91 _mh_is_scheme (mu_record_t record, const char *url, int flags) 91 _mh_is_scheme (mu_record_t record, mu_url_t url, int flags)
92 { 92 {
93 const char *path;
94 int rc = 0; 93 int rc = 0;
95 94
96 if (!url || !record->scheme) 95 if (mu_url_is_scheme (url, record->scheme))
97 return 0;
98
99 if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
100 return MU_FOLDER_ATTRIBUTE_ALL & flags; 96 return MU_FOLDER_ATTRIBUTE_ALL & flags;
101 97
102 if (mu_scheme_autodetect_p (url, &path)) 98 if (mu_scheme_autodetect_p (url))
103 { 99 {
104 /* Attemp auto-detection */ 100 /* Attemp auto-detection */
101 const char *path;
105 struct stat st; 102 struct stat st;
106 103
104 if (mu_url_sget_path (url, &path))
105 return 0;
106
107 if (stat (path, &st) < 0) 107 if (stat (path, &st) < 0)
108 return 0; /* mu_mailbox_open will complain*/ 108 return 0; /* mu_mailbox_open will complain*/
109 109
...@@ -119,21 +119,11 @@ _mh_is_scheme (mu_record_t record, const char *url, int flags) ...@@ -119,21 +119,11 @@ _mh_is_scheme (mu_record_t record, const char *url, int flags)
119 return 0; 119 return 0;
120 } 120 }
121 121
122 /*
123 MH url
124 mh:path
125 */
126 static int
127 _mh_url_init (mu_url_t url)
128 {
129 return amd_url_init (url, MU_MH_SCHEME);
130 }
131
132 static struct _mu_record _mh_record = 122 static struct _mu_record _mh_record =
133 { 123 {
134 MU_MH_PRIO, 124 MU_MH_PRIO,
135 MU_MH_SCHEME, 125 MU_MH_SCHEME,
136 _mh_url_init, /* Url init. */ 126 mu_url_expand_path, /* Url init. */
137 _mailbox_mh_init, /* Mailbox init. */ 127 _mailbox_mh_init, /* Mailbox init. */
138 NULL, /* Mailer init. */ 128 NULL, /* Mailer init. */
139 _mh_folder_init, /* Folder init. */ 129 _mh_folder_init, /* Folder init. */
......
...@@ -63,7 +63,7 @@ static int nntp_folder_open (mu_folder_t, int); ...@@ -63,7 +63,7 @@ static int nntp_folder_open (mu_folder_t, int);
63 static int nntp_folder_close (mu_folder_t); 63 static int nntp_folder_close (mu_folder_t);
64 static void nntp_folder_destroy (mu_folder_t folder); 64 static void nntp_folder_destroy (mu_folder_t folder);
65 static int nntp_folder_list (mu_folder_t folder, const char *ref, 65 static int nntp_folder_list (mu_folder_t folder, const char *ref,
66 void *name, 66 void *name, int flags,
67 size_t max, 67 size_t max,
68 mu_list_t flist, 68 mu_list_t flist,
69 mu_folder_enumerate_fp efp, void *edp); 69 mu_folder_enumerate_fp efp, void *edp);
...@@ -186,7 +186,7 @@ nntp_folder_destroy (mu_folder_t folder) ...@@ -186,7 +186,7 @@ nntp_folder_destroy (mu_folder_t folder)
186 186
187 187
188 static int 188 static int
189 nntp_folder_list (mu_folder_t folder, const char *ref, void *pat, 189 nntp_folder_list (mu_folder_t folder, const char *ref, void *pat, int flags,
190 size_t max_level, mu_list_t flist, 190 size_t max_level, mu_list_t flist,
191 mu_folder_enumerate_fp efp, void *edp) 191 mu_folder_enumerate_fp efp, void *edp)
192 { 192 {
......
...@@ -84,6 +84,7 @@ strchrnul.m4 ...@@ -84,6 +84,7 @@ strchrnul.m4
84 strdup.m4 84 strdup.m4
85 strerror.m4 85 strerror.m4
86 string_h.m4 86 string_h.m4
87 strings_h.m4
87 strndup.m4 88 strndup.m4
88 strnlen.m4 89 strnlen.m4
89 strtok_r.m4 90 strtok_r.m4
......
...@@ -373,6 +373,8 @@ void util_rfc2047_decode (char **value); ...@@ -373,6 +373,8 @@ void util_rfc2047_decode (char **value);
373 373
374 void util_mark_read (mu_message_t msg); 374 void util_mark_read (mu_message_t msg);
375 375
376 const char *util_url_to_string (mu_url_t url);
377
376 int is_address_field (const char *name); 378 int is_address_field (const char *name);
377 379
378 extern int ml_got_interrupt (void); 380 extern int ml_got_interrupt (void);
......
...@@ -55,7 +55,7 @@ mail_mbox_close () ...@@ -55,7 +55,7 @@ mail_mbox_close ()
55 ngettext ("Held %d message in %s\n", 55 ngettext ("Held %d message in %s\n",
56 "Held %d messages in %s\n", 56 "Held %d messages in %s\n",
57 held_count), 57 held_count),
58 held_count, mu_url_to_string (url)); 58 held_count, util_url_to_string (url));
59 mu_mailbox_close (mbox); 59 mu_mailbox_close (mbox);
60 mu_mailbox_destroy (&mbox); 60 mu_mailbox_destroy (&mbox);
61 return 0; 61 return 0;
...@@ -75,7 +75,7 @@ mail_mbox_commit () ...@@ -75,7 +75,7 @@ mail_mbox_commit ()
75 int is_user_mbox; 75 int is_user_mbox;
76 76
77 mu_mailbox_get_url (mbox, &url); 77 mu_mailbox_get_url (mbox, &url);
78 is_user_mbox = strcmp (mu_url_to_string (url), getenv ("MBOX")) == 0; 78 is_user_mbox = strcmp (util_url_to_string (url), getenv ("MBOX")) == 0;
79 79
80 { 80 {
81 mu_mailbox_t mb; 81 mu_mailbox_t mb;
...@@ -151,7 +151,7 @@ mail_mbox_commit () ...@@ -151,7 +151,7 @@ mail_mbox_commit ()
151 ngettext ("Saved %d message in %s\n", 151 ngettext ("Saved %d message in %s\n",
152 "Saved %d messages in %s\n", 152 "Saved %d messages in %s\n",
153 saved_count), 153 saved_count),
154 saved_count, mu_url_to_string (u)); 154 saved_count, util_url_to_string (u));
155 mu_mailbox_close (dest_mbox); 155 mu_mailbox_close (dest_mbox);
156 mu_mailbox_destroy (&dest_mbox); 156 mu_mailbox_destroy (&dest_mbox);
157 } 157 }
......
...@@ -61,7 +61,7 @@ mail_summary (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) ...@@ -61,7 +61,7 @@ mail_summary (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
61 { 61 {
62 mu_url_t url = NULL; 62 mu_url_t url = NULL;
63 mu_mailbox_get_url (mbox, &url); 63 mu_mailbox_get_url (mbox, &url);
64 printf("\"%s\": ", mu_url_to_string (url)); 64 printf("\"%s\": ", util_url_to_string (url));
65 } 65 }
66 printf (ngettext ("%d message", "%d messages", count), count); 66 printf (ngettext ("%d message", "%d messages", count), count);
67 if (mnew > 0) 67 if (mnew > 0)
......
...@@ -1460,3 +1460,18 @@ util_rfc2047_decode (char **value) ...@@ -1460,3 +1460,18 @@ util_rfc2047_decode (char **value)
1460 } 1460 }
1461 } 1461 }
1462 1462
1463 const char *
1464 util_url_to_string (mu_url_t url)
1465 {
1466 const char *scheme;
1467 if (mu_url_sget_scheme (url, &scheme) == 0)
1468 {
1469 if (strcmp (scheme, "file") == 0 || strcmp (scheme, "mbox") == 0)
1470 {
1471 const char *path;
1472 if (mu_url_sget_path (url, &path) == 0)
1473 return path;
1474 }
1475 }
1476 return mu_url_to_string (url);
1477 }
......
...@@ -1531,50 +1531,4 @@ amd_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, size_t *psiz ...@@ -1531,50 +1531,4 @@ amd_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, size_t *psiz
1531 return 0; 1531 return 0;
1532 } 1532 }
1533 1533
1534 static void
1535 amd_url_destroy (mu_url_t url MU_ARG_UNUSED)
1536 {
1537 }
1538
1539 int
1540 amd_url_init (mu_url_t url, const char *scheme)
1541 {
1542 const char *name = mu_url_to_string (url);
1543 const char *path_ptr = name;
1544 size_t len = strlen (name);
1545 size_t scheme_len = strlen (scheme);
1546
1547 if (!name)
1548 return 0;
1549
1550 if (mu_scheme_autodetect_p (name, &path_ptr))
1551 /* nothing */ ;
1552 /* reject the obvious */
1553 else if (strncmp (scheme, name, scheme_len) != 0
1554 || len < scheme_len + 1)
1555 return EINVAL;
1556 else
1557 path_ptr = name + scheme_len;
1558
1559 /* TYPE */
1560 url->_destroy = amd_url_destroy;
1561
1562 /* SCHEME */
1563 url->scheme = strdup (scheme);
1564 if (url->scheme == NULL)
1565 {
1566 amd_url_destroy (url);
1567 return ENOMEM;
1568 }
1569
1570 /* PATH */
1571 url->path = strdup (path_ptr);
1572 if (url->path == NULL)
1573 {
1574 amd_url_destroy (url);
1575 return ENOMEM;
1576 }
1577
1578 return 0;
1579 }
1580 1534
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
28 /* Keep mailutils namespace clean */ 28 /* Keep mailutils namespace clean */
29 #define argcv_get mu_argcv_get 29 #define argcv_get mu_argcv_get
30 #define argcv_get_n mu_argcv_get_n 30 #define argcv_get_n mu_argcv_get_n
31 #define argcv_get_np mu_argcv_get_np
31 #define argcv_string mu_argcv_string 32 #define argcv_string mu_argcv_string
32 #define argcv_free mu_argcv_free 33 #define argcv_free mu_argcv_free
33 #define argcv_unquote_char mu_argcv_unquote_char 34 #define argcv_unquote_char mu_argcv_unquote_char
...@@ -47,15 +48,45 @@ ...@@ -47,15 +48,45 @@
47 #define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n') 48 #define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
48 #define isdelim(c,delim) (strchr(delim,(c))!=NULL) 49 #define isdelim(c,delim) (strchr(delim,(c))!=NULL)
49 50
51 struct argcv_info
52 {
53 int len;
54 const char *command;
55 const char *delim;
56 const char *comment;
57 int flags;
58
59 int start;
60 int end;
61 int save;
62 int finish_pos;
63 };
64
65 static void
66 init_argcv_info (struct argcv_info *ap, int flags,
67 int len, const char *command, const char *delim,
68 const char *comment)
69 {
70 memset (ap, 0, sizeof *ap);
71 ap->len = len;
72 ap->command = command;
73 ap->delim = delim;
74 ap->comment = comment;
75 ap->flags = flags;
76 }
77
50 static int 78 static int
51 argcv_scan (int len, const char *command, const char *delim, const char* cmnt, 79 argcv_scan (struct argcv_info *ap)
52 int *start, int *end, int *save)
53 { 80 {
54 int i = 0; 81 int i = 0;
82 int len = ap->len;
83 const char *command = ap->command;
84 const char *delim = ap->delim;
85 const char *comment = ap->comment;
55 86
56 for (;;) 87 for (;;)
57 { 88 {
58 i = *save; 89 i = ap->save;
59 90
60 if (i >= len) 91 if (i >= len)
61 return i + 1; 92 return i + 1;
...@@ -63,7 +94,7 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt, ...@@ -63,7 +94,7 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
63 /* Skip initial whitespace */ 94 /* Skip initial whitespace */
64 while (i < len && isws (command[i])) 95 while (i < len && isws (command[i]))
65 i++; 96 i++;
66 *start = i; 97 ap->start = i;
67 98
68 if (!isdelim (command[i], delim)) 99 if (!isdelim (command[i], delim))
69 { 100 {
...@@ -80,11 +111,11 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt, ...@@ -80,11 +111,11 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
80 if (command[i] == '\'' || command[i] == '"') 111 if (command[i] == '\'' || command[i] == '"')
81 { 112 {
82 int j; 113 int j;
83 for (j = i+1; j < len && command[j] != command[i]; j++) 114 for (j = i + 1; j < len && command[j] != command[i]; j++)
84 if (command[j] == '\\') 115 if (command[j] == '\\')
85 j++; 116 j++;
86 if (j < len) 117 if (j < len)
87 i = j+1; 118 i = j + 1;
88 else 119 else
89 i++; 120 i++;
90 } 121 }
...@@ -95,27 +126,36 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt, ...@@ -95,27 +126,36 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
95 } 126 }
96 i--; 127 i--;
97 } 128 }
129 else if (!(ap->flags & MU_ARGCV_RETURN_DELIMS))
130 {
131 while (i < len && isdelim (command[i], delim))
132 i++;
133 ap->save = i;
134 continue;
135 }
98 136
99 *end = i; 137
100 *save = i + 1; 138 ap->end = i;
139 ap->save = ap->finish_pos = i + 1;
101 140
102 /* If we have a token, and it starts with a comment character, skip 141 /* If we have a token, and it starts with a comment character, skip
103 to the newline and restart the token search. */ 142 to the newline and restart the token search. */
104 if (*save <= len) 143 if (ap->save <= len)
105 { 144 {
106 if (strchr (cmnt, command[*start]) != NULL) 145 if (strchr (comment, command[ap->start]) != NULL)
107 { 146 {
108 i = *save; 147 ap->finish_pos = ap->start;
148 i = ap->save;
109 while (i < len && command[i] != '\n') 149 while (i < len && command[i] != '\n')
110 i++; 150 i++;
111 151
112 *save = i; 152 ap->save = i;
113 continue; 153 continue;
114 } 154 }
115 } 155 }
116 break; 156 break;
117 } 157 }
118 return *save; 158 return ap->save;
119 } 159 }
120 160
121 static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t"; 161 static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
...@@ -312,67 +352,85 @@ argcv_quote_copy (char *dst, const char *src) ...@@ -312,67 +352,85 @@ argcv_quote_copy (char *dst, const char *src)
312 } 352 }
313 353
314 int 354 int
315 argcv_get_n (const char *command, int len, const char *delim, const char *cmnt, 355 argcv_get_np (const char *command, int len,
316 int *argc, char ***argv) 356 const char *delim, const char *cmnt,
357 int flags,
358 int *pargc, char ***pargv, char **endp)
317 { 359 {
318 int i = 0; 360 int i = 0;
319 int start, end, save; 361 struct argcv_info info;
320 362 int argc;
321 *argv = NULL; 363 char **argv;
322
323 /* Count number of arguments */
324 *argc = 0;
325 save = 0;
326 364
327 if (!delim) 365 if (!delim)
328 delim = ""; 366 delim = "";
329 if (!cmnt) 367 if (!cmnt)
330 cmnt = ""; 368 cmnt = "";
331 369
332 while (argcv_scan (len, command, delim, cmnt, &start, &end, &save) <= len) 370 init_argcv_info (&info, flags, len, command, delim, cmnt);
333 (*argc)++; 371
372 /* Count number of arguments */
373 argc = 0;
374 while (argcv_scan (&info) <= len)
375 argc++;
334 376
335 *argv = calloc ((*argc + 1), sizeof (char *)); 377 argv = calloc ((argc + 1), sizeof (char *));
336 if (*argv == NULL) 378 if (argv == NULL)
337 return ENOMEM; 379 return ENOMEM;
338 380
339 i = 0; 381 i = 0;
340 save = 0; 382 info.save = 0;
341 for (i = 0; i < *argc; i++) 383 for (i = 0; i < argc; i++)
342 { 384 {
343 int n; 385 int n;
344 int unquote; 386 int unquote;
345 387
346 argcv_scan (len, command, delim, cmnt, &start, &end, &save); 388 argcv_scan (&info);
347 389
348 if ((command[start] == '"' || command[end] == '\'') 390 if ((command[info.start] == '"' || command[info.end] == '\'')
349 && command[end] == command[start]) 391 && command[info.end] == command[info.start])
350 { 392 {
351 if (start < end) 393 if (info.start < info.end)
352 { 394 {
353 start++; 395 info.start++;
354 end--; 396 info.end--;
355 } 397 }
356 unquote = 0; 398 unquote = 0;
357 } 399 }
358 else 400 else
359 unquote = 1; 401 unquote = 1;
360 402
361 n = end - start + 1; 403 n = info.end - info.start + 1;
362 (*argv)[i] = calloc (n+1, sizeof (char)); 404 argv[i] = calloc (n + 1, sizeof (char));
363 if ((*argv)[i] == NULL) 405 if (argv[i] == NULL)
406 {
407 argcv_free (i, argv);
364 return ENOMEM; 408 return ENOMEM;
409 }
365 if (unquote) 410 if (unquote)
366 argcv_unquote_copy ((*argv)[i], &command[start], n); 411 argcv_unquote_copy (argv[i], &command[info.start], n);
367 else 412 else
368 memcpy ((*argv)[i], &command[start], n); 413 memcpy (argv[i], &command[info.start], n);
369 (*argv)[i][n] = 0; 414 argv[i][n] = 0;
370 } 415 }
371 (*argv)[i] = NULL; 416 argv[i] = NULL;
417
418 *pargc = argc;
419 *pargv = argv;
420 if (endp)
421 *endp = (char*) (command + info.finish_pos);
372 return 0; 422 return 0;
373 } 423 }
374 424
375 int 425 int
426 argcv_get_n (const char *command, int len, const char *delim, const char *cmnt,
427 int *pargc, char ***pargv)
428 {
429 return argcv_get_np (command, len, delim, cmnt, MU_ARGCV_RETURN_DELIMS,
430 pargc, pargv, NULL);
431 }
432
433 int
376 argcv_get (const char *command, const char *delim, const char *cmnt, 434 argcv_get (const char *command, const char *delim, const char *cmnt,
377 int *argc, char ***argv) 435 int *argc, char ***argv)
378 { 436 {
...@@ -445,3 +503,35 @@ argcv_string (int argc, char **argv, char **pstring) ...@@ -445,3 +503,35 @@ argcv_string (int argc, char **argv, char **pstring)
445 return 0; 503 return 0;
446 } 504 }
447 505
506 void
507 mu_argcv_remove (int *pargc, char ***pargv,
508 int (*sel) (const char *, void *), void *data)
509 {
510 int i, j;
511 int argc = *pargc;
512 char **argv = *pargv;
513 int cnt = 0;
514
515 for (i = j = 0; i < argc; i++)
516 {
517 if (sel (argv[i], data))
518 {
519 free (argv[i]);
520 cnt++;
521 }
522 else
523 {
524 if (i != j)
525 argv[j] = argv[i];
526 j++;
527 }
528 }
529 if (i != j)
530 argv[j] = NULL;
531 argc -= cnt;
532
533 *pargc = argc;
534 *pargv = argv;
535 }
536
537
......
...@@ -677,7 +677,7 @@ struct _prog_stream ...@@ -677,7 +677,7 @@ struct _prog_stream
677 pid_t pid; 677 pid_t pid;
678 int status; 678 int status;
679 pid_t writer_pid; 679 pid_t writer_pid;
680 size_t argc; 680 int argc;
681 char **argv; 681 char **argv;
682 mu_stream_t in, out; 682 mu_stream_t in, out;
683 683
......
...@@ -73,21 +73,36 @@ mu_folder_create_from_record (mu_folder_t *pfolder, const char *name, ...@@ -73,21 +73,36 @@ mu_folder_create_from_record (mu_folder_t *pfolder, const char *name,
73 == 0) 73 == 0)
74 { 74 {
75 int (*f_init) (mu_folder_t) = NULL; 75 int (*f_init) (mu_folder_t) = NULL;
76 int (*u_init) (mu_url_t) = NULL;
77 76
78 mu_record_get_folder (record, &f_init); 77 mu_record_get_folder (record, &f_init);
79 mu_record_get_url (record, &u_init); 78 if (f_init)
80 if (f_init && u_init)
81 { 79 {
82 int status; 80 int status;
83 mu_url_t url; 81 mu_url_t url;
84 mu_folder_t folder; 82 mu_folder_t folder;
83 int (*u_init) (mu_url_t) = NULL;
85 84
86 /* Parse the url, it may be a bad one and we should bailout if this 85 /* Parse the url, it may be a bad one and we should bailout if this
87 failed. */ 86 failed. */
88 if ((status = mu_url_create (&url, name) != 0) 87 if ((status = mu_url_create (&url, name)) != 0)
89 || (status = u_init (url)) != 0) 88 return status;
89
90 status = mu_url_parse (url);
91 if (status)
92 {
93 mu_url_destroy (url);
90 return status; 94 return status;
95 }
96 mu_record_get_url (record, &u_init);
97 if (u_init)
98 {
99 status = u_init (url);
100 if (status)
101 {
102 mu_url_destroy (url);
103 return status;
104 }
105 }
91 106
92 mu_monitor_wrlock (&folder_lock); 107 mu_monitor_wrlock (&folder_lock);
93 108
......
...@@ -165,7 +165,7 @@ int ...@@ -165,7 +165,7 @@ int
165 mu_global_debug_from_string (const char *string, const char *errpfx) 165 mu_global_debug_from_string (const char *string, const char *errpfx)
166 { 166 {
167 int rc; 167 int rc;
168 size_t argc; 168 int argc;
169 char **argv; 169 char **argv;
170 int i; 170 int i;
171 171
......
...@@ -42,20 +42,28 @@ ...@@ -42,20 +42,28 @@
42 #include <mailutils/mutil.h> 42 #include <mailutils/mutil.h>
43 43
44 #include <mailbox0.h> 44 #include <mailbox0.h>
45 #include <url0.h>
45 46
46 static int 47 static int
47 mailbox_folder_create (mu_folder_t *pfolder, const char *name) 48 mailbox_folder_create (mu_mailbox_t mbox, const char *name,
49 mu_record_t record)
48 { 50 {
49 int rc; 51 int rc;
50 char *p, *fname = strdup (name); 52 char *fname;
51 53
52 if (!fname) 54 if ((rc = mu_url_aget_path (mbox->url, &fname)))
53 return ENOMEM; 55 return rc;
54 56
55 p = strrchr (fname, '/'); /* FIXME: Is this always appropriate? */ 57 if (mu_url_is_scheme (mbox->url, "file")
56 if (p && !(mu_is_proto (fname) && strncmp (fname, "file:", 5))) 58 || mu_url_is_scheme (mbox->url, "mbox")
59 || mu_url_is_scheme (mbox->url, "mh")
60 || mu_url_is_scheme (mbox->url, "maildir"))
61 {
62 char *p = strrchr (fname, '/'); /* FIXME: Is this always appropriate? */
63 if (p)
57 *p = 0; 64 *p = 0;
58 rc = mu_folder_create (pfolder, fname); 65 }
66 rc = mu_folder_create_from_record (&mbox->folder, fname, record);
59 free (fname); 67 free (fname);
60 return rc; 68 return rc;
61 } 69 }
...@@ -85,22 +93,21 @@ mu_mailbox_get_default_proto () ...@@ -85,22 +93,21 @@ mu_mailbox_get_default_proto ()
85 } 93 }
86 94
87 static int 95 static int
88 _create_mailbox (mu_mailbox_t *pmbox, const char *name) 96 _create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
89 { 97 {
98 int status;
90 mu_record_t record = NULL; 99 mu_record_t record = NULL;
91 100
92 if (mu_registrar_lookup (name, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) == 0) 101 if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
102 == 0)
93 { 103 {
94 mu_log_level_t level; 104 mu_log_level_t level;
95 int (*m_init) (mu_mailbox_t) = NULL; 105 int (*m_init) (mu_mailbox_t) = NULL;
96 int (*u_init) (mu_url_t) = NULL;
97 106
98 mu_record_get_mailbox (record, &m_init); 107 mu_record_get_mailbox (record, &m_init);
99 mu_record_get_url (record, &u_init); 108 if (m_init)
100 if (m_init && u_init)
101 { 109 {
102 int status; 110 int (*u_init) (mu_url_t) = NULL;
103 mu_url_t url;
104 mu_mailbox_t mbox; 111 mu_mailbox_t mbox;
105 112
106 /* Allocate memory for mbox. */ 113 /* Allocate memory for mbox. */
...@@ -117,19 +124,31 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name) ...@@ -117,19 +124,31 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
117 return status; 124 return status;
118 } 125 }
119 126
120 /* Parse the url, it may be a bad one and we should bailout if this 127 mu_record_get_url (record, &u_init);
121 failed. */ 128 if (u_init && (status = u_init (url)) != 0)
122 if ((status = mu_url_create (&url, name)) != 0
123 || (status = u_init (url)) != 0)
124 { 129 {
125 mu_mailbox_destroy (&mbox); 130 mu_mailbox_destroy (&mbox);
126 return status; 131 return status;
127 } 132 }
133
134 /* Make sure scheme contains actual mailbox scheme */
135 if (strcmp (url->scheme, record->scheme))
136 {
137 char *p = strdup (record->scheme);
138 if (!p)
139 {
140 mu_mailbox_destroy (&mbox);
141 return errno;
142 }
143 free (url->scheme);
144 url->scheme = p;
145 }
146
128 mbox->url = url; 147 mbox->url = url;
129 148
130 /* Create the folder before initializing the concrete mailbox. 149 /* Create the folder before initializing the concrete mailbox.
131 The mailbox needs it's back pointer. */ 150 The mailbox needs it's back pointer. */
132 status = mailbox_folder_create (&mbox->folder, name); 151 status = mailbox_folder_create (mbox, name, record);
133 152
134 if (status == 0) 153 if (status == 0)
135 status = m_init (mbox); /* Create the concrete mailbox type. */ 154 status = m_init (mbox); /* Create the concrete mailbox type. */
...@@ -160,6 +179,21 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name) ...@@ -160,6 +179,21 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
160 return MU_ERR_NO_HANDLER; 179 return MU_ERR_NO_HANDLER;
161 } 180 }
162 181
182 static int
183 _create_mailbox (mu_mailbox_t *pmbox, const char *name)
184 {
185 int status;
186 mu_url_t url;
187
188 status = mu_url_create (&url, name);
189 if (status)
190 return status;
191 status = mu_url_parse (url);
192 if (status == 0)
193 status = _create_mailbox0 (pmbox, url, name);
194 return status;
195 }
196
163 /* The Mailbox Factory. 197 /* The Mailbox Factory.
164 Create an iterator for registrar and see if any url scheme match, 198 Create an iterator for registrar and see if any url scheme match,
165 Then we call the mailbox's mu_url_create() to parse the URL. Last 199 Then we call the mailbox's mu_url_create() to parse the URL. Last
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
59 #include <mailutils/stream.h> 59 #include <mailutils/stream.h>
60 #include <mailutils/filter.h> 60 #include <mailutils/filter.h>
61 #include <mailutils/sql.h> 61 #include <mailutils/sql.h>
62 #include <mailutils/url.h>
62 63
63 #include <registrar0.h> 64 #include <registrar0.h>
64 65
...@@ -1243,21 +1244,15 @@ mu_true_answer_p (const char *p) ...@@ -1243,21 +1244,15 @@ mu_true_answer_p (const char *p)
1243 return -1; 1244 return -1;
1244 } 1245 }
1245 1246
1246 /* Returns true if SCHEME represents a local mail folder. Stores 1247 /* Returns true if SCHEME represents a local (autodetect) mail folder. */
1247 real folder path to PATH */
1248 int 1248 int
1249 mu_scheme_autodetect_p (const char *scheme, const char **path) 1249 mu_scheme_autodetect_p (mu_url_t url)
1250 { 1250 {
1251 *path = scheme; 1251 if (mu_url_is_scheme (url, "file"))
1252 if (strncmp (MU_FILE_SCHEME, scheme, MU_FILE_SCHEME_LEN) == 0)
1253 { 1252 {
1254 *path += MU_FILE_SCHEME_LEN; 1253 mu_url_expand_path (url);
1255 return 1; 1254 return 1;
1256 } 1255 }
1257 if (access (scheme, F_OK) == 0
1258 /* FIXME: this can return true even if the folder is unreadable */
1259 || strncmp (MU_PATH_SCHEME, scheme, MU_PATH_SCHEME_LEN) == 0)
1260 return 1;
1261 return 0; 1256 return 0;
1262 } 1257 }
1263 1258
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
34 #include <mailutils/errno.h> 34 #include <mailutils/errno.h>
35 #include <mailutils/nls.h> 35 #include <mailutils/nls.h>
36 #include <mailutils/error.h> 36 #include <mailutils/error.h>
37 #include <mailutils/url.h>
37 38
38 #include <registrar0.h> 39 #include <registrar0.h>
39 40
...@@ -90,7 +91,7 @@ mu_registrar_get_iterator (mu_iterator_t *pitr) ...@@ -90,7 +91,7 @@ mu_registrar_get_iterator (mu_iterator_t *pitr)
90 } 91 }
91 92
92 int 93 int
93 mu_registrar_lookup (const char *name, int flags, 94 mu_registrar_lookup_url (mu_url_t url, int flags,
94 mu_record_t *precord, int *pflags) 95 mu_record_t *precord, int *pflags)
95 { 96 {
96 mu_iterator_t iterator; 97 mu_iterator_t iterator;
...@@ -104,7 +105,7 @@ mu_registrar_lookup (const char *name, int flags, ...@@ -104,7 +105,7 @@ mu_registrar_lookup (const char *name, int flags,
104 int rc; 105 int rc;
105 mu_record_t record; 106 mu_record_t record;
106 mu_iterator_current (iterator, (void **)&record); 107 mu_iterator_current (iterator, (void **)&record);
107 if ((rc = mu_record_is_scheme (record, name, flags))) 108 if ((rc = mu_record_is_scheme (record, url, flags)))
108 { 109 {
109 status = 0; 110 status = 0;
110 if (precord) 111 if (precord)
...@@ -118,6 +119,23 @@ mu_registrar_lookup (const char *name, int flags, ...@@ -118,6 +119,23 @@ mu_registrar_lookup (const char *name, int flags,
118 return status; 119 return status;
119 } 120 }
120 121
122 int
123 mu_registrar_lookup (const char *name, int flags,
124 mu_record_t *precord, int *pflags)
125 {
126 int rc;
127 mu_url_t url;
128
129 rc = mu_url_create (&url, name);
130 if (rc)
131 return rc;
132 rc = mu_url_parse (url);
133 if (rc == 0)
134 rc = mu_registrar_lookup_url (url, flags, precord, pflags);
135 mu_url_destroy (&url);
136 return rc;
137 }
138
121 static int 139 static int
122 _compare_prio (const void *item, const void *value) 140 _compare_prio (const void *item, const void *value)
123 { 141 {
...@@ -156,18 +174,16 @@ mu_unregistrar_record (mu_record_t record) ...@@ -156,18 +174,16 @@ mu_unregistrar_record (mu_record_t record)
156 } 174 }
157 175
158 int 176 int
159 mu_record_is_scheme (mu_record_t record, const char *scheme, int flags) 177 mu_record_is_scheme (mu_record_t record, mu_url_t url, int flags)
160 { 178 {
161 if (record == NULL) 179 if (record == NULL)
162 return 0; 180 return 0;
163 181
164 /* Overload. */ 182 /* Overload. */
165 if (record->_is_scheme) 183 if (record->_is_scheme)
166 return record->_is_scheme (record, scheme, flags); 184 return record->_is_scheme (record, url, flags);
167 185
168 if (scheme 186 if (mu_url_is_scheme (url, record->scheme))
169 && record->scheme
170 && strncasecmp (record->scheme, scheme, strlen (record->scheme)) == 0)
171 return MU_FOLDER_ATTRIBUTE_ALL; 187 return MU_FOLDER_ATTRIBUTE_ALL;
172 188
173 return 0; 189 return 0;
...@@ -183,8 +199,8 @@ mu_record_set_scheme (mu_record_t record, const char *scheme) ...@@ -183,8 +199,8 @@ mu_record_set_scheme (mu_record_t record, const char *scheme)
183 } 199 }
184 200
185 int 201 int
186 mu_record_set_is_scheme (mu_record_t record, int (*_is_scheme) 202 mu_record_set_is_scheme (mu_record_t record,
187 (mu_record_t, const char *, int)) 203 int (*_is_scheme) (mu_record_t, mu_url_t, int))
188 { 204 {
189 if (record == NULL) 205 if (record == NULL)
190 return EINVAL; 206 return EINVAL;
......
...@@ -627,4 +627,41 @@ ftp://ftp.example.org:111/mbox/user%40host => SUCCESS ...@@ -627,4 +627,41 @@ ftp://ftp.example.org:111/mbox/user%40host => SUCCESS
627 path <mbox/user@host> 627 path <mbox/user@host>
628 query <> 628 query <>
629 629
630 ftp://ftp.example.org:111/mbox/user%40host;type=pass => SUCCESS
631 scheme <ftp>
632 user <>
633 passwd <>
634 auth <>
635 host <ftp.example.org>
636 port 111
637 path <mbox/user@host>
638 param[0] <type=pass>
639 query <>
640
641 mbox:/var/spool/mail;type=index;param=2;user=gray => SUCCESS
642 scheme <mbox>
643 user <>
644 passwd <>
645 auth <>
646 host <>
647 port 0
648 path </var/spool/mail>
649 param[0] <type=index>
650 param[1] <param=2>
651 param[2] <user=gray>
652 query <>
653
654 mbox:///var/spool/mail;type=index;param=2;user=gray => SUCCESS
655 scheme <mbox>
656 user <>
657 passwd <>
658 auth <>
659 host <>
660 port 0
661 path </var/spool/mail>
662 param[0] <type=index>
663 param[1] <param=2>
664 param[2] <user=gray>
665 query <>
666
630 # NOTE: This file must end with an empty line 667 # NOTE: This file must end with an empty line
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 30
31 #include <mailutils/mutil.h> 31 #include <mailutils/mutil.h>
32 #include <mailutils/errno.h> 32 #include <mailutils/errno.h>
33 #include <mailutils/argcv.h>
33 #include <url0.h> 34 #include <url0.h>
34 35
35 /* 36 /*
...@@ -86,6 +87,9 @@ mu_url_destroy (mu_url_t * purl) ...@@ -86,6 +87,9 @@ mu_url_destroy (mu_url_t * purl)
86 if (url->path) 87 if (url->path)
87 free (url->path); 88 free (url->path);
88 89
90 if (url->fvcount)
91 mu_argcv_free (url->fvcount, url->fvpairs);
92
89 if (url->query) 93 if (url->query)
90 free (url->query); 94 free (url->query);
91 95
...@@ -100,11 +104,12 @@ mu_url_parse (mu_url_t url) ...@@ -100,11 +104,12 @@ mu_url_parse (mu_url_t url)
100 { 104 {
101 int err = 0; 105 int err = 0;
102 char *n = NULL; 106 char *n = NULL;
103 struct _mu_url u = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 107 struct _mu_url u;
104 108
105 if (!url || !url->name) 109 if (!url || !url->name)
106 return EINVAL; 110 return EINVAL;
107 111
112 memset (&u, 0, sizeof u);
108 /* can't have been parsed already */ 113 /* can't have been parsed already */
109 if (url->scheme || url->user || url->passwd || url->auth || 114 if (url->scheme || url->user || url->passwd || url->auth ||
110 url->host || url->path || url->query) 115 url->host || url->path || url->query)
...@@ -126,10 +131,13 @@ mu_url_parse (mu_url_t url) ...@@ -126,10 +131,13 @@ mu_url_parse (mu_url_t url)
126 */ 131 */
127 132
128 #define UALLOC(X) \ 133 #define UALLOC(X) \
129 if(u.X && u.X[0] && (url->X = mu_url_decode(u.X)) == 0) { \ 134 if (u.X && u.X[0] && (url->X = mu_url_decode(u.X)) == 0) \
135 { \
130 err = ENOMEM; \ 136 err = ENOMEM; \
131 goto CLEANUP; \ 137 goto CLEANUP; \
132 } else { \ 138 } \
139 else \
140 { \
133 /* Set zero-length strings to NULL. */ \ 141 /* Set zero-length strings to NULL. */ \
134 u.X = NULL; \ 142 u.X = NULL; \
135 } 143 }
...@@ -142,6 +150,8 @@ mu_url_parse (mu_url_t url) ...@@ -142,6 +150,8 @@ mu_url_parse (mu_url_t url)
142 UALLOC (path); 150 UALLOC (path);
143 UALLOC (query); 151 UALLOC (query);
144 #undef UALLOC 152 #undef UALLOC
153 url->fvcount = u.fvcount;
154 url->fvpairs = u.fvpairs;
145 url->port = u.port; 155 url->port = u.port;
146 } 156 }
147 157
...@@ -150,7 +160,7 @@ CLEANUP: ...@@ -150,7 +160,7 @@ CLEANUP:
150 160
151 if (err) 161 if (err)
152 { 162 {
153 #define UFREE(X) if(X) { free(X); X = 0; } 163 #define UFREE(X) if (X) { free(X); X = 0; }
154 164
155 UFREE (url->scheme); 165 UFREE (url->scheme);
156 UFREE (url->user); 166 UFREE (url->user);
...@@ -199,6 +209,12 @@ url_parse0 (mu_url_t u, char *name) ...@@ -199,6 +209,12 @@ url_parse0 (mu_url_t u, char *name)
199 if (name == NULL) 209 if (name == NULL)
200 return EINVAL; 210 return EINVAL;
201 211
212 if (name[0] == '/')
213 {
214 u->scheme = "file";
215 }
216 else
217 {
202 /* Parse out the SCHEME. */ 218 /* Parse out the SCHEME. */
203 p = strchr (name, ':'); 219 p = strchr (name, ':');
204 if (p == NULL) 220 if (p == NULL)
...@@ -213,25 +229,23 @@ url_parse0 (mu_url_t u, char *name) ...@@ -213,25 +229,23 @@ url_parse0 (mu_url_t u, char *name)
213 *name = tolower (*name); 229 *name = tolower (*name);
214 230
215 name = p; 231 name = p;
232 }
216 233
217 /* Check for nothing following the scheme. */ 234 /* Check for nothing following the scheme. */
218 if (!*name) 235 if (!*name)
219 return 0; 236 return 0;
220 237
221 if (strncmp (name, "//", 2) != 0) 238 if (strncmp (name, "//", 2) == 0)
222 { 239 {
223 u->path = name;
224 return 0;
225 }
226
227 name += 2; 240 name += 2;
228 241
229 if (name[0] == '/') 242 if (name[0] == '/')
230 { 243 {
231 u->path = name; 244 u->path = name;
232 return 0; 245 p = u->path + strcspn (u->path, ";?");
233 } 246 }
234 247 else
248 {
235 /* Split into LHS and RHS of the '@', and then parse each side. */ 249 /* Split into LHS and RHS of the '@', and then parse each side. */
236 u->host = strchr (name, '@'); 250 u->host = strchr (name, '@');
237 if (u->host == NULL) 251 if (u->host == NULL)
...@@ -257,11 +271,8 @@ url_parse0 (mu_url_t u, char *name) ...@@ -257,11 +271,8 @@ url_parse0 (mu_url_t u, char *name)
257 if (strncasecmp (name + 1, "auth=", 5) == 0) 271 if (strncasecmp (name + 1, "auth=", 5) == 0)
258 { 272 {
259 *name++ = 0; 273 *name++ = 0;
260
261 name += 5; 274 name += 5;
262
263 u->auth = name; 275 u->auth = name;
264
265 break; 276 break;
266 } 277 }
267 } 278 }
...@@ -276,11 +287,9 @@ url_parse0 (mu_url_t u, char *name) ...@@ -276,11 +287,9 @@ url_parse0 (mu_url_t u, char *name)
276 287
277 /* Parse the host and port from the RHS. */ 288 /* Parse the host and port from the RHS. */
278 p = strchr (u->host, ':'); 289 p = strchr (u->host, ':');
279
280 if (p) 290 if (p)
281 { 291 {
282 *p++ = 0; 292 *p++ = 0;
283
284 u->port = strtol (p, &p, 10); 293 u->port = strtol (p, &p, 10);
285 294
286 /* Check for garbage after the port: we should be on the start 295 /* Check for garbage after the port: we should be on the start
...@@ -289,20 +298,36 @@ url_parse0 (mu_url_t u, char *name) ...@@ -289,20 +298,36 @@ url_parse0 (mu_url_t u, char *name)
289 return MU_ERR_PARSE; 298 return MU_ERR_PARSE;
290 } 299 }
291 else 300 else
292 p = u->host + strcspn (u->host, "/?"); 301 p = u->host + strcspn (u->host, ";/?");
302 }
303 }
304 else
305 {
306 u->path = name;
307 p = u->path + strcspn (u->path, ";?");
308 }
293 309
294 /* Either way, if we're not at a nul, we're at a path or query. */ 310 /* Either way, if we're not at a nul, we're at a path or query. */
295 if (*p == '?') 311 if (u->path == NULL && *p == '/')
296 { 312 {
297 /* found a query */ 313 /* found a path */
298 *p++ = 0; 314 *p++ = 0;
299 u->query = p; 315 u->path = p;
316 p = u->path + strcspn (u->path, ";?");
300 } 317 }
301 if (*p == '/') 318
319 if (*p == ';')
302 { 320 {
303 /* found a path */
304 *p++ = 0; 321 *p++ = 0;
305 u->path = p; 322 mu_argcv_get_np (p, strlen (p), ";", "?", 0,
323 &u->fvcount, &u->fvpairs, &p);
324 }
325
326 if (*p == '?')
327 {
328 /* found a query */
329 *p++ = 0;
330 u->query = p;
306 } 331 }
307 332
308 return 0; 333 return 0;
...@@ -431,6 +456,46 @@ DECL_ACCESSORS (host) ...@@ -431,6 +456,46 @@ DECL_ACCESSORS (host)
431 DECL_ACCESSORS (path) 456 DECL_ACCESSORS (path)
432 DECL_ACCESSORS (query) 457 DECL_ACCESSORS (query)
433 458
459 /* field-value pairs accessors */
460 int
461 mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp)
462 {
463 if (url == NULL)
464 return EINVAL;
465 /* FIXME: no _get_fvpairs method, but the method stuff needs to be rewritten
466 anyway */
467 *fvc = url->fvcount;
468 *fvp = url->fvpairs;
469 return 0;
470 }
471
472 int
473 mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp)
474 {
475 size_t fvc, i;
476 char **fvp;
477 char **fvcopy;
478
479 int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
480 if (rc)
481 return rc;
482
483 fvcopy = calloc (fvc + 1, sizeof (fvcopy[0]));
484 if (!fvcopy)
485 return errno;
486 for (i = 0; i < fvc; i++)
487 {
488 if (!(fvcopy[i] = strdup (fvp[i])))
489 {
490 mu_argcv_free (i, fvcopy);
491 return errno;
492 }
493 }
494 fvcopy[i] = NULL;
495 *pfvc = fvc;
496 *pfvp = fvcopy;
497 return 0;
498 }
434 499
435 int 500 int
436 mu_url_get_port (const mu_url_t url, long *pport) 501 mu_url_get_port (const mu_url_t url, long *pport)
...@@ -572,3 +637,189 @@ mu_url_init (mu_url_t url, int port, const char *scheme) ...@@ -572,3 +637,189 @@ mu_url_init (mu_url_t url, int port, const char *scheme)
572 637
573 return status; 638 return status;
574 } 639 }
640
641 /* Default mailbox path generator */
642 static char *
643 _url_path_default (const char *spooldir, const char *user, int unused)
644 {
645 char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2);
646 if (!mbox)
647 errno = ENOMEM;
648 else
649 sprintf (mbox, "%s/%s", spooldir, user);
650 return mbox;
651 }
652
653 /* Hashed indexing */
654 static char *
655 _url_path_hashed (const char *spooldir, const char *user, int param)
656 {
657 int i;
658 int ulen = strlen (user);
659 char *mbox;
660 unsigned hash;
661
662 if (param > ulen)
663 param = ulen;
664 for (i = 0, hash = 0; i < param; i++)
665 hash += user[i];
666
667 mbox = malloc (ulen + strlen (spooldir) + 5);
668 sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
669 return mbox;
670 }
671
672 static int transtab[] = {
673 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
674 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
675 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
676 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
677 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
678 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
679 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
680 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
681 'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
682 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
683 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
684 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
685 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
686 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
687 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
688 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
689 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
690 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
691 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
692 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
693 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
694 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
695 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
696 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
697 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
698 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
699 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
700 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
701 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
702 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
703 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
704 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
705 };
706
707 /* Forward Indexing */
708 static char *
709 _url_path_index (const char *spooldir, const char *iuser, int index_depth)
710 {
711 const unsigned char* user = (const unsigned char*) iuser;
712 int i, ulen = strlen (iuser);
713 char *mbox, *p;
714
715 if (ulen == 0)
716 return NULL;
717
718 mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
719 strcpy (mbox, spooldir);
720 p = mbox + strlen (mbox);
721 for (i = 0; i < index_depth && i < ulen; i++)
722 {
723 *p++ = '/';
724 *p++ = transtab[ user[i] ];
725 }
726 for (; i < index_depth; i++)
727 {
728 *p++ = '/';
729 *p++ = transtab[ user[ulen-1] ];
730 }
731 *p++ = '/';
732 strcpy (p, iuser);
733 return mbox;
734 }
735
736 /* Reverse Indexing */
737 static char *
738 _url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
739 {
740 const unsigned char* user = (const unsigned char*) iuser;
741 int i, ulen = strlen (iuser);
742 char *mbox, *p;
743
744 if (ulen == 0)
745 return NULL;
746
747 mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
748 strcpy (mbox, spooldir);
749 p = mbox + strlen (mbox);
750 for (i = 0; i < index_depth && i < ulen; i++)
751 {
752 *p++ = '/';
753 *p++ = transtab[ user[ulen - i - 1] ];
754 }
755 for (; i < index_depth; i++)
756 {
757 *p++ = '/';
758 *p++ = transtab[ user[0] ];
759 }
760 *p++ = '/';
761 strcpy (p, iuser);
762 return mbox;
763 }
764
765 static int
766 rmselector (const char *p, void *data MU_ARG_UNUSED)
767 {
768 return strncmp (p, "type=", 5) == 0
769 || strncmp (p, "user=", 5) == 0
770 || strncmp (p, "param=", 6) == 0;
771 }
772
773 int
774 mu_url_expand_path (mu_url_t url)
775 {
776 size_t i;
777 char *user = NULL;
778 int param = 0;
779 char *p;
780 char *(*fun) (const char *, const char *, int) = _url_path_default;
781
782 if (url->fvcount == 0)
783 return 0;
784
785 for (i = 0; i < url->fvcount; i++)
786 {
787 p = url->fvpairs[i];
788 if (strncmp (p, "type=", 5) == 0)
789 {
790 char *type = p + 5;
791
792 if (strcmp (type, "hash") == 0)
793 fun = _url_path_hashed;
794 else if (strcmp (type, "index") == 0)
795 fun = _url_path_index;
796 else if (strcmp (type, "rev-index") == 0)
797 fun = _url_path_rev_index;
798 else
799 return MU_ERR_NOENT;
800 }
801 else if (strncmp (p, "user=", 5) == 0)
802 {
803 user = p + 5;
804 }
805 else if (strncmp (p, "param=", 6) == 0)
806 {
807 param = strtoul (p + 6, NULL, 0);
808 }
809 }
810
811 if (user)
812 {
813 char *p = fun (url->path, user, param);
814 if (p)
815 {
816 free (url->path);
817 url->path = p;
818 }
819 mu_argcv_remove (&url->fvcount, &url->fvpairs, rmselector, NULL);
820 }
821 else
822 return MU_ERR_NOENT;
823
824 return 0;
825 }
......
...@@ -24,7 +24,7 @@ static char *bulletin_db_name; ...@@ -24,7 +24,7 @@ static char *bulletin_db_name;
24 void 24 void
25 set_bulletin_db (char *file) 25 set_bulletin_db (char *file)
26 { 26 {
27 bulletin_db_name = file; 27 bulletin_db_name = strdup (file);
28 } 28 }
29 29
30 static void 30 static void
...@@ -67,7 +67,7 @@ open_bulletin_mailbox (mu_mailbox_t *pmbox) ...@@ -67,7 +67,7 @@ open_bulletin_mailbox (mu_mailbox_t *pmbox)
67 int 67 int
68 set_bulletin_source (char *source) 68 set_bulletin_source (char *source)
69 { 69 {
70 bulletin_mbox_name = source; 70 bulletin_mbox_name = strdup (source);
71 return 0; 71 return 0;
72 } 72 }
73 73
...@@ -145,8 +145,14 @@ read_bulletin_db (size_t *pnum) ...@@ -145,8 +145,14 @@ read_bulletin_db (size_t *pnum)
145 145
146 if (rc) 146 if (rc)
147 { 147 {
148 int ec = errno;
149 if (ec == ENOENT)
150 {
151 *pnum = 0;
152 return 0;
153 }
148 mu_error (_("Cannot fetch bulletin db data: %s"), 154 mu_error (_("Cannot fetch bulletin db data: %s"),
149 mu_strerror (errno)); 155 mu_strerror (ec));
150 mu_dbm_close (db); 156 mu_dbm_close (db);
151 return 1; 157 return 1;
152 } 158 }
...@@ -236,18 +242,14 @@ write_bulletin_db (size_t num) ...@@ -236,18 +242,14 @@ write_bulletin_db (size_t num)
236 } 242 }
237 #endif /* USE_DBM */ 243 #endif /* USE_DBM */
238 244
239 size_t 245 int
240 get_last_delivered_num () 246 get_last_delivered_num (size_t *pret)
241 { 247 {
242 size_t num = 0;
243
244 #ifdef USE_DBM 248 #ifdef USE_DBM
245 if (bulletin_db_name && read_bulletin_db (&num) == 0) 249 if (bulletin_db_name && read_bulletin_db (pret) == 0)
246 return num; 250 return 0;
247 #endif 251 #endif
248 252 return read_popbull_file (pret);
249 read_popbull_file (&num);
250 return num;
251 } 253 }
252 254
253 void 255 void
...@@ -271,9 +273,8 @@ deliver_pending_bulletins () ...@@ -271,9 +273,8 @@ deliver_pending_bulletins ()
271 return; 273 return;
272 274
273 rc = open_bulletin_mailbox (&bull); 275 rc = open_bulletin_mailbox (&bull);
274 if (rc) 276 if (rc || get_last_delivered_num (&lastnum))
275 return; 277 return;
276 lastnum = get_last_delivered_num ();
277 278
278 rc = mu_mailbox_messages_count (bull, &total); 279 rc = mu_mailbox_messages_count (bull, &total);
279 if (rc) 280 if (rc)
......
...@@ -50,7 +50,7 @@ pop3d_capa (const char *arg) ...@@ -50,7 +50,7 @@ pop3d_capa (const char *arg)
50 50
51 login_delay_capa (); 51 login_delay_capa ();
52 /* This can be implemented by setting an header field on the message. */ 52 /* This can be implemented by setting an header field on the message. */
53 if (expire < 0) 53 if (expire == EXPIRE_NEVER)
54 pop3d_outf ("EXPIRE NEVER\r\n"); 54 pop3d_outf ("EXPIRE NEVER\r\n");
55 else 55 else
56 pop3d_outf ("EXPIRE %s\r\n", mu_umaxtostr (0, expire)); 56 pop3d_outf ("EXPIRE %s\r\n", mu_umaxtostr (0, expire));
......