aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap/camel-imap-utils.c')
-rw-r--r--camel/providers/imap/camel-imap-utils.c164
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);
+}