aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@src.gnome.org>2000-05-28 05:57:41 +0800
committerJeffrey Stedfast <fejj@src.gnome.org>2000-05-28 05:57:41 +0800
commitd8c5c9136dbbb3e42f14701bdcadceab40d5171f (patch)
tree8b97429f2b75ff473e49fc9552469ccc8d559428 /camel
parentd206a2e89b5efb9373e3a99cf4cb28fd04986a8a (diff)
downloadgsoc2013-evolution-d8c5c9136dbbb3e42f14701bdcadceab40d5171f.tar.gz
gsoc2013-evolution-d8c5c9136dbbb3e42f14701bdcadceab40d5171f.tar.zst
gsoc2013-evolution-d8c5c9136dbbb3e42f14701bdcadceab40d5171f.zip
Ripped out camel_imap_command_get_additional_data() from camel-imap-store and implemented a number of methods in camel-imap-folder
svn path=/trunk/; revision=3233
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog17
-rw-r--r--camel/providers/imap/camel-imap-folder.c301
-rw-r--r--camel/providers/imap/camel-imap-folder.h3
-rw-r--r--camel/providers/imap/camel-imap-store.c100
-rw-r--r--camel/providers/imap/camel-imap-store.h3
5 files changed, 272 insertions, 152 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index c9e7424a50..b9a2c775dc 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,18 @@
+2000-05-27 Jeffrey Stedfast <fejj@helixcode.com>
+
+ * providers/imap/camel-imap-store.c: Removed
+ camel_imap_command_get_additional_data() as it was
+ completely useless, replaced with
+ camel_imap_command_extended() which may eventually replace
+ camel_imap_command() as well.
+
+ * providers/imap/camel-imap-store.h: Modified to reflect
+ changes made to camel-imap-store.c
+
+ * providers/imap/camel-imap-folder.c: Wrote the first of many
+ methods: camel_imap_init(), imap_open(), imap_expunge(),
+ imap_get_message_count(), and imap_get_subfolder_names()
+
2000-05-26 Dan Winship <danw@helixcode.com>
* camel-multipart.c (camel_multipart_init): Don't set a default
@@ -13,7 +28,7 @@
* providers/imap/camel-imap-store.c (try_connect): Removed
Exception code - Pop doesn't seem to set exceptions
- * providers/imap/camel-imap-folders.c: Initial code, mostly
+ * providers/imap/camel-imap-folder.c: Initial code, mostly
just a template for future code
* providers/imap/imap.[c,h]: Source code from my personal
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index 055978fa2b..e4ad9699fb 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -165,6 +165,7 @@ camel_imap_folder_get_type (void)
CamelFolder *
camel_imap_folder_new (CamelStore *parent, CamelException *ex)
{
+ /* TODO: code this */
CamelFolder *folder = CAMEL_FOLDER (gtk_object_new (camel_imap_folder_get_type (), NULL));
CF_CLASS (folder)->init (folder, parent, NULL, "inbox", '/', ex);
@@ -186,12 +187,11 @@ static void
imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_folder,
const gchar *name, gchar separator, CamelException *ex)
{
- CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
const gchar *root_dir_path;
/* call parent method */
- parent_class->init (folder, parent_store, parent_folder,
- name, separator, ex);
+ parent_class->init (folder, parent_store, parent_folder, name, separator, ex);
if (camel_exception_get_id (ex))
return;
@@ -199,15 +199,15 @@ imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_fo
method checks for the existance of @folder */
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
- folder->has_summary_capability = TRUE;
+ folder->has_summary_capability = FALSE; /* TODO: double-check this */
folder->has_search_capability = TRUE;
- folder->permanent_flags = CAMEL_MESSAGE_ANSWERED |
+ folder->permanent_flags = CAMEL_MESSAGE_SEEN |
+ CAMEL_MESSAGE_ANSWERED |
+ CAMEL_MESSAGE_FLAGGED |
CAMEL_MESSAGE_DELETED |
CAMEL_MESSAGE_DRAFT |
- CAMEL_MESSAGE_FLAGGED |
- CAMEL_MESSAGE_SEEN |
- CAMEL_MESSAGE_USER;
+ CAMEL_MESSAGE_USER; /* some IMAP daemons support user-flags */
imap_folder->summary = NULL;
imap_folder->search = NULL;
@@ -220,7 +220,6 @@ imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_fo
root_dir_path = camel_imap_store_get_toplevel_dir (CAMEL_IMAP_STORE(folder->parent_store));
imap_folder->folder_file_path = g_strdup_printf ("%s/%s", root_dir_path, folder->full_name);
- imap_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", root_dir_path, folder->full_name);
imap_folder->folder_dir_path = g_strdup_printf ("%s/%s.sdb", root_dir_path, folder->full_name);
imap_folder->index_file_path = g_strdup_printf ("%s/%s.ibex", root_dir_path, folder->full_name);
}
@@ -229,55 +228,70 @@ static void
imap_open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
-
- /* TODO: code this - I believe we want to SELECT */
+ gchar *result;
+ gint status;
+
+ camel_imap_store_open (CAMEL_IMAP_STORE (folder->parent_store), ex);
+ if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_NONE) {
+ /* do we actually want to do this? probably not */
+ parent_class->open (folder, mode, ex);
+
+ /* SELECT the IMAP mail spool */
+ status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), &result,
+ "SELECT %s", imap_folder->folder_file_path);
+
+ if (status != CAMEL_IMAP_OK) {
+ CamelService *service = CAMEL_SERVICE (folder->parent_store);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not SELECT %s on IMAP "
+ "server %s: %s.", imap_folder->folder_file_path,
+ service->url->host,
+ status == CAMEL_IMAP_ERR ? result :
+ "Unknown error");
+ g_free (result);
+ return -1;
+ }
+
+ g_free(result);
+ }
}
static void
imap_close (CamelFolder *folder, gboolean expunge, CamelException *ex)
{
- CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
-
- /* call parent implementation */
- parent_class->close (folder, expunge, ex);
-
- if (expunge) {
- imap_expunge(folder, ex);
- }
-
- /* save index */
- if (imap_folder->index) {
- ibex_close(imap_folder->index);
- imap_folder->index = NULL;
- }
- if (imap_folder->summary) {
- camel_folder_summary_save ((CamelFolderSummary *)imap_folder->summary);
- gtk_object_unref((GtkObject *)imap_folder->summary);
- imap_folder->summary = NULL;
- }
- if (imap_folder->search) {
- gtk_object_unref((GtkObject *)imap_folder->search);
- imap_folder->search = NULL;
- }
+ camel_imap_store_close (CAMEL_IMAP_STORE (folder->parent_store), expunge, ex);
+ if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_NONE)
+ parent_class->close (folder, expunge, ex);
}
static void
imap_expunge (CamelFolder *folder, CamelException *ex)
{
- CamelImapFolder *imap = (CamelImapFolder *)folder;
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ gchar *result;
+ gint status;
- if (camel_imap_summary_expunge(imap->summary) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, /* FIXME: right error code */
- "Could not expunge: %s", strerror(errno));
+ status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), &result,
+ "EXPUNGE");
+
+ if (status != CAMEL_IMAP_OK) {
+ CamelService *service = CAMEL_SERVICE (folder->parent_store);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not EXPUNGE from IMAP "
+ "server %s: %s.", service->url->host,
+ status == CAMEL_IMAP_ERR ? result :
+ "Unknown error");
+ g_free (result);
+ return -1;
}
-
- /* TODO: check it actually changed */
- gtk_signal_emit_by_name((GtkObject *)folder, "folder_changed", 0);
+
+ g_free(result);
}
static gboolean
imap_exists (CamelFolder *folder, CamelException *ex)
{
+ /* TODO: look at Mbox code and figure out exactly what needs to be done here */
CamelImapFolder *imap_folder;
struct stat stat_buf;
gint stat_error;
@@ -289,16 +303,14 @@ imap_exists (CamelFolder *folder, CamelException *ex)
/* check if the imap file path is determined */
if (!imap_folder->folder_file_path) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID,
+ camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
"undetermined folder file path. Maybe use set_name ?");
return FALSE;
}
/* check if the imap dir path is determined */
if (!imap_folder->folder_dir_path) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID,
+ camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
"undetermined folder directory path. Maybe use set_name ?");
return FALSE;
}
@@ -309,6 +321,7 @@ imap_exists (CamelFolder *folder, CamelException *ex)
static gboolean
imap_create (CamelFolder *folder, CamelException *ex)
{
+ /* NOTE: this should probably be pretty easy to code... */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
const gchar *folder_file_path, *folder_dir_path;
gboolean folder_already_exists;
@@ -323,8 +336,7 @@ imap_create (CamelFolder *folder, CamelException *ex)
folder_dir_path = imap_folder->folder_dir_path;
if (!(folder_file_path || folder_dir_path)) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID,
+ camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID,
"invalid folder path. Use set_name ?");
return FALSE;
}
@@ -347,44 +359,8 @@ imap_create (CamelFolder *folder, CamelException *ex)
static gboolean
imap_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
{
+ /* NOTE: should be pretty simple as well, just needa break out the RFC ;-) */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- const gchar *folder_file_path, *folder_dir_path;
- gint rmdir_error = 0;
- gint unlink_error = 0;
- gboolean folder_already_exists;
-
- g_assert(folder != NULL);
-
- /* check if the folder object exists
- * in the case where the folder does not exist,
- * return immediatly */
- folder_already_exists = camel_folder_exists (folder, ex);
- if (camel_exception_get_id (ex))
- return FALSE;
-
- if (!folder_already_exists)
- return TRUE;
-
-
- /* call default implementation.
- * It should delete the messages in the folder
- * and recurse the operation to subfolders */
- parent_class->delete (folder, recurse, ex);
-
-
- /* get the paths of what we need to be deleted */
- folder_file_path = imap_folder->folder_file_path;
- folder_dir_path = imap_folder->folder_file_path;
-
- if (!(folder_file_path || folder_dir_path)) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID,
- "invalid folder path. Use set_name ?");
- return FALSE;
- }
-
- /* physically delete the directory */
- /* TODO: actually code this */
return TRUE;
}
@@ -393,52 +369,57 @@ imap_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
gboolean
imap_delete_messages (CamelFolder *folder, CamelException *ex)
{
-
+ /* TODO: delete the messages (mark as deleted/whatever) */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
- const gchar *folder_file_path;
- gboolean folder_already_exists;
+ gchar *result;
+ gint status;
- g_assert(folder!=NULL);
-
- /* in the case where the folder does not exist,
- return immediatly */
- folder_already_exists = camel_folder_exists (folder, ex);
- if (camel_exception_get_id (ex))
- return FALSE;
-
- if (!folder_already_exists)
- return TRUE;
+ g_return_val_if_fail (folder != NULL, FALSE);
- /* get the paths of the imap file we need to delete */
- folder_file_path = imap_folder->folder_file_path;
-
- if (!folder_file_path) {
- camel_exception_set (ex,
- CAMEL_EXCEPTION_FOLDER_INVALID,
- "invalid folder path. Use set_name ?");
- return FALSE;
- }
-
-
- /* create the imap file */
- /* TODO: delete the messages (mark as deleted/whatever) */
-
return TRUE;
}
static gint
imap_get_message_count (CamelFolder *folder, CamelException *ex)
{
- CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ gint status;
+ gchar *result, *msg_count;
+
+ g_return_val_if_fail (folder != NULL, -1);
+
+ if (imap_folder->count != -1)
+ imap_folder->count;
+
+ status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), &result,
+ "STATUS %s (MESSAGES)", imap_folder->folder_file_path);
+
+ if (status != CAMEL_IMAP_OK) {
+ CamelService *service = CAMEL_SERVICE (folder->parent_store);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not get message count from IMAP "
+ "server %s: %s.", service->url->host,
+ status == CAMEL_IMAP_ERR ? result :
+ "Unknown error");
+ g_free (result);
+ return -1;
+ }
- g_assert (folder);
- g_assert (imap_folder->summary);
-
- return camel_folder_summary_count((CamelFolderSummary *)imap_folder->summary);
+ /* parse out the message count - should come in the form: "* STATUS <folder> (MESSAGES <count>)\r\n" */
+ if (result && *result == '*' ) {
+ if (msg_count = strstr(result, "MESSAGES")) {
+ msg_count += strlen("MESSAGES") + 1;
+
+ /* we should now be pointing to the message count */
+ imap_folder->count = atoi(msg_count);
+ }
+ }
+ g_free(result);
+
+ return imap_folder->count;
}
-/* FIXME: this may need some tweaking for performance? */
static void
imap_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex)
{
@@ -451,9 +432,10 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept
static GPtrArray *
imap_get_uids (CamelFolder *folder, CamelException *ex)
{
+ /* TODO: Find out what this is actually supposed to do */
GPtrArray *array;
- CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
- int i, count;
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ gint i, count;
count = camel_folder_summary_count((CamelFolderSummary *)imap_folder->summary);
array = g_ptr_array_new ();
@@ -470,16 +452,76 @@ imap_get_uids (CamelFolder *folder, CamelException *ex)
static GPtrArray *
imap_get_subfolder_names (CamelFolder *folder, CamelException *ex)
{
- /* TODO: LSUB or LIST */
+ /* NOTE: use LSUB or LIST - preferably LSUB but I managed with LIST in Spruce */
+ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
+ GPtrArray *listing;
+ gint status;
+ gchar *result;
+
+ g_return_val_if_fail (folder != NULL, g_ptr_array_new());
+
+ if (imap_folder->count != -1)
+ imap_folder->count;
+
+ status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), &result,
+ "LSUB \"\" \"%s\"", imap_folder->folder_file_path);
+
+ if (status != CAMEL_IMAP_OK) {
+ CamelService *service = CAMEL_SERVICE (folder->parent_store);
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not get subfolder listing from IMAP "
+ "server %s: %s.", service->url->host,
+ status == CAMEL_IMAP_ERR ? result :
+ "Unknown error");
+ g_free (result);
+ return g_ptr_array_new ();
+ }
+
+ /* parse out the subfolders */
+ listing = g_ptr_array_new ();
+ if (result) {
+ ptr = result;
+ while (*ptr == '*') {
+ gchar *flags, *param, *end, *dir_sep;
+
+ ptr = flags = strchr(ptr, '(') + 1; /* jump to the flags section */
+ end = strchr(flags, ')'); /* locate end of flags */
+ flags = strndup(flags, (gint)(end - flags));
+
+ if (strstr(flags, "\\NoSelect")) {
+ g_free(flags);
+ continue;
+ }
+ g_free(flags);
+
+ ptr = dir_sep = strchr(ptr, '"') + 1; /* jump to the first param */
+ end = strchr(param, '"'); /* locate the end of the param */
+ dir_sep = g_strndup(dir_sep, (gint)(end - param));
+
+ /* skip to the actual directory parameter */
+ for (ptr = end++; *ptr == ' '; ptr++);
+ for (end = ptr; *end && *end != '\n'; end++);
+ param = g_strndup(ptr, (gint)(end - ptr));
- /* No subfolders. */
- return g_ptr_array_new ();
+ g_ptr_array_add (listing, param);
+
+ g_free(dir_sep); /* TODO: decide if we really need dir_sep */
+
+ if (*end)
+ ptr = end + 1;
+ else
+ ptr = end;
+ }
+ }
+ g_free(result);
+
+ return listing;
}
static void
imap_delete_message_by_uid(CamelFolder *folder, const gchar *uid, CamelException *ex)
{
- CamelMessageInfo *info;
+ /* NOTE: should be as easy as marking as deleted - which should be easy in IMAP */
CamelImapFolder *mf = (CamelImapFolder *)folder;
info = camel_folder_summary_uid((CamelFolderSummary *)mf->summary, uid);
@@ -493,6 +535,7 @@ imap_delete_message_by_uid(CamelFolder *folder, const gchar *uid, CamelException
static void
message_changed(CamelMimeMessage *m, int type, CamelImapFolder *mf)
{
+ /* TODO: find a way to do this in IMAP - will probably not be easy */
CamelMessageInfo *info;
CamelFlag *flag;
@@ -521,6 +564,7 @@ message_changed(CamelMimeMessage *m, int type, CamelImapFolder *mf)
static CamelMimeMessage *
imap_get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex)
{
+ /* NOTE: extremely easy to do in IMAP - just needa code it ;-) */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
CamelStream *message_stream = NULL;
CamelMimeMessage *message = NULL;
@@ -597,6 +641,7 @@ fail:
GPtrArray *
imap_get_summary (CamelFolder *folder, CamelException *ex)
{
+ /* TODO: what should we do here?? */
CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
return ((CamelFolderSummary *)imap_folder->summary)->messages;
@@ -605,13 +650,15 @@ imap_get_summary (CamelFolder *folder, CamelException *ex)
void
imap_free_summary (CamelFolder *folder, GPtrArray *array)
{
- /* no-op */
+ /* This is IMAP dude, no need to free a summary */
+ return;
}
/* get a single message info, by uid */
static const CamelMessageInfo *
imap_summary_get_by_uid(CamelFolder *f, const char *uid)
{
+ /* TODO: what do we do here? */
CamelImapFolder *imap_folder = (CamelImapFolder *)f;
return camel_folder_summary_uid((CamelFolderSummary *)imap_folder->summary, uid);
@@ -620,6 +667,7 @@ imap_summary_get_by_uid(CamelFolder *f, const char *uid)
static GList *
imap_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex)
{
+ /* TODO: find a good way of doing this */
CamelImapFolder *imap_folder = (CamelImapFolder *)folder;
if (imap_folder->search == NULL) {
@@ -634,3 +682,8 @@ imap_search_by_expression(CamelFolder *folder, const char *expression, CamelExce
return camel_folder_search_execute_expression(imap_folder->search, expression, ex);
}
+
+
+
+
+
diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h
index 5a54d693d2..54605cfb35 100644
--- a/camel/providers/imap/camel-imap-folder.h
+++ b/camel/providers/imap/camel-imap-folder.h
@@ -48,6 +48,9 @@ typedef struct {
gchar *folder_dir_path; /* contains the subfolders */
gchar *index_file_path; /* index of body contents */
+ ibex *index; /* index for this folder */
+ CamelImapSummary *summary;
+ CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */
} CamelImapFolder;
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index b5d5f71ccc..0d35e971b2 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -367,7 +367,7 @@ static gchar
* (a protocol-level error occurred, and Camel is uncertain of the
* result of the command.)
**/
-int
+gint
camel_imap_command (CamelImapStore *store, char **ret, char *fmt, ...)
{
gchar *cmdbuf, *respbuf;
@@ -403,9 +403,10 @@ camel_imap_command (CamelImapStore *store, char **ret, char *fmt, ...)
fprintf(stderr, "received: %s\n", respbuf);
+ /* TODO: We should really check the command id, da? */
if (!strncmp (respbuf + 11, "OK", 2))
status = CAMEL_IMAP_OK;
- else if (!strncmp (respbuf + 11, "BAD", 3))
+ else if (!strncmp (respbuf + 11, "NO", 2))
status = CAMEL_IMAP_ERR;
else
status = CAMEL_IMAP_FAIL;
@@ -424,41 +425,81 @@ camel_imap_command (CamelImapStore *store, char **ret, char *fmt, ...)
}
/**
- * camel_imap_command_get_additional_data: get "additional data" from
- * an IMAP command.
+ * camel_imap_command_extended: Send a command to a IMAP server and get
+ * a multi-line response.
* @store: the IMAP store
+ * @ret: a pointer to return the full server response in
+ * @fmt: a printf-style format string, followed by arguments
+ *
+ * This command sends the command specified by @fmt and the following
+ * arguments to the connected IMAP store specified by @store. It then
+ * reads the server's response and parses out the status code.
+ * Camel_imap_command_extended will set it to point to a buffer containing the
+ * response from the IMAP server. (If @ret was passed but there was The caller
+ * must free this buffer when it is done with it.
*
* This command gets the additional data returned by "multi-line" IMAP
- * commands, such as LIST, RETR, TOP, and UIDL. This command _must_
- * be called after a successful (CAMEL_IMAP_OK) call to
- * camel_imap_command for a command that has a multi-line response.
+ * commands, such as SELECT, LIST, LSUB, and various other commands.
* The returned data is un-byte-stuffed, and has lines termined by
* newlines rather than CR/LF pairs.
*
- * Return value: the data, which the caller must free.
+ * Return value: one of CAMEL_IMAP_OK (command executed successfully),
+ * CAMEL_IMAP_ERR (command encounted an error), or CAMEL_IMAP_FAIL
+ * (a protocol-level error occurred, and Camel is uncertain of the
+ * result of the command.)
**/
-char *
-camel_imap_command_get_additional_data (CamelImapStore *store,
- CamelException *ex)
+
+gint
+camel_imap_command_extended (CamelImapStore *store, char **ret, char *fmt, ...)
{
CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream);
GPtrArray *data;
- char *buf;
- int i, status = CAMEL_IMAP_OK;
+ gchar *cmdid, *cmdbuf, *respbuf, *code;
+ va_list app;
+ gint i, status = CAMEL_IMAP_OK;
+
+ /* Create the command */
+ cmdid = g_strdup_printf("A%.5d", store->command++);
+ va_start (ap, fmt);
+ cmdbuf = g_strdup_vprintf (fmt, ap);
+ va_end (ap);
+
+ fprintf(stderr, "sending : %s %s\r\n", cmdid, cmdbuf);
+
+ if (camel_stream_printf (store->ostream, "%s %s\r\n", cmdid, cmdbuf) == -1) {
+ g_free(cmdbuf);
+ g_free(cmdid);
+
+ *ret = g_strdup(strerror(errno));
+
+ return CAMEL_IMAP_FAIL;
+ }
+ g_free(cmdbuf);
+ g_free(cmdid);
data = g_ptr_array_new ();
while (1) {
- buf = camel_stream_buffer_read_line (stream);
- if (!buf) {
- status = CAMEL_IMAP_FAIL;
+ respbuf = camel_stream_buffer_read_line (stream);
+ if (!respbuf || !strncmp(respbuf, cmdid, strlen(cmdid)) ) {
+ /* IMAP's last response starts with our command id */
break;
}
- if (!strcmp (buf, "."))
- break;
- if (*buf == '.')
- memmove (buf, buf + 1, strlen (buf));
- g_ptr_array_add (data, buf);
+ fprintf(stderr, "received: %s\n", respbuf);
+
+ g_ptr_array_add (data, respbuf);
+ }
+
+ if (respbuf) {
+ code = respbuf + strlen(cmdid) + 1;
+ if (!strncmp(code, "OK", 2))
+ status = CAMEL_IMAP_OK;
+ else if (!strncmp(code, "NO", 2))
+ status = CAMEL_IMAP_ERR;
+ else
+ status = CAMEL_IMAP_FAIL;
+ } else {
+ status = CAMEL_IMAP_FAIL;
}
if (status == CAMEL_IMAP_OK) {
@@ -468,14 +509,23 @@ camel_imap_command_get_additional_data (CamelImapStore *store,
*/
g_ptr_array_add (data, "");
g_ptr_array_add (data, NULL);
- buf = g_strjoinv ("\n", (char **)data->pdata);
- } else
- buf = NULL;
+ *ret = g_strjoinv ("\n", (gchar **)data->pdata);
+ } else {
+ if (status != CAMEL_IMAP_FAIL)
+ *ret = g_strdup (strchr (respbuf, ' ' + 1);
+ else
+ *ret = NULL;
+ }
for (i = 0; i < data->len - 2; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
- return buf;
+ return status;
}
+
+
+
+
+
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index 970461582b..fc6ac9b61c 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -68,8 +68,7 @@ void camel_imap_store_close (CamelImapStore *store, gboolean expunge,
enum { CAMEL_IMAP_OK, CAMEL_IMAP_ERR, CAMEL_IMAP_FAIL };
gint camel_imap_command (CamelImapStore *store, char **ret, char *fmt, ...);
-gchar *camel_imap_command_get_additional_data (CamelImapStore *store,
- CamelException *ex);
+gchar *camel_imap_command_extended (CamelImapStore *store, char **ret, char *fmt, ...);
/* Standard Gtk function */
GtkType camel_imap_store_get_type (void);