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
2007-12-28 Sergey Poznyakoff <gray@gnu.org.ua>
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.
2007-12-21 Sergey Poznyakoff <gray@gnu.org.ua>
* examples/lsf.c: Use mu_folder_enumerate + callback function, for
......
GNU mailutils NEWS -- history of user-visible changes. 2007-12-19
GNU mailutils NEWS -- history of user-visible changes. 2007-12-28
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
See the end of file for copying conditions.
......@@ -26,6 +26,11 @@ The programs using configuration file facility also understand the
output the detailed description of configuration file statements that
affect the given program.
** URL parameters.
Additional mailbox URL parameters `type', `user' and `param' can
appear in any local URLs.
** New utility `maidag'
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 **);
extern int mu_url_sget_query (const mu_url_t, const char **);
extern int mu_url_aget_query (const mu_url_t, char **);
int mu_url_sget_fvpairs (const mu_url_t, size_t *, char ***);
int mu_url_aget_fvpairs (const mu_url_t, size_t *, char ***);
** ACL
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.,
appending to the URL `remote+smtp://127.0.0.1:24' is equivalent to
sending a message using mailer `smtp://127.0.0.1:24'.
** New argcv functions.
- int mu_argcv_get_np (const char *command, int len,
const char *delim, const char *cmnt,
int flags,
int *pargc, char ***pargv, char **endp);
This function is an alternative entry point to
mu_argcv_get/mu_argcv_get_n functions. The resulting argv will contain
non-whitespace delimiters only if flags contains the bit
MU_ARGCV_RETURN_DELIMS.
- void mu_argcv_remove (int *pargc, char ***pargv,
int (*sel) (const char *, void *), void *);
Removes from pargc/pargv all elements for which the sel function
returns true.
** New registry functions.
- int mu_registrar_lookup_url (mu_url_t url, int flags,
mu_record_t *precord, int *pflags);
** Fixed parsing of URLs similar to file:///a/b.
It is parsed as an absolute file name `/a/b'.
......
GNU mailutils TODO list. 2007-12-07
GNU mailutils TODO list. 2007-12-28
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
2007 Free Software Foundation, Inc.
* Fix folder_imap_list in libproto/imap/folder.c
* Documentation
* Review the code and use mu_vartab_* and mu_kwd_* functions where
......
......@@ -39,6 +39,22 @@
} \
printf ("\t" #field " <%s>\n", buf)
static void
print_fvpairs (mu_url_t url)
{
size_t fvc, i;
char **fvp;
int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
if (rc)
{
mu_error ("cannot get F/V pairs: %s", mu_strerror (rc));
exit (1);
}
if (fvc == 0)
return;
for (i = 0; i < fvc; i++)
printf ("\tparam[%d] <%s>\n", i, fvp[i]);
}
int
main ()
......@@ -84,6 +100,7 @@ main ()
printf ("\tport %ld\n", port);
GET_AND_PRINT (path, u, buf, rc);
print_fvpairs (u);
GET_AND_PRINT (query, u, buf, rc);
mu_url_destroy (&u);
......
......@@ -28,12 +28,18 @@
extern "C" {
#endif
#define MU_ARGCV_RETURN_DELIMS 0x01
extern int mu_argcv_get (const char *command, const char *delim,
const char* cmnt,
int *argc, char ***argv);
extern int mu_argcv_get_n (const char *command, int len,
const char *delim, const char *cmnt,
int *argc, char ***argv);
extern int mu_argcv_get_np (const char *command, int len,
const char *delim, const char *cmnt,
int flags,
int *pargc, char ***pargv, char **endp);
extern int mu_argcv_string (int argc, char **argv, char **string);
extern int mu_argcv_free (int argc, char **argv);
......@@ -42,6 +48,8 @@ extern int mu_argcv_quote_char (int c);
extern size_t mu_argcv_quoted_length (const char *str, int *quote);
extern void mu_argcv_unquote_copy (char *dst, const char *src, size_t n);
extern void mu_argcv_quote_copy (char *dst, const char *src);
extern void mu_argcv_remove (int *pargc, char ***pargv,
int (*sel) (const char *, void *), void *);
#ifdef __cplusplus
}
......
......@@ -128,7 +128,7 @@ extern int mu_unre_subject (const char *subject, const char **new_subject);
extern char *mu_charset_lookup (char *lang, char *terr);
extern int mu_true_answer_p (const char *p);
extern int mu_scheme_autodetect_p (const char *scheme, const char **path);
extern int mu_scheme_autodetect_p (mu_url_t);
struct timeval;
......
......@@ -38,7 +38,7 @@ struct _mu_record
void *data; /* back pointer. */
/* Stub functions to override. The default is to return the fields. */
int (*_is_scheme) (mu_record_t, const char *, int);
int (*_is_scheme) (mu_record_t, mu_url_t, int);
int (*_get_url) (mu_record_t, int (*(*_mu_url)) (mu_url_t));
int (*_get_mailbox) (mu_record_t, int (*(*_mu_mailbox)) (mu_mailbox_t));
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));
extern int mu_registrar_lookup (const char *name, int flags,
mu_record_t *precord, int *pflags);
extern int mu_registrar_lookup_url (mu_url_t url, int flags,
mu_record_t *precord, int *pflags);
extern int mu_registrar_record (mu_record_t);
extern int mu_unregistrar_record (mu_record_t);
/* Scheme. */
extern int mu_record_is_scheme (mu_record_t, const char *, int flags);
extern int mu_record_is_scheme (mu_record_t, mu_url_t, int flags);
extern int mu_record_set_scheme (mu_record_t, const char *);
extern int mu_record_set_is_scheme (mu_record_t,
int (*_is_scheme) (mu_record_t, const char *, int));
int (*_is_scheme) (mu_record_t, mu_url_t, int));
/* Url. */
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 *);
extern int mu_url_get_port (const mu_url_t, long *);
int mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp);
int mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp);
extern int mu_url_expand_path (mu_url_t url);
extern const char *mu_url_to_string (const mu_url_t);
extern int mu_url_is_scheme (mu_url_t, const char* scheme);
extern int mu_url_is_scheme (mu_url_t, const char *scheme);
extern int mu_url_is_same_scheme (mu_url_t, mu_url_t);
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);
extern int mu_url_is_same_host (mu_url_t, mu_url_t);
extern int mu_url_is_same_port (mu_url_t, mu_url_t);
extern char* mu_url_decode (const char *s);
extern char *mu_url_decode (const char *s);
extern int mu_url_is_ticket (mu_url_t ticket, mu_url_t url);
extern int mu_url_init (mu_url_t url, int port, const char *scheme);
......
......@@ -143,6 +143,8 @@ streq.h
strerror.c
string.h
string.in.h
strings.h
strings.in.h
stripslash.c
strncasecmp.c
strndup.c
......
......@@ -112,7 +112,7 @@ static int folder_imap_close (mu_folder_t);
static void folder_imap_destroy (mu_folder_t);
static int folder_imap_delete (mu_folder_t, const char *);
static int folder_imap_list (mu_folder_t, const char *, void *,
size_t,
int, size_t,
mu_list_t,
mu_folder_enumerate_fp efp, void *edp);
static int folder_imap_lsub (mu_folder_t, const char *, const char *,
......@@ -975,9 +975,10 @@ glob_to_imap (const char *pat, int recursive)
return ret;
}
/* FIXME: Flags unused */
static int
folder_imap_list (mu_folder_t folder, const char *ref, void *name,
size_t max_level,
int flags, size_t max_level,
mu_list_t flist,
mu_folder_enumerate_fp efp, void *edp)
{
......
......@@ -99,7 +99,6 @@ int _amd_message_insert (struct _amd_data *mhd, struct _amd_message *msg);
int amd_message_stream_open (struct _amd_message *mhm);
void amd_message_stream_close (struct _amd_message *mhm);
void amd_cleanup (void *arg);
int amd_url_init (mu_url_t url, const char *scheme);
struct _amd_message *_amd_get_message (struct _amd_data *amd, size_t msgno);
int amd_msg_lookup (struct _amd_data *amd, struct _amd_message *msg,
size_t *pret);
......
......@@ -36,62 +36,60 @@ extern "C" {
Perhaps they can be changed?
*/
#define MU_POP_PORT 110
#define MU_POP_SCHEME "pop://"
#define MU_POP_SCHEME "pop"
#define MU_POP_SCHEME_LEN (sizeof (MU_POP_SCHEME) - 1)
extern int _url_pop_init (mu_url_t);
extern int _mailbox_pop_init (mu_mailbox_t);
extern int _folder_pop_init (mu_folder_t);
#define MU_POPS_PORT 995
#define MU_POPS_SCHEME "pops://"
#define MU_POPS_SCHEME "pops"
#define MU_POPS_SCHEME_LEN (sizeof (MU_POPS_SCHEME) - 1)
extern int _url_pops_init (mu_url_t);
extern int _mailbox_pops_init (mu_mailbox_t);
#define MU_IMAP_PORT 143
#define MU_IMAP_SCHEME "imap://"
#define MU_IMAP_SCHEME "imap"
#define MU_IMAP_SCHEME_LEN (sizeof (MU_IMAP_SCHEME) - 1)
extern int _url_imap_init (mu_url_t);
extern int _mailbox_imap_init (mu_mailbox_t);
extern int _folder_imap_init (mu_folder_t);
#define MU_IMAPS_PORT 993
#define MU_IMAPS_SCHEME "imaps://"
#define MU_IMAPS_SCHEME "imaps"
#define MU_IMAPS_SCHEME_LEN (sizeof (MU_IMAPS_SCHEME) - 1)
extern int _url_imaps_init (mu_url_t);
extern int _mailbox_imaps_init (mu_mailbox_t);
#define MU_MBOX_SCHEME "mbox:"
#define MU_MBOX_SCHEME "mbox"
#define MU_MBOX_SCHEME_LEN (sizeof (MU_MBOX_SCHEME) - 1)
extern int _url_mbox_init (mu_url_t);
extern int _mailbox_mbox_init (mu_mailbox_t);
extern int _folder_mbox_init (mu_folder_t);
#define MU_FILE_SCHEME "file:"
#define MU_FILE_SCHEME "file"
#define MU_FILE_SCHEME_LEN (sizeof (MU_FILE_SCHEME) - 1)
#define MU_PATH_SCHEME "/"
#define MU_PATH_SCHEME_LEN (sizeof (MU_PATH_SCHEME) - 1)
extern int _url_path_init (mu_url_t);
extern int _mailbox_path_init (mu_mailbox_t);
extern int _folder_path_init (mu_folder_t);
#define MU_SMTP_SCHEME "smtp://"
#define MU_SMTP_SCHEME "smtp"
#define MU_SMTP_SCHEME_LEN (sizeof (MU_SMTP_SCHEME) - 1)
#define MU_SMTP_PORT 25
extern int _url_smtp_init (mu_url_t);
extern int _mailer_smtp_init (mu_mailer_t);
#define MU_SENDMAIL_SCHEME "sendmail:"
#define MU_SENDMAIL_SCHEME "sendmail"
#define MU_SENDMAIL_SCHEME_LEN (sizeof (MU_SENDMAIL_SCHEME) - 1)
extern int _url_sendmail_init (mu_url_t);
extern int _mailer_sendmail_init (mu_mailer_t);
#define MU_MH_SCHEME "mh:"
#define MU_MH_SCHEME "mh"
#define MU_MH_SCHEME_LEN (sizeof (MU_MH_SCHEME) - 1)
extern int _mailbox_mh_init (mu_mailbox_t mailbox);
#define MU_MAILDIR_SCHEME "maildir:"
#define MU_MAILDIR_SCHEME "maildir"
#define MU_MAILDIR_SCHEME_LEN (sizeof (MU_MAILDIR_SCHEME) - 1)
extern int _mailbox_maildir_init (mu_mailbox_t mailbox);
......
......@@ -40,9 +40,10 @@ struct _mu_url
char *host;
long port;
char *path;
char **fvpairs;
int fvcount;
char *query;
void *data;
void (*_destroy) (mu_url_t url);
......
......@@ -33,6 +33,7 @@
#include <maildir.h>
#include <mailutils/mutil.h>
#include <mailutils/url.h>
#include <amd.h>
static int
......@@ -56,22 +57,21 @@ dir_exists (const char *name, const char *suf)
}
static int
_maildir_is_scheme (mu_record_t record, const char *url, int flags)
_maildir_is_scheme (mu_record_t record, mu_url_t url, int flags)
{
const char *path;
if (!url || !record->scheme)
return 0;
if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
if (mu_url_is_scheme (url, record->scheme))
return MU_FOLDER_ATTRIBUTE_ALL & flags;
if (mu_scheme_autodetect_p (url, &path))
if (mu_scheme_autodetect_p (url))
{
/* Attemp auto-detection */
const char *path;
struct stat st;
int rc = 0;
if (mu_url_sget_path (url, &path))
return 0;
if (stat (path, &st) < 0)
return 0;
......@@ -89,21 +89,11 @@ _maildir_is_scheme (mu_record_t record, const char *url, int flags)
return 0;
}
/*
MAILDIR url
maildir:path
*/
int
_maildir_url_init (mu_url_t url)
{
return amd_url_init (url, MU_MAILDIR_SCHEME);
}
static struct _mu_record _maildir_record =
{
MU_MAILDIR_PRIO,
MU_MAILDIR_SCHEME,
_maildir_url_init, /* Url init. */
mu_url_expand_path, /* Url init. */
_mailbox_maildir_init, /* Mailbox init. */
NULL, /* Mailer init. */
_maildir_folder_init, /* Folder init. */
......
......@@ -26,6 +26,5 @@ libmu_mbox_la_SOURCES = \
folder.c\
mbox.c\
mboxscan.c\
mbox0.h\
url.c
mbox0.h
......
......@@ -50,7 +50,7 @@ static struct _mu_record _mbox_record =
{
MU_MBOX_PRIO,
MU_MBOX_SCHEME,
_url_mbox_init, /* Mailbox init. */
mu_url_expand_path, /* URL init. */
_mailbox_mbox_init, /* Mailbox init. */
NULL, /* Mailer init. */
_folder_mbox_init, /* Folder init. */
......@@ -64,19 +64,18 @@ static struct _mu_record _mbox_record =
mu_record_t mu_mbox_record = &_mbox_record;
static int
_path_is_scheme (mu_record_t record, const char *url, int flags)
_path_is_scheme (mu_record_t record, mu_url_t url, int flags)
{
int rc = 0;
const char *path;
if (url && record->scheme)
{
if (mu_scheme_autodetect_p (url, &path))
/* implies:
if (strncmp (record->scheme, url, strlen(record->scheme)) == 0) */
if (mu_scheme_autodetect_p (url))
{
struct stat st;
const char *path;
mu_url_sget_path (url, &path);
if (stat (path, &st) < 0)
{
if (errno == ENOENT)
......@@ -92,6 +91,10 @@ _path_is_scheme (mu_record_t record, const char *url, int flags)
}
else if (flags & MU_FOLDER_ATTRIBUTE_FILE)
{
#if 0
/* This effectively sieves out all non-mailbox files,
but it makes mu_folder_enumerate crawl, which is
intolerable for imap4d LIST command. */
int fd = open (path, O_RDONLY);
if (fd != -1)
{
......@@ -101,6 +104,9 @@ _path_is_scheme (mu_record_t record, const char *url, int flags)
rc |= MU_FOLDER_ATTRIBUTE_FILE;
close (fd);
}
#else
rc |= MU_FOLDER_ATTRIBUTE_FILE;
#endif
}
}
......@@ -116,7 +122,7 @@ static struct _mu_record _path_record =
{
MU_PATH_PRIO,
MU_PATH_SCHEME,
_url_path_init, /* Mailbox init. */
NULL, /* URL init. */
_mailbox_mbox_init, /* Mailbox init. */
NULL, /* Mailer init. */
_folder_mbox_init, /* Folder init. */
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2003, 2007 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <registrar0.h>
#include <url0.h>
#include <mailutils/errno.h>
#include <mailutils/mutil.h>
static void url_mbox_destroy (mu_url_t purl);
static void
url_mbox_destroy (mu_url_t url MU_ARG_UNUSED)
{
}
/* Default mailbox path generator */
static char *
_url_path_default (const char *spooldir, const char *user, int unused)
{
char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2);
if (!mbox)
errno = ENOMEM;
else
sprintf (mbox, "%s/%s", spooldir, user);
return mbox;
}
/* Hashed indexing */
static char *
_url_path_hashed (const char *spooldir, const char *user, int param)
{
int i;
int ulen = strlen (user);
char *mbox;
unsigned hash;
if (param > ulen)
param = ulen;
for (i = 0, hash = 0; i < param; i++)
hash += user[i];
mbox = malloc (ulen + strlen (spooldir) + 5);
sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
return mbox;
}
static int transtab[] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
};
/* Forward Indexing */
static char *
_url_path_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[i] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen-1] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
/* Reverse Indexing */
static char *
_url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen - i - 1] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[0] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
/*
UNIX Mbox
mbox:path[;type=TYPE][;param=PARAM][;user=USERNAME]
*/
int
_url_mbox_init (mu_url_t url)
{
const char *name = mu_url_to_string (url);
size_t len = strlen (name);
char *p;
/* reject the obvious */
if (name == NULL || strncmp (MU_MBOX_SCHEME, name, MU_MBOX_SCHEME_LEN) != 0
|| len < (MU_MBOX_SCHEME_LEN + 1) /* (scheme)+1+(path)*/)
return EINVAL;
/* do I need to decode url encoding '% hex hex' ? */
/* TYPE */
url->_destroy = url_mbox_destroy;
/* SCHEME */
url->scheme = strdup (MU_MBOX_SCHEME);
if (url->scheme == NULL)
{
url_mbox_destroy (url);
return ENOMEM;
}
/* PATH */
name += MU_MBOX_SCHEME_LEN; /* pass the scheme */
url->path = strdup (name);
if (url->path == NULL)
{
url_mbox_destroy (url);
return ENOMEM;
}
p = strchr (url->path, ';');
if (p)
{
char *(*fun)() = _url_path_default;
char *user = NULL;
int param = 0;
*p++ = 0;
while (p)
{
char *q = strchr (p, ';');
if (q)
*q++ = 0;
if (strncasecmp (p, "type=", 5) == 0)
{
char *type = p + 5;
if (strcmp (type, "hash") == 0)
fun = _url_path_hashed;
else if (strcmp (type, "index") == 0)
fun = _url_path_index;
else if (strcmp (type, "rev-index") == 0)
fun = _url_path_rev_index;
else
{
url_mbox_destroy (url);
return MU_ERR_NOENT;
}
}
else if (strncasecmp (p, "user=", 5) == 0)
{
user = p + 5;
}
else if (strncasecmp (p, "param=", 6) == 0)
{
param = strtoul (p+6, NULL, 0);
}
p = q;
}
if (user)
{
p = fun (url->path, user, param);
free (url->path);
url->path = p;
}
else
{
url_mbox_destroy (url);
return MU_ERR_NOENT;
}
}
return 0;
}
static void
url_path_destroy (mu_url_t url MU_ARG_UNUSED)
{
}
int
_url_path_init (mu_url_t url)
{
const char *name = mu_url_to_string (url);
const char *path;
/* reject the obvious */
if (name == NULL || *name == '\0')
return EINVAL;
mu_scheme_autodetect_p (name, &path);
name = strdup (path);
free (url->name);
url->name = (char*) name;
/* TYPE */
url->_destroy = url_path_destroy;
/* SCHEME */
url->scheme = strdup (MU_PATH_SCHEME);
if (url->scheme == NULL)
{
url_path_destroy (url);
return ENOMEM;
}
/* PATH */
url->path = strdup (name);
if (url->path == NULL)
{
url_path_destroy (url);
return ENOMEM;
}
return 0;
}
......@@ -88,22 +88,22 @@ mh_dir_p (const char *name)
}
static int
_mh_is_scheme (mu_record_t record, const char *url, int flags)
_mh_is_scheme (mu_record_t record, mu_url_t url, int flags)
{
const char *path;
int rc = 0;
if (!url || !record->scheme)
return 0;
if (strncmp (record->scheme, url, strlen (record->scheme)) == 0)
if (mu_url_is_scheme (url, record->scheme))
return MU_FOLDER_ATTRIBUTE_ALL & flags;
if (mu_scheme_autodetect_p (url, &path))
if (mu_scheme_autodetect_p (url))
{
/* Attemp auto-detection */
const char *path;
struct stat st;
if (mu_url_sget_path (url, &path))
return 0;
if (stat (path, &st) < 0)
return 0; /* mu_mailbox_open will complain*/
......@@ -119,21 +119,11 @@ _mh_is_scheme (mu_record_t record, const char *url, int flags)
return 0;
}
/*
MH url
mh:path
*/
static int
_mh_url_init (mu_url_t url)
{
return amd_url_init (url, MU_MH_SCHEME);
}
static struct _mu_record _mh_record =
{
MU_MH_PRIO,
MU_MH_SCHEME,
_mh_url_init, /* Url init. */
mu_url_expand_path, /* Url init. */
_mailbox_mh_init, /* Mailbox init. */
NULL, /* Mailer init. */
_mh_folder_init, /* Folder init. */
......
......@@ -63,7 +63,7 @@ static int nntp_folder_open (mu_folder_t, int);
static int nntp_folder_close (mu_folder_t);
static void nntp_folder_destroy (mu_folder_t folder);
static int nntp_folder_list (mu_folder_t folder, const char *ref,
void *name,
void *name, int flags,
size_t max,
mu_list_t flist,
mu_folder_enumerate_fp efp, void *edp);
......@@ -186,7 +186,7 @@ nntp_folder_destroy (mu_folder_t folder)
static int
nntp_folder_list (mu_folder_t folder, const char *ref, void *pat,
nntp_folder_list (mu_folder_t folder, const char *ref, void *pat, int flags,
size_t max_level, mu_list_t flist,
mu_folder_enumerate_fp efp, void *edp)
{
......
......@@ -84,6 +84,7 @@ strchrnul.m4
strdup.m4
strerror.m4
string_h.m4
strings_h.m4
strndup.m4
strnlen.m4
strtok_r.m4
......
......@@ -373,6 +373,8 @@ void util_rfc2047_decode (char **value);
void util_mark_read (mu_message_t msg);
const char *util_url_to_string (mu_url_t url);
int is_address_field (const char *name);
extern int ml_got_interrupt (void);
......
......@@ -55,7 +55,7 @@ mail_mbox_close ()
ngettext ("Held %d message in %s\n",
"Held %d messages in %s\n",
held_count),
held_count, mu_url_to_string (url));
held_count, util_url_to_string (url));
mu_mailbox_close (mbox);
mu_mailbox_destroy (&mbox);
return 0;
......@@ -75,7 +75,7 @@ mail_mbox_commit ()
int is_user_mbox;
mu_mailbox_get_url (mbox, &url);
is_user_mbox = strcmp (mu_url_to_string (url), getenv ("MBOX")) == 0;
is_user_mbox = strcmp (util_url_to_string (url), getenv ("MBOX")) == 0;
{
mu_mailbox_t mb;
......@@ -151,7 +151,7 @@ mail_mbox_commit ()
ngettext ("Saved %d message in %s\n",
"Saved %d messages in %s\n",
saved_count),
saved_count, mu_url_to_string (u));
saved_count, util_url_to_string (u));
mu_mailbox_close (dest_mbox);
mu_mailbox_destroy (&dest_mbox);
}
......
......@@ -61,7 +61,7 @@ mail_summary (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
mu_url_t url = NULL;
mu_mailbox_get_url (mbox, &url);
printf("\"%s\": ", mu_url_to_string (url));
printf("\"%s\": ", util_url_to_string (url));
}
printf (ngettext ("%d message", "%d messages", count), count);
if (mnew > 0)
......
......@@ -1460,3 +1460,18 @@ util_rfc2047_decode (char **value)
}
}
const char *
util_url_to_string (mu_url_t url)
{
const char *scheme;
if (mu_url_sget_scheme (url, &scheme) == 0)
{
if (strcmp (scheme, "file") == 0 || strcmp (scheme, "mbox") == 0)
{
const char *path;
if (mu_url_sget_path (url, &path) == 0)
return path;
}
}
return mu_url_to_string (url);
}
......
......@@ -1531,50 +1531,4 @@ amd_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, size_t *psiz
return 0;
}
static void
amd_url_destroy (mu_url_t url MU_ARG_UNUSED)
{
}
int
amd_url_init (mu_url_t url, const char *scheme)
{
const char *name = mu_url_to_string (url);
const char *path_ptr = name;
size_t len = strlen (name);
size_t scheme_len = strlen (scheme);
if (!name)
return 0;
if (mu_scheme_autodetect_p (name, &path_ptr))
/* nothing */ ;
/* reject the obvious */
else if (strncmp (scheme, name, scheme_len) != 0
|| len < scheme_len + 1)
return EINVAL;
else
path_ptr = name + scheme_len;
/* TYPE */
url->_destroy = amd_url_destroy;
/* SCHEME */
url->scheme = strdup (scheme);
if (url->scheme == NULL)
{
amd_url_destroy (url);
return ENOMEM;
}
/* PATH */
url->path = strdup (path_ptr);
if (url->path == NULL)
{
amd_url_destroy (url);
return ENOMEM;
}
return 0;
}
......
......@@ -28,6 +28,7 @@
/* Keep mailutils namespace clean */
#define argcv_get mu_argcv_get
#define argcv_get_n mu_argcv_get_n
#define argcv_get_np mu_argcv_get_np
#define argcv_string mu_argcv_string
#define argcv_free mu_argcv_free
#define argcv_unquote_char mu_argcv_unquote_char
......@@ -47,15 +48,45 @@
#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
#define isdelim(c,delim) (strchr(delim,(c))!=NULL)
struct argcv_info
{
int len;
const char *command;
const char *delim;
const char *comment;
int flags;
int start;
int end;
int save;
int finish_pos;
};
static void
init_argcv_info (struct argcv_info *ap, int flags,
int len, const char *command, const char *delim,
const char *comment)
{
memset (ap, 0, sizeof *ap);
ap->len = len;
ap->command = command;
ap->delim = delim;
ap->comment = comment;
ap->flags = flags;
}
static int
argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
int *start, int *end, int *save)
argcv_scan (struct argcv_info *ap)
{
int i = 0;
int len = ap->len;
const char *command = ap->command;
const char *delim = ap->delim;
const char *comment = ap->comment;
for (;;)
{
i = *save;
i = ap->save;
if (i >= len)
return i + 1;
......@@ -63,7 +94,7 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
/* Skip initial whitespace */
while (i < len && isws (command[i]))
i++;
*start = i;
ap->start = i;
if (!isdelim (command[i], delim))
{
......@@ -80,11 +111,11 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
if (command[i] == '\'' || command[i] == '"')
{
int j;
for (j = i+1; j < len && command[j] != command[i]; j++)
for (j = i + 1; j < len && command[j] != command[i]; j++)
if (command[j] == '\\')
j++;
if (j < len)
i = j+1;
i = j + 1;
else
i++;
}
......@@ -95,27 +126,36 @@ argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
}
i--;
}
else if (!(ap->flags & MU_ARGCV_RETURN_DELIMS))
{
while (i < len && isdelim (command[i], delim))
i++;
ap->save = i;
continue;
}
*end = i;
*save = i + 1;
ap->end = i;
ap->save = ap->finish_pos = i + 1;
/* If we have a token, and it starts with a comment character, skip
to the newline and restart the token search. */
if (*save <= len)
if (ap->save <= len)
{
if (strchr (cmnt, command[*start]) != NULL)
if (strchr (comment, command[ap->start]) != NULL)
{
i = *save;
ap->finish_pos = ap->start;
i = ap->save;
while (i < len && command[i] != '\n')
i++;
*save = i;
ap->save = i;
continue;
}
}
break;
}
return *save;
return ap->save;
}
static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
......@@ -312,67 +352,85 @@ argcv_quote_copy (char *dst, const char *src)
}
int
argcv_get_n (const char *command, int len, const char *delim, const char *cmnt,
int *argc, char ***argv)
argcv_get_np (const char *command, int len,
const char *delim, const char *cmnt,
int flags,
int *pargc, char ***pargv, char **endp)
{
int i = 0;
int start, end, save;
*argv = NULL;
/* Count number of arguments */
*argc = 0;
save = 0;
struct argcv_info info;
int argc;
char **argv;
if (!delim)
delim = "";
if (!cmnt)
cmnt = "";
while (argcv_scan (len, command, delim, cmnt, &start, &end, &save) <= len)
(*argc)++;
init_argcv_info (&info, flags, len, command, delim, cmnt);
/* Count number of arguments */
argc = 0;
while (argcv_scan (&info) <= len)
argc++;
*argv = calloc ((*argc + 1), sizeof (char *));
if (*argv == NULL)
argv = calloc ((argc + 1), sizeof (char *));
if (argv == NULL)
return ENOMEM;
i = 0;
save = 0;
for (i = 0; i < *argc; i++)
info.save = 0;
for (i = 0; i < argc; i++)
{
int n;
int unquote;
argcv_scan (len, command, delim, cmnt, &start, &end, &save);
argcv_scan (&info);
if ((command[start] == '"' || command[end] == '\'')
&& command[end] == command[start])
if ((command[info.start] == '"' || command[info.end] == '\'')
&& command[info.end] == command[info.start])
{
if (start < end)
if (info.start < info.end)
{
start++;
end--;
info.start++;
info.end--;
}
unquote = 0;
}
else
unquote = 1;
n = end - start + 1;
(*argv)[i] = calloc (n+1, sizeof (char));
if ((*argv)[i] == NULL)
n = info.end - info.start + 1;
argv[i] = calloc (n + 1, sizeof (char));
if (argv[i] == NULL)
{
argcv_free (i, argv);
return ENOMEM;
}
if (unquote)
argcv_unquote_copy ((*argv)[i], &command[start], n);
argcv_unquote_copy (argv[i], &command[info.start], n);
else
memcpy ((*argv)[i], &command[start], n);
(*argv)[i][n] = 0;
memcpy (argv[i], &command[info.start], n);
argv[i][n] = 0;
}
(*argv)[i] = NULL;
argv[i] = NULL;
*pargc = argc;
*pargv = argv;
if (endp)
*endp = (char*) (command + info.finish_pos);
return 0;
}
int
argcv_get_n (const char *command, int len, const char *delim, const char *cmnt,
int *pargc, char ***pargv)
{
return argcv_get_np (command, len, delim, cmnt, MU_ARGCV_RETURN_DELIMS,
pargc, pargv, NULL);
}
int
argcv_get (const char *command, const char *delim, const char *cmnt,
int *argc, char ***argv)
{
......@@ -445,3 +503,35 @@ argcv_string (int argc, char **argv, char **pstring)
return 0;
}
void
mu_argcv_remove (int *pargc, char ***pargv,
int (*sel) (const char *, void *), void *data)
{
int i, j;
int argc = *pargc;
char **argv = *pargv;
int cnt = 0;
for (i = j = 0; i < argc; i++)
{
if (sel (argv[i], data))
{
free (argv[i]);
cnt++;
}
else
{
if (i != j)
argv[j] = argv[i];
j++;
}
}
if (i != j)
argv[j] = NULL;
argc -= cnt;
*pargc = argc;
*pargv = argv;
}
......
......@@ -677,7 +677,7 @@ struct _prog_stream
pid_t pid;
int status;
pid_t writer_pid;
size_t argc;
int argc;
char **argv;
mu_stream_t in, out;
......
......@@ -73,21 +73,36 @@ mu_folder_create_from_record (mu_folder_t *pfolder, const char *name,
== 0)
{
int (*f_init) (mu_folder_t) = NULL;
int (*u_init) (mu_url_t) = NULL;
mu_record_get_folder (record, &f_init);
mu_record_get_url (record, &u_init);
if (f_init && u_init)
if (f_init)
{
int status;
mu_url_t url;
mu_folder_t folder;
int (*u_init) (mu_url_t) = NULL;
/* Parse the url, it may be a bad one and we should bailout if this
failed. */
if ((status = mu_url_create (&url, name) != 0)
|| (status = u_init (url)) != 0)
if ((status = mu_url_create (&url, name)) != 0)
return status;
status = mu_url_parse (url);
if (status)
{
mu_url_destroy (url);
return status;
}
mu_record_get_url (record, &u_init);
if (u_init)
{
status = u_init (url);
if (status)
{
mu_url_destroy (url);
return status;
}
}
mu_monitor_wrlock (&folder_lock);
......
......@@ -165,7 +165,7 @@ int
mu_global_debug_from_string (const char *string, const char *errpfx)
{
int rc;
size_t argc;
int argc;
char **argv;
int i;
......
......@@ -42,20 +42,28 @@
#include <mailutils/mutil.h>
#include <mailbox0.h>
#include <url0.h>
static int
mailbox_folder_create (mu_folder_t *pfolder, const char *name)
mailbox_folder_create (mu_mailbox_t mbox, const char *name,
mu_record_t record)
{
int rc;
char *p, *fname = strdup (name);
char *fname;
if (!fname)
return ENOMEM;
if ((rc = mu_url_aget_path (mbox->url, &fname)))
return rc;
p = strrchr (fname, '/'); /* FIXME: Is this always appropriate? */
if (p && !(mu_is_proto (fname) && strncmp (fname, "file:", 5)))
if (mu_url_is_scheme (mbox->url, "file")
|| mu_url_is_scheme (mbox->url, "mbox")
|| mu_url_is_scheme (mbox->url, "mh")
|| mu_url_is_scheme (mbox->url, "maildir"))
{
char *p = strrchr (fname, '/'); /* FIXME: Is this always appropriate? */
if (p)
*p = 0;
rc = mu_folder_create (pfolder, fname);
}
rc = mu_folder_create_from_record (&mbox->folder, fname, record);
free (fname);
return rc;
}
......@@ -85,22 +93,21 @@ mu_mailbox_get_default_proto ()
}
static int
_create_mailbox (mu_mailbox_t *pmbox, const char *name)
_create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
{
int status;
mu_record_t record = NULL;
if (mu_registrar_lookup (name, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL) == 0)
if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
== 0)
{
mu_log_level_t level;
int (*m_init) (mu_mailbox_t) = NULL;
int (*u_init) (mu_url_t) = NULL;
mu_record_get_mailbox (record, &m_init);
mu_record_get_url (record, &u_init);
if (m_init && u_init)
if (m_init)
{
int status;
mu_url_t url;
int (*u_init) (mu_url_t) = NULL;
mu_mailbox_t mbox;
/* Allocate memory for mbox. */
......@@ -117,19 +124,31 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
return status;
}
/* Parse the url, it may be a bad one and we should bailout if this
failed. */
if ((status = mu_url_create (&url, name)) != 0
|| (status = u_init (url)) != 0)
mu_record_get_url (record, &u_init);
if (u_init && (status = u_init (url)) != 0)
{
mu_mailbox_destroy (&mbox);
return status;
}
/* Make sure scheme contains actual mailbox scheme */
if (strcmp (url->scheme, record->scheme))
{
char *p = strdup (record->scheme);
if (!p)
{
mu_mailbox_destroy (&mbox);
return errno;
}
free (url->scheme);
url->scheme = p;
}
mbox->url = url;
/* Create the folder before initializing the concrete mailbox.
The mailbox needs it's back pointer. */
status = mailbox_folder_create (&mbox->folder, name);
status = mailbox_folder_create (mbox, name, record);
if (status == 0)
status = m_init (mbox); /* Create the concrete mailbox type. */
......@@ -160,6 +179,21 @@ _create_mailbox (mu_mailbox_t *pmbox, const char *name)
return MU_ERR_NO_HANDLER;
}
static int
_create_mailbox (mu_mailbox_t *pmbox, const char *name)
{
int status;
mu_url_t url;
status = mu_url_create (&url, name);
if (status)
return status;
status = mu_url_parse (url);
if (status == 0)
status = _create_mailbox0 (pmbox, url, name);
return status;
}
/* The Mailbox Factory.
Create an iterator for registrar and see if any url scheme match,
Then we call the mailbox's mu_url_create() to parse the URL. Last
......
......@@ -59,6 +59,7 @@
#include <mailutils/stream.h>
#include <mailutils/filter.h>
#include <mailutils/sql.h>
#include <mailutils/url.h>
#include <registrar0.h>
......@@ -1243,21 +1244,15 @@ mu_true_answer_p (const char *p)
return -1;
}
/* Returns true if SCHEME represents a local mail folder. Stores
real folder path to PATH */
/* Returns true if SCHEME represents a local (autodetect) mail folder. */
int
mu_scheme_autodetect_p (const char *scheme, const char **path)
mu_scheme_autodetect_p (mu_url_t url)
{
*path = scheme;
if (strncmp (MU_FILE_SCHEME, scheme, MU_FILE_SCHEME_LEN) == 0)
if (mu_url_is_scheme (url, "file"))
{
*path += MU_FILE_SCHEME_LEN;
mu_url_expand_path (url);
return 1;
}
if (access (scheme, F_OK) == 0
/* FIXME: this can return true even if the folder is unreadable */
|| strncmp (MU_PATH_SCHEME, scheme, MU_PATH_SCHEME_LEN) == 0)
return 1;
return 0;
}
......
......@@ -34,6 +34,7 @@
#include <mailutils/errno.h>
#include <mailutils/nls.h>
#include <mailutils/error.h>
#include <mailutils/url.h>
#include <registrar0.h>
......@@ -90,7 +91,7 @@ mu_registrar_get_iterator (mu_iterator_t *pitr)
}
int
mu_registrar_lookup (const char *name, int flags,
mu_registrar_lookup_url (mu_url_t url, int flags,
mu_record_t *precord, int *pflags)
{
mu_iterator_t iterator;
......@@ -104,7 +105,7 @@ mu_registrar_lookup (const char *name, int flags,
int rc;
mu_record_t record;
mu_iterator_current (iterator, (void **)&record);
if ((rc = mu_record_is_scheme (record, name, flags)))
if ((rc = mu_record_is_scheme (record, url, flags)))
{
status = 0;
if (precord)
......@@ -118,6 +119,23 @@ mu_registrar_lookup (const char *name, int flags,
return status;
}
int
mu_registrar_lookup (const char *name, int flags,
mu_record_t *precord, int *pflags)
{
int rc;
mu_url_t url;
rc = mu_url_create (&url, name);
if (rc)
return rc;
rc = mu_url_parse (url);
if (rc == 0)
rc = mu_registrar_lookup_url (url, flags, precord, pflags);
mu_url_destroy (&url);
return rc;
}
static int
_compare_prio (const void *item, const void *value)
{
......@@ -156,18 +174,16 @@ mu_unregistrar_record (mu_record_t record)
}
int
mu_record_is_scheme (mu_record_t record, const char *scheme, int flags)
mu_record_is_scheme (mu_record_t record, mu_url_t url, int flags)
{
if (record == NULL)
return 0;
/* Overload. */
if (record->_is_scheme)
return record->_is_scheme (record, scheme, flags);
return record->_is_scheme (record, url, flags);
if (scheme
&& record->scheme
&& strncasecmp (record->scheme, scheme, strlen (record->scheme)) == 0)
if (mu_url_is_scheme (url, record->scheme))
return MU_FOLDER_ATTRIBUTE_ALL;
return 0;
......@@ -183,8 +199,8 @@ mu_record_set_scheme (mu_record_t record, const char *scheme)
}
int
mu_record_set_is_scheme (mu_record_t record, int (*_is_scheme)
(mu_record_t, const char *, int))
mu_record_set_is_scheme (mu_record_t record,
int (*_is_scheme) (mu_record_t, mu_url_t, int))
{
if (record == NULL)
return EINVAL;
......
......@@ -627,4 +627,41 @@ ftp://ftp.example.org:111/mbox/user%40host => SUCCESS
path <mbox/user@host>
query <>
ftp://ftp.example.org:111/mbox/user%40host;type=pass => SUCCESS
scheme <ftp>
user <>
passwd <>
auth <>
host <ftp.example.org>
port 111
path <mbox/user@host>
param[0] <type=pass>
query <>
mbox:/var/spool/mail;type=index;param=2;user=gray => SUCCESS
scheme <mbox>
user <>
passwd <>
auth <>
host <>
port 0
path </var/spool/mail>
param[0] <type=index>
param[1] <param=2>
param[2] <user=gray>
query <>
mbox:///var/spool/mail;type=index;param=2;user=gray => SUCCESS
scheme <mbox>
user <>
passwd <>
auth <>
host <>
port 0
path </var/spool/mail>
param[0] <type=index>
param[1] <param=2>
param[2] <user=gray>
query <>
# NOTE: This file must end with an empty line
......
......@@ -30,6 +30,7 @@
#include <mailutils/mutil.h>
#include <mailutils/errno.h>
#include <mailutils/argcv.h>
#include <url0.h>
/*
......@@ -86,6 +87,9 @@ mu_url_destroy (mu_url_t * purl)
if (url->path)
free (url->path);
if (url->fvcount)
mu_argcv_free (url->fvcount, url->fvpairs);
if (url->query)
free (url->query);
......@@ -100,11 +104,12 @@ mu_url_parse (mu_url_t url)
{
int err = 0;
char *n = NULL;
struct _mu_url u = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
struct _mu_url u;
if (!url || !url->name)
return EINVAL;
memset (&u, 0, sizeof u);
/* can't have been parsed already */
if (url->scheme || url->user || url->passwd || url->auth ||
url->host || url->path || url->query)
......@@ -126,10 +131,13 @@ mu_url_parse (mu_url_t url)
*/
#define UALLOC(X) \
if(u.X && u.X[0] && (url->X = mu_url_decode(u.X)) == 0) { \
if (u.X && u.X[0] && (url->X = mu_url_decode(u.X)) == 0) \
{ \
err = ENOMEM; \
goto CLEANUP; \
} else { \
} \
else \
{ \
/* Set zero-length strings to NULL. */ \
u.X = NULL; \
}
......@@ -142,6 +150,8 @@ mu_url_parse (mu_url_t url)
UALLOC (path);
UALLOC (query);
#undef UALLOC
url->fvcount = u.fvcount;
url->fvpairs = u.fvpairs;
url->port = u.port;
}
......@@ -150,7 +160,7 @@ CLEANUP:
if (err)
{
#define UFREE(X) if(X) { free(X); X = 0; }
#define UFREE(X) if (X) { free(X); X = 0; }
UFREE (url->scheme);
UFREE (url->user);
......@@ -199,6 +209,12 @@ url_parse0 (mu_url_t u, char *name)
if (name == NULL)
return EINVAL;
if (name[0] == '/')
{
u->scheme = "file";
}
else
{
/* Parse out the SCHEME. */
p = strchr (name, ':');
if (p == NULL)
......@@ -213,25 +229,23 @@ url_parse0 (mu_url_t u, char *name)
*name = tolower (*name);
name = p;
}
/* Check for nothing following the scheme. */
if (!*name)
return 0;
if (strncmp (name, "//", 2) != 0)
if (strncmp (name, "//", 2) == 0)
{
u->path = name;
return 0;
}
name += 2;
if (name[0] == '/')
{
u->path = name;
return 0;
p = u->path + strcspn (u->path, ";?");
}
else
{
/* Split into LHS and RHS of the '@', and then parse each side. */
u->host = strchr (name, '@');
if (u->host == NULL)
......@@ -257,11 +271,8 @@ url_parse0 (mu_url_t u, char *name)
if (strncasecmp (name + 1, "auth=", 5) == 0)
{
*name++ = 0;
name += 5;
u->auth = name;
break;
}
}
......@@ -276,11 +287,9 @@ url_parse0 (mu_url_t u, char *name)
/* Parse the host and port from the RHS. */
p = strchr (u->host, ':');
if (p)
{
*p++ = 0;
u->port = strtol (p, &p, 10);
/* Check for garbage after the port: we should be on the start
......@@ -289,20 +298,36 @@ url_parse0 (mu_url_t u, char *name)
return MU_ERR_PARSE;
}
else
p = u->host + strcspn (u->host, "/?");
p = u->host + strcspn (u->host, ";/?");
}
}
else
{
u->path = name;
p = u->path + strcspn (u->path, ";?");
}
/* Either way, if we're not at a nul, we're at a path or query. */
if (*p == '?')
if (u->path == NULL && *p == '/')
{
/* found a query */
/* found a path */
*p++ = 0;
u->query = p;
u->path = p;
p = u->path + strcspn (u->path, ";?");
}
if (*p == '/')
if (*p == ';')
{
/* found a path */
*p++ = 0;
u->path = p;
mu_argcv_get_np (p, strlen (p), ";", "?", 0,
&u->fvcount, &u->fvpairs, &p);
}
if (*p == '?')
{
/* found a query */
*p++ = 0;
u->query = p;
}
return 0;
......@@ -431,6 +456,46 @@ DECL_ACCESSORS (host)
DECL_ACCESSORS (path)
DECL_ACCESSORS (query)
/* field-value pairs accessors */
int
mu_url_sget_fvpairs (const mu_url_t url, size_t *fvc, char ***fvp)
{
if (url == NULL)
return EINVAL;
/* FIXME: no _get_fvpairs method, but the method stuff needs to be rewritten
anyway */
*fvc = url->fvcount;
*fvp = url->fvpairs;
return 0;
}
int
mu_url_aget_fvpairs (const mu_url_t url, size_t *pfvc, char ***pfvp)
{
size_t fvc, i;
char **fvp;
char **fvcopy;
int rc = mu_url_sget_fvpairs (url, &fvc, &fvp);
if (rc)
return rc;
fvcopy = calloc (fvc + 1, sizeof (fvcopy[0]));
if (!fvcopy)
return errno;
for (i = 0; i < fvc; i++)
{
if (!(fvcopy[i] = strdup (fvp[i])))
{
mu_argcv_free (i, fvcopy);
return errno;
}
}
fvcopy[i] = NULL;
*pfvc = fvc;
*pfvp = fvcopy;
return 0;
}
int
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)
return status;
}
/* Default mailbox path generator */
static char *
_url_path_default (const char *spooldir, const char *user, int unused)
{
char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2);
if (!mbox)
errno = ENOMEM;
else
sprintf (mbox, "%s/%s", spooldir, user);
return mbox;
}
/* Hashed indexing */
static char *
_url_path_hashed (const char *spooldir, const char *user, int param)
{
int i;
int ulen = strlen (user);
char *mbox;
unsigned hash;
if (param > ulen)
param = ulen;
for (i = 0, hash = 0; i < param; i++)
hash += user[i];
mbox = malloc (ulen + strlen (spooldir) + 5);
sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user);
return mbox;
}
static int transtab[] = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f',
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g'
};
/* Forward Indexing */
static char *
_url_path_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[i] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen-1] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
/* Reverse Indexing */
static char *
_url_path_rev_index (const char *spooldir, const char *iuser, int index_depth)
{
const unsigned char* user = (const unsigned char*) iuser;
int i, ulen = strlen (iuser);
char *mbox, *p;
if (ulen == 0)
return NULL;
mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1);
strcpy (mbox, spooldir);
p = mbox + strlen (mbox);
for (i = 0; i < index_depth && i < ulen; i++)
{
*p++ = '/';
*p++ = transtab[ user[ulen - i - 1] ];
}
for (; i < index_depth; i++)
{
*p++ = '/';
*p++ = transtab[ user[0] ];
}
*p++ = '/';
strcpy (p, iuser);
return mbox;
}
static int
rmselector (const char *p, void *data MU_ARG_UNUSED)
{
return strncmp (p, "type=", 5) == 0
|| strncmp (p, "user=", 5) == 0
|| strncmp (p, "param=", 6) == 0;
}
int
mu_url_expand_path (mu_url_t url)
{
size_t i;
char *user = NULL;
int param = 0;
char *p;
char *(*fun) (const char *, const char *, int) = _url_path_default;
if (url->fvcount == 0)
return 0;
for (i = 0; i < url->fvcount; i++)
{
p = url->fvpairs[i];
if (strncmp (p, "type=", 5) == 0)
{
char *type = p + 5;
if (strcmp (type, "hash") == 0)
fun = _url_path_hashed;
else if (strcmp (type, "index") == 0)
fun = _url_path_index;
else if (strcmp (type, "rev-index") == 0)
fun = _url_path_rev_index;
else
return MU_ERR_NOENT;
}
else if (strncmp (p, "user=", 5) == 0)
{
user = p + 5;
}
else if (strncmp (p, "param=", 6) == 0)
{
param = strtoul (p + 6, NULL, 0);
}
}
if (user)
{
char *p = fun (url->path, user, param);
if (p)
{
free (url->path);
url->path = p;
}
mu_argcv_remove (&url->fvcount, &url->fvpairs, rmselector, NULL);
}
else
return MU_ERR_NOENT;
return 0;
}
......
......@@ -24,7 +24,7 @@ static char *bulletin_db_name;
void
set_bulletin_db (char *file)
{
bulletin_db_name = file;
bulletin_db_name = strdup (file);
}
static void
......@@ -67,7 +67,7 @@ open_bulletin_mailbox (mu_mailbox_t *pmbox)
int
set_bulletin_source (char *source)
{
bulletin_mbox_name = source;
bulletin_mbox_name = strdup (source);
return 0;
}
......@@ -145,8 +145,14 @@ read_bulletin_db (size_t *pnum)
if (rc)
{
int ec = errno;
if (ec == ENOENT)
{
*pnum = 0;
return 0;
}
mu_error (_("Cannot fetch bulletin db data: %s"),
mu_strerror (errno));
mu_strerror (ec));
mu_dbm_close (db);
return 1;
}
......@@ -236,18 +242,14 @@ write_bulletin_db (size_t num)
}
#endif /* USE_DBM */
size_t
get_last_delivered_num ()
int
get_last_delivered_num (size_t *pret)
{
size_t num = 0;
#ifdef USE_DBM
if (bulletin_db_name && read_bulletin_db (&num) == 0)
return num;
if (bulletin_db_name && read_bulletin_db (pret) == 0)
return 0;
#endif
read_popbull_file (&num);
return num;
return read_popbull_file (pret);
}
void
......@@ -271,9 +273,8 @@ deliver_pending_bulletins ()
return;
rc = open_bulletin_mailbox (&bull);
if (rc)
if (rc || get_last_delivered_num (&lastnum))
return;
lastnum = get_last_delivered_num ();
rc = mu_mailbox_messages_count (bull, &total);
if (rc)
......
......@@ -50,7 +50,7 @@ pop3d_capa (const char *arg)
login_delay_capa ();
/* This can be implemented by setting an header field on the message. */
if (expire < 0)
if (expire == EXPIRE_NEVER)
pop3d_outf ("EXPIRE NEVER\r\n");
else
pop3d_outf ("EXPIRE %s\r\n", mu_umaxtostr (0, expire));
......