aboutsummaryrefslogtreecommitdiffstats
path: root/mail/upgrade-mailer.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/upgrade-mailer.c')
-rw-r--r--mail/upgrade-mailer.c295
1 files changed, 259 insertions, 36 deletions
diff --git a/mail/upgrade-mailer.c b/mail/upgrade-mailer.c
index 42bdd27ca6..aa9127378e 100644
--- a/mail/upgrade-mailer.c
+++ b/mail/upgrade-mailer.c
@@ -34,6 +34,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <dirent.h>
#include <errno.h>
#include <ctype.h>
@@ -41,6 +42,7 @@
#include <bonobo-conf/bonobo-config-database.h>
#include <camel/camel-file-utils.h>
+#include <camel/camel-store.h>
struct _storeinfo {
char *base_url;
@@ -84,9 +86,8 @@ find_dir_sep (const char *lsub_response)
}
static void
-si_free (gpointer key, gpointer val, gpointer user_data)
+si_free (struct _storeinfo *si)
{
- struct _storeinfo *si = val;
int i;
g_free (si->base_url);
@@ -99,38 +100,6 @@ si_free (gpointer key, gpointer val, gpointer user_data)
g_free (si);
}
-static char *
-get_base_url (const char *protocol, const char *uri)
-{
- unsigned char *base_url, *p;
-
- p = (unsigned char *) uri + strlen (protocol) + 1;
- if (!strncmp (p, "//", 2))
- p += 2;
-
- base_url = p;
- p = strchr (p, '/');
- base_url = g_strdup_printf ("%s://%.*s", protocol, p ? (int) (p - base_url) : (int) strlen (base_url), base_url);
-
- return base_url;
-}
-
-static char *
-imap_namespace (const char *uri)
-{
- unsigned char *name, *p;
-
- if ((name = strstr (uri, ";namespace=\"")) == NULL)
- return NULL;
-
- name += strlen (";namespace=\"");
- p = name;
- while (*p && *p != '\"')
- p++;
-
- return g_strndup (name, p - name);
-}
-
static unsigned char tohex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
@@ -190,6 +159,259 @@ hex_decode (const char *in, size_t len)
}
static char *
+parse_lsub (const char *lsub, char *dir_sep)
+{
+ const unsigned char *inptr = (const unsigned char *) lsub;
+ const unsigned char *inend;
+ int inlen, quoted = 0;
+
+ inend = inptr + strlen (inptr);
+ if (strncmp (inptr, "* LSUB (", 8))
+ return NULL;
+
+ inptr += 8;
+ while (inptr < inend && *inptr != ')')
+ inptr++;
+
+ if (inptr >= inend)
+ return NULL;
+
+ inptr++;
+ while (inptr < inend && isspace ((int) *inptr))
+ inptr++;
+
+ if (inptr >= inend)
+ return NULL;
+
+ /* skip over the dir sep */
+ if (*inptr == '\"')
+ inptr++;
+
+ *dir_sep = (char) *inptr++;
+ if (*inptr == '\"')
+ inptr++;
+
+ if (inptr >= inend)
+ return NULL;
+
+ while (inptr < inend && isspace ((int) *inptr))
+ inptr++;
+
+ if (inptr >= inend)
+ return NULL;
+
+ if (*inptr == '\"') {
+ inptr++;
+ quoted = 1;
+ } else
+ quoted = 0;
+
+ inlen = strlen (inptr) - quoted;
+
+ return g_strndup (inptr, inlen);
+}
+
+static void
+cache_upgrade (struct _storeinfo *si, const char *folder_name)
+{
+ const char *old_folder_name = folder_name;
+ char *oldpath, *newpath, *p;
+ struct dirent *dent;
+ DIR *dir = NULL;
+
+ if (si->namespace && strcmp ("INBOX", folder_name)) {
+ if (!strncmp (old_folder_name, si->namespace, strlen (si->namespace))) {
+ old_folder_name += strlen (si->namespace);
+ if (*old_folder_name == si->dir_sep)
+ old_folder_name++;
+ }
+ }
+
+ oldpath = g_strdup_printf ("%s/evolution/mail/imap/%s/%s", getenv ("HOME"),
+ si->base_url + 7, old_folder_name);
+
+ newpath = g_strdup_printf ("%s/evolution/mail/imap/%s/folders/%s",
+ getenv ("HOME"), si->base_url + 7, folder_name);
+
+ if (!strcmp (folder_name, "folders"))
+ goto special_case_folders;
+
+ if (si->dir_sep != '/') {
+ p = newpath + strlen (newpath) - strlen (folder_name) - 1;
+ while (*p) {
+ if (*p == si->dir_sep)
+ *p = '/';
+ p++;
+ }
+ }
+
+ /* make sure all parent directories exist */
+ if ((p = strrchr (newpath, '/'))) {
+ *p = '\0';
+ camel_mkdir_hier (newpath, 0755);
+ *p = '/';
+ }
+
+ if (rename (oldpath, newpath) == -1) {
+ fprintf (stderr, "Failed to upgrade cache for imap folder %s/%s: %s\n",
+ si->base_url, folder_name, g_strerror (errno));
+ }
+
+ g_free (oldpath);
+ g_free (newpath);
+
+ return;
+
+ special_case_folders:
+
+ /* the user had a toplevel folder named "folders" */
+ if (camel_mkdir_hier (newpath, 0755) == -1) {
+ /* we don't bother to check EEXIST because well, if
+ folders/folders exists then we're pretty much
+ fucked */
+ goto exception;
+ }
+
+ if (!(dir = opendir (oldpath)))
+ goto exception;
+
+ while ((dent = readdir (dir))) {
+ char *old_path, *new_path;
+
+ if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, ".."))
+ continue;
+
+ old_path = g_strdup_printf ("%s/%s", oldpath, dent->d_name);
+ new_path = g_strdup_printf ("%s/%s", newpath, dent->d_name);
+
+ /* make sure all parent directories exist */
+ if ((p = strrchr (new_path, '/'))) {
+ *p = '\0';
+ camel_mkdir_hier (new_path, 0755);
+ *p = '/';
+ }
+
+ if (rename (old_path, new_path) == -1) {
+ g_free (old_path);
+ g_free (new_path);
+ goto exception;
+ }
+
+ g_free (old_path);
+ g_free (new_path);
+ }
+
+ closedir (dir);
+
+ g_free (oldpath);
+ g_free (newpath);
+
+ return;
+
+ exception:
+
+ fprintf (stderr, "Failed to upgrade cache for imap folder %s/%s: %s\n",
+ si->base_url, folder_name, g_strerror (errno));
+
+ if (dir)
+ closedir (dir);
+
+ g_free (oldpath);
+ g_free (newpath);
+}
+
+static int
+foldercmp (const void *f1, const void *f2)
+{
+ const char **folder1 = f1;
+ const char **folder2 = f2;
+
+ return strcmp (*folder1, *folder2);
+}
+
+static void
+cache_upgrade_and_free (gpointer key, gpointer val, gpointer user_data)
+{
+ struct _storeinfo *si = val;
+ GPtrArray *folders;
+ char *path = NULL;
+ char dir_sep;
+ int i;
+
+ if (si->folders) {
+ path = g_strdup_printf ("%s/evolution/mail/imap/%s/folders",
+ getenv ("HOME"), si->base_url + 7);
+
+ if (mkdir (path, 0755) == -1 && errno != EEXIST) {
+ fprintf (stderr, "Failed to create directory %s: %s", path, g_strerror (errno));
+ goto exception;
+ }
+
+ g_free (path);
+ folders = g_ptr_array_new ();
+ for (i = 0; i < si->folders->len; i++) {
+ if ((path = parse_lsub (si->folders->pdata[i], &dir_sep))) {
+ g_ptr_array_add (folders, path);
+ }
+ }
+
+ /* sort the folders so that parents get created before
+ their children */
+ qsort (folders->pdata, folders->len, sizeof (void *), foldercmp);
+
+ for (i = 0; i < folders->len; i++) {
+ cache_upgrade (si, folders->pdata[i]);
+ g_free (folders->pdata[i]);
+ }
+ }
+
+ si_free (si);
+
+ return;
+
+ exception:
+
+ fprintf (stderr, "Could not upgrade imap cache for %s: %s\n",
+ si->base_url + 7, g_strerror (errno));
+
+ g_free (path);
+
+ si_free (si);
+}
+
+static char *
+get_base_url (const char *protocol, const char *uri)
+{
+ unsigned char *base_url, *p;
+
+ p = (unsigned char *) uri + strlen (protocol) + 1;
+ if (!strncmp (p, "//", 2))
+ p += 2;
+
+ base_url = p;
+ p = strchr (p, '/');
+ base_url = g_strdup_printf ("%s://%.*s", protocol, p ? (int) (p - base_url) : (int) strlen (base_url), base_url);
+
+ return base_url;
+}
+
+static char *
+imap_namespace (const char *uri)
+{
+ unsigned char *name, *p;
+
+ if ((name = strstr (uri, ";namespace=\"")) == NULL)
+ return NULL;
+
+ name += strlen (";namespace=\"");
+ p = name;
+ while (*p && *p != '\"')
+ p++;
+
+ return g_strndup (name, p - name);
+}
+
+static char *
find_folder (GPtrArray *folders, const char *folder, char *dir_sep)
{
const unsigned char *inptr, *inend;
@@ -926,9 +1148,9 @@ mailer_upgrade (Bonobo_ConfigDatabase db)
shortcuts_upgrade_xml_file (accounts, imap_sources, path);
g_free (path);
- g_hash_table_foreach (imap_sources, si_free, NULL);
+ g_hash_table_foreach (imap_sources, cache_upgrade_and_free, NULL);
g_hash_table_destroy (imap_sources);
-
+#if 0
path = g_strdup_printf ("%s/evolution/mail/imap", getenv ("HOME"));
bak = g_strdup_printf ("%s.bak-1.0", path);
@@ -937,6 +1159,7 @@ mailer_upgrade (Bonobo_ConfigDatabase db)
g_free (path);
g_free (bak);
+#endif
return 0;
}