Commit 2b99aa95 2b99aa9530eb3001e8015df35993d245383ffcca by Alain Magloire

* imap4d/create.c: First implementation.

	* imap4d/delete.c: First implementation.
	* imap4d/list.c: First implementation.
	* imap4d/rename.c: First implementation.
	* imap4d/util.c: New functions.
	(util_tilde_expansion): expand ~.
	(util_unquote): Remove surrounding double quotes.
	(util_getfullpath): Expand the path to absolute.
	* imap4d/fetch.c:  Did not cycle throught the items.
	(fetch_send_address): Patch from Sam Roberts, did not
	use the index.

	* mailbox/attachement.c (message_unencapsulate): Little buglet
	strncasemp() passing the wrong size.
1 parent 29972003
......@@ -16,6 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "imap4d.h"
#include <unistd.h>
/*
* must create a new mailbox
......@@ -24,7 +25,76 @@
int
imap4d_create (struct imap4d_command *command, char *arg)
{
char *name;
char *sp = NULL;
const char *delim = "/";
int rc = RESP_OK;
const char *msg = "Completed";
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Command not supported");
name = util_getword (arg, &sp);
if (!name)
return util_finish (command, RESP_BAD, "Too few arguments");
util_unquote (&name);
if (*name == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
/* Creating, "Inbox" should always fail. */
if (strcasecmp (name, "INBOX") == 0)
return util_finish (command, RESP_BAD, "Already exist");
/* Allocates memory. */
name = util_getfullpath (name, delim);
/* It will fail if the mailbx already exists. */
if (access (name, F_OK) != 0)
{
char *dir;
char *d = name + strlen (delim); /* Pass the root delimeter. */
if (chdir (delim) == 0) /* start on the root. */
for (; (dir = strchr (d, delim[0])); d = dir)
{
*dir++ = '\0';
if (chdir (d) != 0)
{
if (mkdir (d, 0700) == 0)
{
if (chdir (d) == 0)
{
continue;
}
else
{
rc = RESP_NO;
msg = "Can not create mailbox";
break;
}
}
}
}
/* If it ended with the delim they wanted to create a new folder. */
if (rc == RESP_OK && d && *d != '\0')
{
int fd = creat (d, 0600);
if (fd != -1)
close (fd);
else
{
rc = RESP_NO;
msg = "Can not create mailbox";
}
}
}
else
{
rc = RESP_NO;
msg = "already exists";
}
chdir (homedir);
free (name);
return util_finish (command, rc, msg);
}
......
......@@ -24,7 +24,36 @@
int
imap4d_delete (struct imap4d_command *command, char *arg)
{
char *sp = NULL;
int rc = RESP_OK;
const char *msg = "Completed";
const char *delim = "/";
char *name;
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Command not supported");;
name = util_getword (arg, &sp);
if (!name)
return util_finish (command, RESP_BAD, "Too few arguments");
util_unquote (&name);
if (*name == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
/* Deleting, "Inbox" should always fail. */
if (strcasecmp (name, "INBOX") == 0)
return util_finish (command, RESP_BAD, "Already exist");
/* Allocates memory. */
name = util_getfullpath (name, delim);
if (remove (name) != 0)
{
rc = RESP_NO;
msg = "Can not remove";
}
free (name);
return util_finish (command, rc, msg);
}
......
......@@ -105,7 +105,6 @@ imap4d_fetch (struct imap4d_command *command, char *arg)
int status;
const char *errmsg = "Completed";
struct imap4d_command *fcmd;
char item[32];
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
......@@ -114,14 +113,8 @@ imap4d_fetch (struct imap4d_command *command, char *arg)
if (!msgset)
return util_finish (command, RESP_BAD, "Too few args");
/* Get the command name. */
item[0] = '\0';
util_token (item, sizeof (item), &sp);
/* Search in the table. */
fcmd = util_getcommand (item, fetch_command_table);
if (!fcmd)
return util_finish (command, RESP_BAD, "Command unknown");
if (sp == NULL || *sp == '\0')
return util_finish (command, RESP_BAD, "Too few args");
/* Get the message numbers in set[]. */
status = util_msgset (msgset, &set, &n, 0);
......@@ -130,10 +123,26 @@ imap4d_fetch (struct imap4d_command *command, char *arg)
for (i = 0; i < n; i++)
{
char item[32];
char *items = strdup (sp);
char *p = items;
util_send ("* FETCH %d (", set[i]);
item[0] = '\0';
/* Get the fetch command names. */
while (*items && *items != ')')
{
util_token (item, sizeof (item), &items);
/* Search in the table. */
fcmd = util_getcommand (item, fetch_command_table);
if (fcmd)
{
/* We use the states field to hold the msgno/uid. */
fcmd->states = set[i];
util_send ("* FETCH %d (", set[i]);
fcmd->func (fcmd, sp);
fcmd->func (fcmd, items);
util_send (" ");
}
}
free (p);
util_send (")\r\n");
}
free (set);
......@@ -358,19 +367,19 @@ fetch_rfc822 (struct imap4d_command *command, char *arg)
{
if (*arg == '.')
{
if (strcasecmp (arg, ".SIZE") == 0)
if (strncasecmp (arg, ".SIZE", 5) == 0)
{
struct imap4d_command c_rfc= fetch_command_table[F_RFC822_SIZE];
c_rfc.states = command->states;
fetch_rfc822_size (&c_rfc, arg);
}
else if (strcasecmp (arg, ".TEXT") == 0)
else if (strncasecmp (arg, ".TEXT", 5) == 0)
{
struct imap4d_command c_rfc = fetch_command_table[F_RFC822_TEXT];
c_rfc.states = command->states;
fetch_rfc822_text (&c_rfc, arg);
}
else if (strcasecmp (arg, ".HEADER") == 0)
else if (strncasecmp (arg, ".HEADER", 7) == 0)
{
struct imap4d_command c_rfc = fetch_command_table[F_RFC822_HEADER];
c_rfc.states = command->states;
......@@ -824,33 +833,46 @@ fetch_send_address (char *addr)
util_send ("(");
*buf = '\0';
address_get_personal (address, 1, buf, sizeof (buf), NULL);
address_get_personal (address, i, buf, sizeof (buf), NULL);
if (*buf == '\0')
util_send ("NIL ");
util_send ("NIL");
else
util_send ("\"%s\" ", buf);
util_send ("\"%s\"", buf);
util_send (" ");
*buf = '\0';
address_get_route (address, 1, buf, sizeof (buf), NULL);
address_get_route (address, i, buf, sizeof (buf), NULL);
if (*buf == '\0')
util_send ("NIL ");
util_send ("NIL");
else
util_send ("\"%s\" ", buf);
util_send ("NIL ", buf);
util_send ("\"%s\"", buf);
util_send (" ");
*buf = '\0';
address_get_local_part (address, 1, buf, sizeof (buf), NULL);
{
int is_group = 0;
address_is_group(address, i, &is_group);
if(is_group)
address_get_personal (address, i, buf, sizeof (buf), NULL);
else
address_get_local_part (address, i, buf, sizeof (buf), NULL);
}
if (*buf == '\0')
util_send ("NIL ");
util_send ("NIL");
else
util_send ("\"%s\" ", buf);
util_send ("\"%s\"", buf);
util_send (" ");
*buf = '\0';
address_get_domain (address, 1, buf, sizeof (buf), NULL);
address_get_domain (address, i, buf, sizeof (buf), NULL);
if (*buf == '\0')
util_send ("NIL ");
util_send ("NIL");
else
util_send ("\"%s\" ", buf);
util_send ("\"%s\"", buf);
util_send (")");
}
......
......@@ -47,6 +47,8 @@
#include <stdarg.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
......@@ -111,46 +113,49 @@ extern char *homedir;
extern int state;
/* Imap4 commands */
int imap4d_capability __P ((struct imap4d_command *, char *));
int imap4d_noop __P ((struct imap4d_command *, char *));
int imap4d_logout __P ((struct imap4d_command *, char *));
int imap4d_authenticate __P ((struct imap4d_command *, char *));
int imap4d_login __P ((struct imap4d_command *, char *));
int imap4d_select __P ((struct imap4d_command *, char *));
int imap4d_select0 __P ((struct imap4d_command *, char *, int));
int imap4d_examine __P ((struct imap4d_command *, char *));
int imap4d_create __P ((struct imap4d_command *, char *));
int imap4d_delete __P ((struct imap4d_command *, char *));
int imap4d_rename __P ((struct imap4d_command *, char *));
int imap4d_subscribe __P ((struct imap4d_command *, char *));
int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
int imap4d_list __P ((struct imap4d_command *, char *));
int imap4d_lsub __P ((struct imap4d_command *, char *));
int imap4d_status __P ((struct imap4d_command *, char *));
int imap4d_append __P ((struct imap4d_command *, char *));
int imap4d_check __P ((struct imap4d_command *, char *));
int imap4d_close __P ((struct imap4d_command *, char *));
int imap4d_expunge __P ((struct imap4d_command *, char *));
int imap4d_search __P ((struct imap4d_command *, char *));
int imap4d_fetch __P ((struct imap4d_command *, char *));
int imap4d_store __P ((struct imap4d_command *, char *));
int imap4d_copy __P ((struct imap4d_command *, char *));
int imap4d_uid __P ((struct imap4d_command *, char *));
extern int imap4d_capability __P ((struct imap4d_command *, char *));
extern int imap4d_noop __P ((struct imap4d_command *, char *));
extern int imap4d_logout __P ((struct imap4d_command *, char *));
extern int imap4d_authenticate __P ((struct imap4d_command *, char *));
extern int imap4d_login __P ((struct imap4d_command *, char *));
extern int imap4d_select __P ((struct imap4d_command *, char *));
extern int imap4d_select0 __P ((struct imap4d_command *, char *, int));
extern int imap4d_examine __P ((struct imap4d_command *, char *));
extern int imap4d_create __P ((struct imap4d_command *, char *));
extern int imap4d_delete __P ((struct imap4d_command *, char *));
extern int imap4d_rename __P ((struct imap4d_command *, char *));
extern int imap4d_subscribe __P ((struct imap4d_command *, char *));
extern int imap4d_unsubscribe __P ((struct imap4d_command *, char *));
extern int imap4d_list __P ((struct imap4d_command *, char *));
extern int imap4d_lsub __P ((struct imap4d_command *, char *));
extern int imap4d_status __P ((struct imap4d_command *, char *));
extern int imap4d_append __P ((struct imap4d_command *, char *));
extern int imap4d_check __P ((struct imap4d_command *, char *));
extern int imap4d_close __P ((struct imap4d_command *, char *));
extern int imap4d_expunge __P ((struct imap4d_command *, char *));
extern int imap4d_search __P ((struct imap4d_command *, char *));
extern int imap4d_fetch __P ((struct imap4d_command *, char *));
extern int imap4d_store __P ((struct imap4d_command *, char *));
extern int imap4d_copy __P ((struct imap4d_command *, char *));
extern int imap4d_uid __P ((struct imap4d_command *, char *));
/* Helper functions. */
int util_out __P ((int rc, const char *f, ...));
int util_send __P ((const char *f, ...));
int util_start __P ((char *tag));
int util_finish __P ((struct imap4d_command *, int sc, const char *f, ...));
int util_getstate __P ((void));
int util_do_command __P ((char *prompt));
char *imap4d_readline __P ((int fd));
void util_quit __P ((int));
char *util_getword __P ((char *s, char **save_ptr));
int util_token __P ((char *s, size_t, char **save_ptr));
int util_msgset __P ((char *s, int **set, int *n, int isuid));
int util_upper __P ((char *));
struct imap4d_command *util_getcommand __P ((char *cmd,
extern int util_out __P ((int, const char *, ...));
extern int util_send __P ((const char *, ...));
extern int util_start __P ((char *));
extern int util_finish __P ((struct imap4d_command *, int, const char *, ...));
extern int util_getstate __P ((void));
extern int util_do_command __P ((char *));
extern char *imap4d_readline __P ((int));
extern void util_quit __P ((int));
extern char *util_getword __P ((char *, char **));
extern int util_token __P ((char *, size_t, char **));
extern void util_unquote __P ((char **));
extern char *util_tilde_expansion __P ((const char *, const char *));
extern char *util_getfullpath __P ((char *, const char *));
extern int util_msgset __P ((char *, int **, int *, int));
extern int util_upper __P ((char *));
extern struct imap4d_command *util_getcommand __P ((char *,
struct imap4d_command []));
#ifdef __cplusplus
......
......@@ -24,7 +24,109 @@
int
imap4d_rename (struct imap4d_command *command, char *arg)
{
char *oldname;
char *newname;
char *sp = NULL;
int rc = RESP_OK;
const char *msg = "Completed";
struct stat newst;
const char *delim = "/";
if (! (command->states & state))
return util_finish (command, RESP_BAD, "Wrong state");
return util_finish (command, RESP_NO, "Not Supported");
oldname = util_getword (arg, &sp);
newname = util_getword (NULL, &sp);
if (!newname || !oldname)
return util_finish (command, RESP_BAD, "Too few arguments");
util_unquote (&newname);
util_unquote (&oldname);
if (*newname == '\0' || *oldname == '\0')
return util_finish (command, RESP_BAD, "Too few arguments");
if (strcasecmp (newname, "INBOX") == 0)
return util_finish (command, RESP_NO, "Name Inbox is reservered");
/* Allocates memory. */
newname = util_getfullpath (newname, delim);
/* It is an error to attempt to rename from a mailbox name that already
exist. */
if (stat (newname, &newst) == 0)
{
if (!S_ISDIR(newst.st_mode))
{
free (newname);
return util_finish (command, RESP_NO, "Already exist, delete first");
}
}
/* Renaming INBOX is permitted, and has special behavior. It moves
all messages in INBOX to a new mailbox with the given name,
leaving INBOX empty. */
if (strcasecmp (oldname, "INBOX") == 0)
{
mailbox_t newmbox = NULL;
char *name;
struct passwd *pw;
if (S_ISDIR(newst.st_mode))
{
free (newname);
return util_finish (command, RESP_NO, "Can not be a directory");
}
name = calloc (strlen ("mbox:") + strlen (newname) + 1, 1);
sprintf (name, "mbox:%s", newname);
if (mailbox_create (&newmbox, newname) != 0
|| mailbox_open (newmbox, MU_STREAM_CREAT | MU_STREAM_RDWR) != 0)
{
free (name);
free (newname);
return util_finish (command, RESP_NO, "Can not create new mailbox");
}
free (name);
free (newname);
pw = getpwuid (getuid ());
if (pw)
{
mailbox_t inbox = NULL;
if (mailbox_create_default (&inbox, pw->pw_name) == 0 &&
mailbox_open (inbox, MU_STREAM_RDWR) == 0)
{
size_t no;
size_t total = 0;
mailbox_messages_count (inbox, &total);
for (no = 1; no <= total; no++)
{
message_t message;
if (mailbox_get_message (inbox, no, &message) == 0)
{
attribute_t attr = NULL;
mailbox_append_message (newmbox, message);
message_get_attribute (message, &attr);
attribute_set_deleted (attr);
}
}
mailbox_expunge (inbox);
mailbox_close (inbox);
mailbox_destroy (&inbox);
}
}
mailbox_close (newmbox);
mailbox_destroy (&newmbox);
return util_finish (command, RESP_OK, "Already exist");
}
oldname = util_getfullpath (oldname, delim);
/* It must exist. */
if (rename (oldname, newname) != 0)
{
rc = RESP_NO;
msg = "Failed";
}
free (oldname);
free (newname);
return util_finish (command, rc, msg);
}
......
......@@ -58,6 +58,9 @@ util_token (char *buf, size_t len, char **ptr)
/* Skip leading space. */
while (**ptr && **ptr == ' ')
(*ptr)++;
/* Break the string by token, i.e when we reconize IMAP special
atoms we stop and send it. */
for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++)
{
if (**ptr == ' ' || **ptr == '.'
......@@ -76,7 +79,82 @@ util_token (char *buf, size_t len, char **ptr)
/* Skip trailing space. */
while (**ptr && **ptr == ' ')
(*ptr)++;
return *ptr - start;;
return *ptr - start;
}
/* Remove the surrounding double quotes. */
void
util_unquote (char **ptr)
{
char *s = *ptr;
if (*s == '"')
{
char *p = ++s;
while (*p && *p != '"')
p++;
if (*p == '"')
*p = '\0';
}
*ptr = s;
}
/* NOTE: Allocates Memory. */
/* Expand: ~ --> /home/user and to ~guest --> /home/guest. */
char *
util_tilde_expansion (const char *ref, const char *delim)
{
char *p = strdup (ref);
if (*p == '~')
{
p++;
if (*p == delim[0] || *p == '\0')
{
char *s = calloc (strlen (homedir) + strlen (p) + 1, 1);
strcpy (s, homedir);
strcat (s, p);
free (--p);
p = s;
}
else
{
struct passwd *pw;
char *s = p;
char *name;
while (*s && *s != delim[0])
s++;
name = calloc (s - p + 1, 1);
memcpy (name, p, s - p);
name [s - p] = '\0';
pw = getpwnam (name);
free (name);
if (pw)
{
char *buf = calloc (strlen (pw->pw_dir) + strlen (s) + 1, 1);
strcpy (buf, pw->pw_dir);
strcat (buf, s);
free (--p);
p = buf;
}
else
p--;
}
}
return p;
}
/* Absolute path. */
char *
util_getfullpath (char *name, const char *delim)
{
char *p = util_tilde_expansion (name, delim);
if (*p != delim[0])
{
char *s = calloc (strlen (homedir) + strlen (delim) + strlen (p) + 1, 1);
sprintf (s, "%s%s%s", homedir, delim, p);
free (p);
p = s;
}
return p;
}
/* Return in set an allocated array contain (n) numbers, for imap messsage set
......
......@@ -346,7 +346,7 @@ int message_unencapsulate(message_t msg, message_t *newmsg, void **data)
if ( ( content_type = alloca(size+1) ) == NULL )
return ENOMEM;
header_get_value(hdr, "Content-Type", content_type, size+1, 0);
if ( strncasecmp(content_type, "message/rfc822", strlen(content_type)) != 0 )
if ( strncasecmp(content_type, "message/rfc822", strlen("message/rfc822")) != 0 )
return EINVAL;
} else
return EINVAL;
......
......@@ -1533,6 +1533,7 @@ imap_token (char *buf, size_t len, char **ptr)
/* Skip leading space. */
while (**ptr && **ptr == ' ')
(*ptr)++;
/* Break the string by token, when we recognise Atoms we stop. */
for (i = 1; **ptr && i < len; (*ptr)++, buf++, i++)
{
if (**ptr == ' ' || **ptr == '.'
......