summaryrefslogtreecommitdiff
path: root/mailbox/mbox/folder.c
diff options
context:
space:
mode:
Diffstat (limited to 'mailbox/mbox/folder.c')
-rw-r--r--mailbox/mbox/folder.c427
1 files changed, 427 insertions, 0 deletions
diff --git a/mailbox/mbox/folder.c b/mailbox/mbox/folder.c
new file mode 100644
index 000000000..6568ab36a
--- /dev/null
+++ b/mailbox/mbox/folder.c
@@ -0,0 +1,427 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <glob.h>
+#include <fnmatch.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <folder0.h>
+#include <registrar0.h>
+
+#include <mailutils/auth.h>
+#include <mailutils/url.h>
+#include <mailutils/stream.h>
+
+/* We export url parsing and the initialisation of
+ the mailbox, via the register entry/record. */
+
+static struct _record _mbox_record =
+{
+ MU_MBOX_SCHEME,
+ _url_mbox_init, /* Mailbox init. */
+ _mailbox_mbox_init, /* Mailbox init. */
+ NULL, /* Mailer init. */
+ _folder_mbox_init, /* Folder init. */
+ NULL, /* No need for an back pointer. */
+ NULL, /* _is_scheme method. */
+ NULL, /* _get_url method. */
+ NULL, /* _get_mailbox method. */
+ NULL, /* _get_mailer method. */
+ NULL /* _get_folder method. */
+};
+record_t mbox_record = &_mbox_record;
+
+static struct _record _file_record =
+{
+ MU_FILE_SCHEME,
+ _url_file_init, /* Mailbox init. */
+ _mailbox_file_init, /* Mailbox init. */
+ NULL, /* Mailer init. */
+ _folder_mbox_init, /* Folder init. */
+ NULL, /* No need for an owner. */
+ NULL, /* _is_scheme method. */
+ NULL, /* _get_url method. */
+ NULL, /* _get_mailbox method. */
+ NULL, /* _get_mailer method. */
+ NULL /* _get_folder method. */
+};
+record_t file_record = &_file_record;
+
+static struct _record _path_record =
+{
+ MU_PATH_SCHEME,
+ _url_path_init, /* Mailbox init. */
+ _mailbox_file_init, /* Mailbox init. */
+ NULL, /* Mailer init. */
+ _folder_mbox_init, /* Folder init. */
+ NULL, /* No need for an owner. */
+ NULL, /* is_scheme method. */
+ NULL, /* get_url method. */
+ NULL, /* get_mailbox method. */
+ NULL, /* get_mailer method. */
+ NULL /* get_folder method. */
+};
+record_t path_record = &_path_record;
+
+/* lsub/subscribe/unsubscribe are not needed. */
+static void folder_mbox_destroy __P ((folder_t));
+static int folder_mbox_open __P ((folder_t, int));
+static int folder_mbox_close __P ((folder_t));
+static int folder_mbox_delete __P ((folder_t, const char *));
+static int folder_mbox_rename __P ((folder_t , const char *,
+ const char *));
+static int folder_mbox_list __P ((folder_t, const char *, const char *,
+ struct folder_list *));
+static int folder_mbox_subscribe __P ((folder_t, const char *));
+static int folder_mbox_unsubscribe __P ((folder_t, const char *));
+static int folder_mbox_lsub __P ((folder_t, const char *, const char *,
+ struct folder_list *));
+
+
+static char *get_pathname __P ((const char *, const char *));
+
+static int folder_mbox_get_authority __P ((folder_t folder,
+ authority_t * pauth));
+
+struct _fmbox
+{
+ char *dirname;
+ char **subscribe;
+ size_t sublen;
+};
+typedef struct _fmbox *fmbox_t;
+
+
+int
+_folder_mbox_init (folder_t folder)
+{
+ fmbox_t dfolder;
+ size_t name_len = 0;
+ int status = 0;
+
+ /* We create an authority so the API is uniform across the mailbox
+ types. */
+ status = folder_mbox_get_authority (folder, NULL);
+ if (status != 0)
+ return status;
+
+ dfolder = folder->data = calloc (1, sizeof (*dfolder));
+ if (dfolder == NULL)
+ return ENOMEM;
+
+ url_get_path (folder->url, NULL, 0, &name_len);
+ dfolder->dirname = calloc (name_len + 1, sizeof (char));
+ if (dfolder->dirname == NULL)
+ {
+ free (dfolder);
+ folder->data = NULL;
+ return ENOMEM;
+ }
+ url_get_path (folder->url, dfolder->dirname, name_len + 1, NULL);
+
+ folder->_destroy = folder_mbox_destroy;
+
+ folder->_open = folder_mbox_open;
+ folder->_close = folder_mbox_close;
+
+ folder->_list = folder_mbox_list;
+ folder->_lsub = folder_mbox_lsub;
+ folder->_subscribe = folder_mbox_subscribe;
+ folder->_unsubscribe = folder_mbox_unsubscribe;
+ folder->_delete = folder_mbox_delete;
+ folder->_rename = folder_mbox_rename;
+ return 0;
+}
+
+void
+folder_mbox_destroy (folder_t folder)
+{
+ if (folder->data)
+ {
+ fmbox_t fmbox = folder->data;
+ if (fmbox->dirname)
+ free (fmbox->dirname);
+ if (fmbox->subscribe)
+ free (fmbox->subscribe);
+ free (folder->data);
+ folder->data = NULL;
+ }
+}
+
+/* Noop. */
+static int
+folder_mbox_open (folder_t folder, int flags)
+{
+ fmbox_t fmbox = folder->data;
+ if (flags & MU_STREAM_CREAT)
+ {
+ return (mkdir (fmbox->dirname, S_IRWXU) == 0) ? 0 : errno;
+ }
+ (void)(flags);
+ return 0;
+}
+
+/* Noop. */
+static int
+folder_mbox_close (folder_t folder)
+{
+ (void)(folder);
+ return 0;
+}
+
+static int
+folder_mbox_delete (folder_t folder, const char *filename)
+{
+ fmbox_t fmbox = folder->data;
+ if (filename)
+ {
+ int status = 0;
+ char *pathname = get_pathname (fmbox->dirname, filename);
+ if (pathname)
+ {
+ if (remove (pathname) != 0)
+ status = errno;
+ free (pathname);
+ }
+ else
+ status = ENOMEM;
+ return status;
+ }
+ return EINVAL;
+}
+
+static int
+folder_mbox_rename (folder_t folder, const char *oldpath, const char *newpath)
+{
+ fmbox_t fmbox = folder->data;
+ if (oldpath && newpath)
+ {
+ int status = 0;
+ char *pathold = get_pathname (fmbox->dirname, oldpath);
+ if (pathold)
+ {
+ char *pathnew = get_pathname (fmbox->dirname, newpath);
+ if (pathnew)
+ {
+ if (rename (pathold, pathnew) != 0)
+ status = errno;
+ free (pathnew);
+ }
+ else
+ status = ENOMEM;
+ free (pathold);
+ }
+ else
+ status = ENOMEM;
+ return status;
+ }
+ return EINVAL;
+}
+
+/* The listing is not recursif and we use glob() some expansion for us.
+ 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,
+ struct folder_list *pflist)
+{
+ fmbox_t fmbox = folder->data;
+ char *pathname = NULL;
+ int status;
+ size_t num = 0;
+ glob_t gl;
+
+ if (dirname == NULL || dirname[0] == '\0')
+ dirname = (const char *)fmbox->dirname;
+
+ pathname = get_pathname (dirname, pattern);
+ if (pathname)
+ {
+ memset(&gl, 0, sizeof(gl));
+ status = glob (pathname, 0, NULL, &gl);
+ free (pathname);
+ num = gl.gl_pathc;
+ }
+ else
+ status = ENOMEM;
+
+ /* Build the folder list from glob. */
+ if (status == 0)
+ {
+ if (pflist)
+ {
+ struct list_response **plist;
+ plist = calloc (num, sizeof (*plist));
+ if (plist)
+ {
+ size_t i;
+ struct stat stbuf;
+ for (i = 0; i < num; i++)
+ {
+ plist[i] = calloc (1, sizeof (**plist));
+ if (plist[i] == NULL
+ || (plist[i]->name = strdup (gl.gl_pathv[i])) == NULL)
+ {
+ num = i;
+ break;
+ }
+ if (stat (gl.gl_pathv[i], &stbuf) == 0)
+ {
+ if (S_ISDIR(stbuf.st_mode))
+ plist[i]->type = MU_FOLDER_ATTRIBUTE_DIRECTORY;
+ if (S_ISREG(stbuf.st_mode))
+ plist[i]->type = MU_FOLDER_ATTRIBUTE_FILE;
+ }
+ plist[i]->separator = '/';
+ }
+ }
+ pflist->element = plist;
+ pflist->num = num;
+ }
+ globfree (&gl);
+ }
+ else
+ {
+ status = (status == GLOB_NOSPACE) ? ENOMEM : EINVAL;
+ }
+ return status;
+}
+
+static int
+folder_mbox_lsub (folder_t folder, const char *ref, const char *name,
+ struct folder_list *pflist)
+{
+ fmbox_t fmbox = folder->data;
+ size_t j = 0;
+
+ if (pflist == NULL)
+ return EINVAL;
+
+ (void)ref;
+ if (name == NULL || *name == '\0')
+ name = "*";
+
+ if (fmbox->sublen > 0)
+ {
+ struct list_response **plist;
+ size_t i;
+ plist = calloc (fmbox->sublen, sizeof (*plist));
+ for (i = 0; i < fmbox->sublen; i++)
+ {
+ if (fmbox->subscribe[i]
+ && fnmatch (name, fmbox->subscribe[i], 0) == 0)
+ {
+ plist[i] = calloc (1, sizeof (**plist));
+ if (plist[i] == NULL
+ || (plist[i]->name = strdup (fmbox->subscribe[i])) == NULL)
+ break;
+ plist[i]->type = MU_FOLDER_ATTRIBUTE_FILE;
+ plist[i]->separator = '/';
+ j++;
+ }
+ }
+ pflist->element = plist;
+ }
+ pflist->num = j;
+ return 0;
+}
+
+static int
+folder_mbox_subscribe (folder_t folder, const char *name)
+{
+ fmbox_t fmbox = folder->data;
+ char **tmp;
+ size_t i;
+ for (i = 0; i < fmbox->sublen; i++)
+ {
+ if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
+ return 0;
+ }
+ tmp = realloc (fmbox->subscribe, (fmbox->sublen + 1) * sizeof (*tmp));
+ if (tmp == NULL)
+ return ENOMEM;
+ fmbox->subscribe = tmp;
+ fmbox->subscribe[fmbox->sublen] = strdup (name);
+ if (fmbox->subscribe[fmbox->sublen] == NULL)
+ return ENOMEM;
+ fmbox->sublen++;
+ return 0;
+}
+
+static int
+folder_mbox_unsubscribe (folder_t folder, const char *name)
+{
+ fmbox_t fmbox = folder->data;
+ size_t i;
+ for (i = 0; i < fmbox->sublen; i++)
+ {
+ if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
+ {
+ free (fmbox->subscribe[i]);
+ fmbox->subscribe[i] = NULL;
+ return 0;
+ }
+ }
+ return ENOENT;
+}
+
+static char *
+get_pathname (const char *dirname, const char *basename)
+{
+ char *pathname = NULL;
+ /* null basename gives dirname. */
+ if (basename == NULL)
+ pathname = (dirname) ? strdup (dirname) : strdup (".");
+ /* Absolute. */
+ else if (basename[0] == '/')
+ pathname = strdup (basename);
+ /* Relative. */
+ else
+ {
+ size_t len = strlen (basename);
+ pathname = calloc (strlen (dirname) + len + 2, sizeof (char));
+ if (pathname)
+ sprintf (pathname, "%s/%s", dirname, basename);
+ }
+ return pathname;
+}
+
+static int
+folder_mbox_get_authority (folder_t folder, authority_t *pauth)
+{
+ int status = 0;
+ if (folder->authority == NULL)
+ {
+ status = authority_create_null (&folder->authority, folder);
+ }
+ if (!status && pauth)
+ *pauth = folder->authority;
+ return status;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.