diff options
Diffstat (limited to 'camel/providers/imap/camel-imap-utils.c')
-rw-r--r-- | camel/providers/imap/camel-imap-utils.c | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c index a557f7fcae..06028ef79d 100644 --- a/camel/providers/imap/camel-imap-utils.c +++ b/camel/providers/imap/camel-imap-utils.c @@ -30,6 +30,10 @@ #include <string.h> #include <time.h> #include <errno.h> +#include <sys/types.h> +#include <dirent.h> +#include <sys/stat.h> +#include <unistd.h> #include "camel-imap-utils.h" #include "camel-imap-summary.h" @@ -40,6 +44,9 @@ #define d(x) +#define SUBFOLDER_DIR_NAME "subfolders" +#define SUBFOLDER_DIR_NAME_LEN 10 + const char * imap_next_word (const char *buf) { @@ -1263,3 +1270,160 @@ imap_mailbox_decode (const unsigned char *in, size_t inlen) return camel_utf7_utf8 (buf); } + +char * +imap_path_to_physical (const char *prefix, const char *vpath) +{ + const char *p, *newp; + char *dp; + char *ppath; + int ppath_len; + int prefix_len; + + while (*vpath == '/') + vpath++; + if (!prefix) + prefix = ""; + + /* Calculate the length of the real path. */ + ppath_len = strlen (vpath); + ppath_len++; /* For the ending zero. */ + + prefix_len = strlen (prefix); + ppath_len += prefix_len; + ppath_len++; /* For the separating slash. */ + + /* Take account of the fact that we need to translate every + * separator into `subfolders/'. + */ + p = vpath; + while (1) { + newp = strchr (p, '/'); + if (newp == NULL) + break; + + ppath_len += SUBFOLDER_DIR_NAME_LEN; + ppath_len++; /* For the separating slash. */ + + /* Skip consecutive slashes. */ + while (*newp == '/') + newp++; + + p = newp; + }; + + ppath = g_malloc (ppath_len); + dp = ppath; + + memcpy (dp, prefix, prefix_len); + dp += prefix_len; + *(dp++) = '/'; + + /* Copy the mangled path. */ + p = vpath; + while (1) { + newp = strchr (p, '/'); + if (newp == NULL) { + strcpy (dp, p); + break; + } + + memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ + dp += newp - p + 1; + + memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); + dp += SUBFOLDER_DIR_NAME_LEN; + + *(dp++) = '/'; + + /* Skip consecutive slashes. */ + while (*newp == '/') + newp++; + + p = newp; + } + + return ppath; +} + +static gboolean +find_folders_recursive (const char *physical_path, const char *path, + IMAPPathFindFoldersCallback callback, gpointer data) +{ + DIR *dir; + char *subfolder_directory_path; + gboolean ok; + + if (*path) { + if (!callback (physical_path, path, data)) + return FALSE; + + subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME); + } else { + /* On the top level, we have no folders and, + * consequently, no subfolder directory. + */ + + subfolder_directory_path = g_strdup (physical_path); + } + + /* Now scan the subfolders and load them. */ + dir = opendir (subfolder_directory_path); + if (dir == NULL) { + g_free (subfolder_directory_path); + return TRUE; + } + + ok = TRUE; + while (ok) { + struct stat file_stat; + struct dirent *dirent; + char *file_path; + char *new_path; + + dirent = readdir (dir); + if (dirent == NULL) + break; + + if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0) + continue; + + file_path = g_strdup_printf ("%s/%s", subfolder_directory_path, + dirent->d_name); + + if (stat (file_path, &file_stat) < 0 || + ! S_ISDIR (file_stat.st_mode)) { + g_free (file_path); + continue; + } + + new_path = g_strdup_printf ("%s/%s", path, dirent->d_name); + + ok = find_folders_recursive (file_path, new_path, callback, data); + + g_free (file_path); + g_free (new_path); + } + + closedir (dir); + g_free (subfolder_directory_path); + + return ok; +} + +/** + * imap_path_find_folders: + * @prefix: directory to start from + * @callback: Callback to invoke on each folder + * @data: Data for @callback + * + * Walks the folder tree starting at @prefix and calls @callback + * on each folder. + * + * Return value: %TRUE on success, %FALSE if an error occurs at any point + **/ +gboolean +imap_path_find_folders (const char *prefix, IMAPPathFindFoldersCallback callback, gpointer data) +{ + return find_folders_recursive (prefix, "", callback, data); +} |