Commit 0e4bc2f8 0e4bc2f83e2cc5c51783a4fca8c9b038cb66c8ea by Alain Magloire

* mailbox/smtp.c(smtp_readline): Because of the buffering mechanism,

	we must maintain the offset.

	* imap4d/list.c: partially implemented the LIST command.
	* imap4d/imap4d.c: homedir new global variable.
	* imap4d/login.c: same ${HOME} in homedir.
	* imap4d/util.c (util_getword): Be aware of the quotes.

	* lib/fnmatch.c: New replacement file.
	* lib/fnmatch.h: New replacement file.
	* configure.in: Check for fnmatch().
1 parent efe54c6d
2001-04-19 Alain Magloire
* mailbox/smtp.c(smtp_readline): Because of the buffering mechanism,
we must maintain the offset.
* imap4d/list.c: partially implemented the LIST command.
* imap4d/imap4d.c: homedir new global variable.
* imap4d/login.c: same ${HOME} in homedir.
* imap4d/util.c (util_getword): Be aware of the quotes.
* lib/fnmatch.c: New replacement file.
* lib/fnmatch.h: New replacement file.
* configure.in: Check for fnmatch().
2001-04-18 Alain Magloire
Finally took time to put the code in from Jakob first draft, in
......
......@@ -66,8 +66,10 @@ AC_FUNC_ALLOCA
# Not use.
#AC_FUNC_MEMCMP
AC_FUNC_MMAP
# FIXME: Provide the GNU one for loosing platforms
AC_FUNC_FNMATCH
if test "$ac_cv_func_fnmatch_works" = "no"; then
AC_LIBOBJ(fnmatch)
fi
AC_REPLACE_FUNCS(setenv snprintf strtok_r strncasecmp strcasecmp vasprintf)
AC_CHECK_FUNCS(mkstemp)
......
......@@ -51,12 +51,6 @@ Return non-zero value if message is multi-part.
@deftypefun int message_get_part (message_t @var{msg}, size_t part, message_t *msg)
@end deftypefun
@deftypefun int message_add_part (message_t @var{msg}, message_t @var{msg})
@end deftypefun
@deftypefun int message_set_add_part (message_t @var{msg}, message_t @var{msg})
@end deftypefun
@deftypefun int message_get_stream (message_t @var{msg}, stream_t *@var{pstream})
@end deftypefun
......
......@@ -20,6 +20,7 @@
int
imap4d_capability (struct imap4d_command *command, char *arg)
{
(void)arg;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
util_out (RESP_NONE, "CAPABILITY IMAP4rev1");
......
......@@ -799,6 +799,8 @@ fetch_header_fields_not (message_t msg, char *arg, unsigned long start,
return 0;
}
/* FIXME: The address is limit by a buffer of 128, no good. We should
allocate the buffer. */
static int
fetch_send_address (char *addr)
{
......
......@@ -21,6 +21,7 @@ int *ifile;
FILE *ofile;
unsigned int timeout = 1800; /* RFC2060: 30 minutes, if enable. */
mailbox_t mbox;
char *homedir;
int state = STATE_NONAUTH;
static int imap4_mainloop __P ((int, int));
......
......@@ -107,6 +107,7 @@ extern struct imap4d_command imap4d_command_table[];
extern FILE *ofile;
extern unsigned int timeout;
extern mailbox_t mbox;
extern char *homedir;
extern int state;
/* Imap4 commands */
......
......@@ -16,15 +16,216 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "imap4d.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define MATCH (1 << 0)
#define RECURSE_MATCH (1 << 1)
#define NOMATCH (1 << 2)
#define NOSELECT (1 << 3)
#define NOINFERIORS (1 << 4)
#define NOSELECT_RECURSE (1 << 5)
/*
*
*/
static void unquote (char **);
static int match (const char *, const char *);
static int imap_match (const char *, const char *);
static void list_file (const char *, const char *);
static char *expand (const char *);
static void print_file (const char *, const char *);
static void print_dir (const char *, const char *);
int
imap4d_list (struct imap4d_command *command, char *arg)
{
char *sp = NULL;
char *reference;
char *wildcard;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Not supported");
reference = util_getword (arg, &sp);
wildcard = util_getword (NULL, &sp);
if (!reference || !wildcard)
return util_finish (command, RESP_BAD, "Too few arguments");
unquote (&reference);
unquote (&wildcard);
if (*wildcard == '\0')
{
/* FIXME: How do we know the hierarchy delimeter. */
util_out (RESP_NONE, "LIST (\\NoSelect) \"/\" \"%s\"",
(*reference == '\0' || *reference != '/') ? "" : "/");
}
else
{
char *p;
if (*reference == '\0')
reference = homedir;
p = expand (reference);
if (chdir (p) == 0)
{
list_file (reference, wildcard);
chdir (homedir);
}
free (p);
}
return util_finish (command, RESP_OK, "Completed");
}
/* expand the '~' */
static char *
expand (const char *ref)
{
/* FIXME: note done. */
return strdup (ref);
}
/* Remove the surrounding double quotes. */
static void
unquote (char **ptr)
{
char *s = *ptr;
if (*s == '"')
{
char *p = ++s;
while (*p && *p != '"')
p++;
if (*p == '"')
*p = '\0';
}
*ptr = s;
}
static void
print_file (const char *ref, const char *file)
{
if (strpbrk (file, "\"{}"))
{
util_out (RESP_NONE, "LIST (\\NoInferior \\UnMarked) \"/\" {%d}",
strlen (ref) + strlen ((*ref) ? "/" : "") + strlen (file));
util_send ("%s%s%s\r\n", ref, (*ref) ? "/" : "", file);
}
else
util_out (RESP_NONE, "LIST (\\NoInferior \\UnMarked) \"/\" %s%s%s",
ref, (*ref) ? "/" : "", file);
}
static void
print_dir (const char *ref, const char *file)
{
if (strpbrk (file, "\"{}"))
{
util_out (RESP_NONE, "LIST (\\NoSelect) \"/\" {%d}",
strlen (ref) + strlen ((*ref) ? "/" : "") + strlen (file));
util_send ("%s%s%s\r\n", ref, (*ref) ? "/" : "", file);
}
else
util_out (RESP_NONE, "LIST (\\NoSelect) \"/\" %s%s%s",
ref, (*ref) ? "/" : "", file);
}
/* Recusively calling the files. */
static void
list_file (const char *ref, const char *pattern)
{
DIR *dirp;
struct dirent *dp;
dirp = opendir (".");
if (dirp == NULL)
return;
while ((dp = readdir (dirp)) != NULL)
{
int status = match (dp->d_name, pattern);
if (status & (MATCH | RECURSE_MATCH))
{
if (status & NOSELECT)
{
print_dir (ref, dp->d_name);
if (status & RECURSE_MATCH)
{
if (chdir (dp->d_name) == 0)
{
char *buffer = NULL;
asprintf (&buffer, "%s%s%s", ref,
(*ref) ? "/" : "", dp->d_name);
list_file (buffer, pattern);
free (buffer);
chdir ("..");
}
}
}
else if (status & NOINFERIORS)
{
print_file (ref, dp->d_name);
}
}
}
}
static int
match (const char *entry, const char *pattern)
{
struct stat stats;
int status = imap_match (entry, pattern);
if (status & MATCH || status || RECURSE_MATCH)
{
if (stat (entry, &stats) == 0)
status |= (S_ISREG (stats.st_mode)) ? NOINFERIORS : NOSELECT;
}
return status;
}
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
static int
imap_match (const char *string, const char *pattern)
{
const char *p = pattern, *n = string;
char c;
for (;(c = *p++) != '\0'; n++)
{
switch (c)
{
case '%':
if (*p == '\0')
return (*n == '/') ? NOMATCH : MATCH;
for (; *n != '\0'; ++n)
if (match (n, p) == MATCH)
return MATCH;
break;
case '*':
if (*p == '\0')
return RECURSE_MATCH;
for (; *n != '\0'; ++n)
{
int status = match (n, p);
if (status == MATCH || status == RECURSE_MATCH)
return status;
}
break;
default:
if (c != *n)
return NOMATCH;
}
}
if (*n == '\0')
return MATCH;
return NOMATCH;
}
......
......@@ -128,5 +128,9 @@ imap4d_login (struct imap4d_command *command, char *arg)
if (pw->pw_uid > 1)
setuid (pw->pw_uid);
homedir = strdup (pw->pw_dir);
/* FIXME: Check for errors. */
chdir (homedir);
return util_finish (command, RESP_OK, "Completed");
}
......
......@@ -63,7 +63,6 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
unsigned long uidvalidity = 0;
size_t count = 0, recent = 0, unseen = 0, uidnext = 0;
state = STATE_SEL;
mailbox_uidvalidity (mbox, &uidvalidity);
mailbox_uidnext (mbox, &uidnext);
mailbox_messages_count (mbox, &count);
......@@ -75,13 +74,14 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
uidvalidity);
util_out (RESP_OK, "[UIDNEXT %d] Predicted next uid", uidnext);
if (unseen)
util_out (RESP_OK, "[UNSEEN (%d)] %d is first unseen messsage ",
unseen, unseen);
util_out (RESP_OK, "[UNSEEN (%d)] first unseen messsage ", unseen);
util_out (RESP_NONE, "FLAGS (%s)", mflags);
/* FIXME:
- '\*' can be supported if we use the attribute_set userflag()
- Answered is still not set in the mailbox code. */
util_out (RESP_OK, "[PERMANENTFLAGS (%s)] Permanent flags", pflags);
/* Need to set the state explicitely for select. */
state = STATE_SEL;
return util_send ("%s OK [%s] %s Complete\r\n", command->tag,
(MU_STREAM_READ == flags) ?
"READ-ONLY" : "READ-WRITE", command->name);
......
......@@ -26,6 +26,27 @@ static const char * sc2string (int rc);
char *
util_getword (char *s, char **save)
{
/* Take care of words between double quotes. */
{
char *p;
if ((p = s) || (p = *save))
{
while (isspace ((unsigned)*p))
p++;
if (*p == '"')
{
s = p;
p++;
while (*p && *p != '"')
p++;
if (*p == '"')
p++;
*save = (*p) ? p + 1 : p;
*p = '\0';
return s;
}
}
}
return strtok_r (s, " \r\n", save);
}
......
......@@ -4,11 +4,11 @@ noinst_LIBRARIES = libmailutils.a
libmailutils_a_SOURCES = basename.c getopt.c getopt1.c md5.c getline.c \
xstrdup.c xmalloc.c argcv.c
EXTRA_DIST = alloca.c setenv.c snprintf.c strchrnul.c strndup.c strnlen.c \
strtok_r.c xstrtol.c vasprintf.c
EXTRA_DIST = alloca.c fnmatch.c setenv.c snprintf.c strchrnul.c strndup.c \
strnlen.c strtok_r.c xstrtol.c vasprintf.c
noinst_HEADERS = getopt.h md5.h getline.h snprintf.h xstrtol.h xalloc.h \
argcv.h error.h
noinst_HEADERS = argcv.h error.h fnmatch.h getline.h getopt.h md5.h \
snprintf.h xalloc.h xstrtol.h
libmailutils_a_LIBADD = @LIBOBJS@ @ALLOCA@
......
......@@ -225,7 +225,7 @@ folder_mbox_rename (folder_t folder, const char *oldpath, const char *newpath)
}
/* The listing is not recursif and we use glob() some expansion for us.
Unfortunately glov() does not expand the '~'. We also return
Unfortunately glob() does not expand the '~'. We also return
The full pathname so it can be use to create other folders. */
static int
folder_mbox_list (folder_t folder, const char *dirname, const char *pattern,
......
......@@ -62,6 +62,7 @@ struct _smtp
char *nl;
char *buffer;
size_t buflen;
off_t s_offset;
enum smtp_state
{
......@@ -818,7 +819,7 @@ smtp_readline (smtp_t smtp)
do
{
status = stream_readline (smtp->mailer->stream, smtp->buffer + total,
smtp->buflen - total, 0, &n);
smtp->buflen - total, smtp->s_offset, &n);
if (status != 0)
return status;
......@@ -827,6 +828,7 @@ smtp_readline (smtp_t smtp)
return EIO;
total += n;
smtp->s_offset += n;
smtp->nl = memchr (smtp->buffer, '\n', total);
if (smtp->nl == NULL) /* Do we have a full line. */
{
......