Return untagged data in a GPtrArray rather than a string, since it saves

* providers/imap/camel-imap-store.c (camel_imap_command_extended):
	Return untagged data in a GPtrArray rather than a string, since it
	saves processing time and is much easier to deal with for several
	commands. Update for camel_imap_folder_changed change.
	(camel_imap_fetch_command): Update for camel_imap_folder_changed
	change.
	(imap_connect, imap_folder_exists): Update for
	camel_imap_command_extended change.

	* providers/imap/camel-imap-folder.c
	(imap_get_message_count_internal,
	imap_get_subfolder_info_internal, imap_search_by_expression):
	Update for camel_imap_command_extended change.

	(imap_get_summary_internal, imap_get_message_info_internal): Use
	camel_imap_fetch_command here now to get around the
	camel_imap_command_extended change.

	(camel_imap_folder_changed): turn expunged into a GArray of ints
	rather than a GPtrArray of strings representing ints.

svn path=/trunk/; revision=5608
This commit is contained in:
Dan Winship
2000-09-27 23:55:26 +00:00
parent 6f2839b4d1
commit ef97f35231
5 changed files with 214 additions and 142 deletions

View File

@ -1,3 +1,26 @@
2000-09-27 Dan Winship <danw@helixcode.com>
* providers/imap/camel-imap-store.c (camel_imap_command_extended):
Return untagged data in a GPtrArray rather than a string, since it
saves processing time and is much easier to deal with for several
commands. Update for camel_imap_folder_changed change.
(camel_imap_fetch_command): Update for camel_imap_folder_changed
change.
(imap_connect, imap_folder_exists): Update for
camel_imap_command_extended change.
* providers/imap/camel-imap-folder.c
(imap_get_message_count_internal,
imap_get_subfolder_info_internal, imap_search_by_expression):
Update for camel_imap_command_extended change.
(imap_get_summary_internal, imap_get_message_info_internal): Use
camel_imap_fetch_command here now to get around the
camel_imap_command_extended change.
(camel_imap_folder_changed): turn expunged into a GArray of ints
rather than a GPtrArray of strings representing ints.
2000-09-26 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-folder.c

View File

@ -93,7 +93,6 @@ static const CamelMessageInfo *imap_get_message_info (CamelFolder *folder, const
static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex);
/* flag methods */
/*static guint32 imap_get_permanent_flags (CamelFolder *folder, CamelException *ex);*/
static guint32 imap_get_message_flags (CamelFolder *folder, const char *uid);
static void imap_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set);
static gboolean imap_get_message_user_flag (CamelFolder *folder, const char *uid, const char *name);
@ -306,6 +305,7 @@ imap_get_message_count_internal (CamelFolder *folder, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
gchar *result, *msg_count, *folder_path;
GPtrArray *response;
gint status, count = 0;
g_return_val_if_fail (folder->can_hold_messages, 0);
@ -313,10 +313,10 @@ imap_get_message_count_internal (CamelFolder *folder, CamelException *ex)
folder_path = camel_imap_store_folder_path (store, folder->full_name);
if (store->has_status_capability)
status = camel_imap_command_extended (store, folder, &result, ex,
status = camel_imap_command_extended (store, folder, &response, ex,
"STATUS \"%s\" (MESSAGES)", folder_path);
else
status = camel_imap_command_extended (store, folder, &result, ex,
status = camel_imap_command_extended (store, folder, &response, ex,
"EXAMINE \"%s\"", folder_path);
g_free (folder_path);
@ -325,17 +325,22 @@ imap_get_message_count_internal (CamelFolder *folder, CamelException *ex)
return 0;
/* parse out the message count */
if (result && *result == '*') {
if (store->has_status_capability) {
/* should come in the form: "* STATUS <folder> (MESSAGES <count>)" */
if (store->has_status_capability) {
/* should come in the form: "* STATUS <folder> (MESSAGES <count>)" */
result = camel_imap_response_extract (response, "STATUS", NULL);
if (result) {
if ((msg_count = strstr (result, "MESSAGES")) != NULL) {
msg_count = imap_next_word (msg_count);
/* we should now be pointing to the message count */
count = atoi (msg_count);
}
} else {
/* should come in the form: "* <count> EXISTS" */
g_free (result);
}
} else {
/* should come in the form: "* <count> EXISTS" */
result = camel_imap_response_extract (response, "EXISTS", NULL);
if (result) {
if ((msg_count = strstr (result, "EXISTS")) != NULL) {
for ( ; msg_count > result && *msg_count != '*'; msg_count--);
@ -344,9 +349,9 @@ imap_get_message_count_internal (CamelFolder *folder, CamelException *ex)
/* we should now be pointing to the message count */
count = atoi (msg_count);
}
g_free (result);
}
}
g_free (result);
return count;
}
@ -501,16 +506,16 @@ imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
GPtrArray *listing;
GPtrArray *response, *listing;
gboolean found_inbox = FALSE;
gint status;
gchar *result, *namespace;
gint status, i;
gchar *namespace;
CamelFolderInfo *fi;
g_return_val_if_fail (folder != NULL, g_ptr_array_new ());
namespace = camel_imap_store_folder_path (store, folder->full_name);
status = camel_imap_command_extended (store, NULL, &result, ex,
status = camel_imap_command_extended (store, NULL, &response, ex,
"LIST \"\" \"%s%s*\"", namespace,
*namespace ? store->dir_sep : "");
@ -523,31 +528,20 @@ imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex)
/* parse out the subfolders */
listing = g_ptr_array_new ();
if (result) {
char *ptr = result;
while (ptr && *ptr == '*') {
gchar *flags, *sep, *dir, *buf, *end;
for (end = ptr; *end && *end != '\n'; end++);
buf = g_strndup (ptr, (gint)(end - ptr));
ptr = end;
if (!imap_parse_list_response (buf, namespace, &flags, &sep, &dir)) {
g_free (buf);
if (response) {
for (i = 0; i < response->len; i++) {
gchar *resp, *flags, *sep, *dir;
resp = response->pdata[i];
if (!imap_parse_list_response (resp, namespace, &flags, &sep, &dir)) {
g_free (flags);
g_free (sep);
g_free (dir);
if (*ptr == '\n')
ptr++;
continue;
}
g_free (buf);
g_free (flags);
if (*dir) {
d(fprintf (stderr, "adding folder: %s\n", dir));
fi = g_new0 (CamelFolderInfo, 1);
@ -563,12 +557,10 @@ imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex)
found_inbox = TRUE;
g_ptr_array_add (listing, fi);
}
g_free (sep);
if (*ptr == '\n')
ptr++;
}
camel_imap_response_free (response);
}
if (!*folder->name && !found_inbox) {
@ -580,7 +572,6 @@ imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex)
g_ptr_array_add (listing, fi);
}
g_free (result);
g_free (namespace);
imap_folder->lsub = listing;
@ -821,13 +812,12 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex)
summary_specifier = imap_protocol_get_summary_specifier (store);
/* We use camel_imap_command_extended here because it's safe */
if (num == 1) {
status = camel_imap_command_extended (store, folder, &result, ex,
"FETCH 1 (%s)", summary_specifier);
status = camel_imap_fetch_command (store, folder, &result, ex,
"FETCH 1 (%s)", summary_specifier);
} else {
status = camel_imap_command_extended (store, folder, &result, ex,
"FETCH 1:%d (%s)", num, summary_specifier);
status = camel_imap_fetch_command (store, folder, &result, ex,
"FETCH 1:%d (%s)", num, summary_specifier);
}
g_free (summary_specifier);
@ -986,9 +976,8 @@ imap_get_message_info_internal (CamelFolder *folder, guint id, CamelException *e
/* we don't have a cached copy, so fetch it */
summary_specifier = imap_protocol_get_summary_specifier (store);
/* again, we use camel_imap_command_extended here because it's safe to do so */
status = camel_imap_command_extended (store, folder, &result, ex,
"FETCH %d (%s)", id, summary_specifier);
status = camel_imap_fetch_command (store, folder, &result, ex,
"FETCH %d (%s)", id, summary_specifier);
g_free (summary_specifier);
@ -1093,7 +1082,7 @@ imap_get_message_info (CamelFolder *folder, const char *uid)
static GPtrArray *
imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex)
{
GPtrArray *uids = NULL;
GPtrArray *response, *uids = NULL;
char *result, *sexp, *p;
int status;
@ -1109,12 +1098,14 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
}
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, ex, "UID SEARCH %s", sexp);
&response, NULL, "UID SEARCH %s", sexp);
g_free (sexp);
if (status != CAMEL_IMAP_OK) {
g_free (sexp);
if (status != CAMEL_IMAP_OK)
return uids;
result = camel_imap_response_extract (response, "SEARCH", NULL);
if (!result)
return uids;
}
if ((p = strstr (result, "* SEARCH"))) {
char *word;
@ -1136,7 +1127,6 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
}
g_free (result);
g_free (sexp);
return uids;
}
@ -1178,7 +1168,7 @@ imap_set_message_user_flag (CamelFolder *folder, const char *uid, const char *na
}
void
camel_imap_folder_changed (CamelFolder *folder, gint recent, GPtrArray *expunged, CamelException *ex)
camel_imap_folder_changed (CamelFolder *folder, gint recent, GArray *expunged, CamelException *ex)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
@ -1186,7 +1176,7 @@ camel_imap_folder_changed (CamelFolder *folder, gint recent, GPtrArray *expunged
gint i, id;
for (i = 0; i < expunged->len; i++) {
id = atoi (expunged->pdata[i]);
id = g_array_index (expunged, int, i);
d(fprintf (stderr, "Expunging message %d from the summary (i = %d)\n", id + i, i));
if (id <= imap_folder->summary->len) {

View File

@ -64,7 +64,7 @@ typedef struct {
/* public methods */
CamelFolder *camel_imap_folder_new (CamelStore *parent, const char *folder_name);
void camel_imap_folder_changed (CamelFolder *folder, gint recent, GPtrArray *expunged,
void camel_imap_folder_changed (CamelFolder *folder, gint recent, GArray *expunged,
CamelException *ex);
/* Standard Camel function */

View File

@ -180,7 +180,8 @@ imap_connect (CamelService *service, CamelException *ex)
{
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelSession *session = camel_service_get_session (CAMEL_SERVICE (store));
gchar *buf, *result, *errbuf = NULL;
gchar *result, *buf, *errbuf = NULL;
GPtrArray *response;
gboolean authenticated = FALSE;
gint status;
@ -244,12 +245,14 @@ imap_connect (CamelService *service, CamelException *ex)
}
/* Now lets find out the IMAP capabilities */
status = camel_imap_command_extended (store, NULL, &result, ex, "CAPABILITY");
if (status != CAMEL_IMAP_OK) {
/* Non-fatal error... (ex is set) */
}
status = camel_imap_command_extended (store, NULL, &response, ex, "CAPABILITY");
if (status != CAMEL_IMAP_OK)
return FALSE;
result = camel_imap_response_extract (response, "CAPABILITY", ex);
if (!result)
return FALSE;
/* parse for capabilities here. */
if (e_strstrcase (result, "IMAP4REV1"))
store->server_level = IMAP_LEVEL_IMAP4REV1;
@ -257,20 +260,22 @@ imap_connect (CamelService *service, CamelException *ex)
store->server_level = IMAP_LEVEL_IMAP4;
else
store->server_level = IMAP_LEVEL_UNKNOWN;
if ((store->server_level >= IMAP_LEVEL_IMAP4REV1) || (e_strstrcase (result, "STATUS")))
if ((store->server_level >= IMAP_LEVEL_IMAP4REV1) ||
(e_strstrcase (result, "STATUS")))
store->has_status_capability = TRUE;
else
store->has_status_capability = FALSE;
g_free (result);
/* We now need to find out which directory separator this daemon uses */
status = camel_imap_command_extended (store, NULL, &result, ex, "LIST \"\" \"\"");
if (status != CAMEL_IMAP_OK) {
/* Again, this is non-fatal */
} else {
status = camel_imap_command_extended (store, NULL, &response, ex, "LIST \"\" \"\"");
if (status != CAMEL_IMAP_OK)
return FALSE;
result = camel_imap_response_extract (response, "LIST", ex);
if (!result)
return FALSE;
else {
char *flags, *sep, *folder;
if (imap_parse_list_response (result, "", &flags, &sep, &folder)) {
@ -283,9 +288,8 @@ imap_connect (CamelService *service, CamelException *ex)
g_free (flags);
g_free (sep);
g_free (folder);
g_free (result);
}
g_free (result);
camel_remote_store_refresh_folders (CAMEL_REMOTE_STORE (store), ex);
@ -330,8 +334,8 @@ camel_imap_store_folder_path (CamelImapStore *store, const char *name)
static gboolean
imap_folder_exists (CamelImapStore *store, const char *folder_path, gboolean *selectable, CamelException *ex)
{
gchar *result;
char *flags, *sep, *dirname;
GPtrArray *response;
char *result, *flags, *sep, *dirname;
gint status;
if (!g_strcasecmp (folder_path, "INBOX")) {
@ -345,12 +349,13 @@ imap_folder_exists (CamelImapStore *store, const char *folder_path, gboolean *se
*selectable = FALSE;
status = camel_imap_command_extended (CAMEL_IMAP_STORE (store), NULL,
&result, ex, "LIST \"\" \"%s\"", folder_path);
if (status != CAMEL_IMAP_OK) {
g_free (result);
&response, ex, "LIST \"\" \"%s\"", folder_path);
if (status != CAMEL_IMAP_OK)
return FALSE;
}
result = camel_imap_response_extract (response, "LIST", ex);
if (!result)
return FALSE;
if (imap_parse_list_response (result, "", &flags, &sep, &dirname)) {
if (selectable)
*selectable = !e_strstrcase (flags, "NoSelect");
@ -358,9 +363,11 @@ imap_folder_exists (CamelImapStore *store, const char *folder_path, gboolean *se
g_free (flags);
g_free (sep);
g_free (dirname);
g_free (result);
return TRUE;
}
g_free (result);
g_free (flags);
g_free (sep);
@ -630,12 +637,12 @@ camel_imap_command (CamelImapStore *store, CamelFolder *folder, CamelException *
**/
gint
camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **ret, CamelException *ex, char *fmt, ...)
camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, GPtrArray **ret, CamelException *ex, char *fmt, ...)
{
gint status = CAMEL_IMAP_OK;
GPtrArray *data, *expunged;
GPtrArray *data;
GArray *expunged;
gchar *respbuf, *cmdid;
guint32 len = 0;
gint recent = 0;
va_list ap;
gint i;
@ -653,27 +660,24 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
}
va_end (ap);
data = g_ptr_array_new ();
expunged = g_ptr_array_new ();
expunged = g_array_new (FALSE, FALSE, sizeof (int));
if (ret)
data = g_ptr_array_new ();
/* read multi-line response */
while (1) {
if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &respbuf, ex) < 0) {
/* cleanup */
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
for (i = 0; i < expunged->len; i++)
g_free (expunged->pdata[i]);
g_ptr_array_free (expunged, TRUE);
if (ret) {
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
}
g_array_free (expunged, TRUE);
return CAMEL_IMAP_FAIL;
}
g_ptr_array_add (data, respbuf);
len += strlen (respbuf) + 1;
/* IMAPs multi-line response ends with the cmdid string at the beginning of the line */
if (!strncmp (respbuf, cmdid, strlen (cmdid))) {
status = camel_imap_status (cmdid, respbuf);
@ -690,6 +694,8 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
rcnt = imap_next_word (respbuf);
if (*rcnt >= '0' && *rcnt <= '9' && !strncmp ("RECENT", imap_next_word (rcnt), 6))
recent = atoi (rcnt);
g_free (respbuf);
continue;
} else if (strstr (respbuf, "EXPUNGE")) {
char *id_str;
int id;
@ -699,33 +705,22 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
id_str = imap_next_word (respbuf);
if (*id_str >= '0' && *id_str <= '9' && !strncmp ("EXPUNGE", imap_next_word (id_str), 7)) {
id = atoi (id_str);
g_ptr_array_add (expunged, g_strdup_printf ("%d", id));
g_array_append_val (expunged, id);
}
g_free (respbuf);
continue;
}
}
if (ret)
g_ptr_array_add (data, respbuf);
else
g_free (respbuf);
}
if (status == CAMEL_IMAP_OK && ret) {
gchar *p;
/* populate the return buffer with the server response */
*ret = g_new (char, len + 1);
p = *ret;
for (i = 0; i < data->len; i++) {
char *datap;
datap = (char *) data->pdata[i];
if (*datap == '.')
datap++;
len = strlen (datap);
memcpy (p, datap, len);
p += len;
*p++ = '\n';
}
*p = '\0';
} else if (status != CAMEL_IMAP_OK) {
if (status == CAMEL_IMAP_OK) {
if (ret)
*ret = data;
} else {
/* command failed */
if (respbuf) {
char *word;
@ -741,10 +736,16 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
"IMAP command failed: Unknown");
}
if (ret)
*ret = NULL;
if (ret) {
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
}
}
if (respbuf)
g_free (respbuf);
/* Update the summary */
if (folder && (recent > 0 || expunged->len > 0)) {
CamelException dex;
@ -753,18 +754,80 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
camel_imap_folder_changed (folder, recent, expunged, &dex);
camel_exception_clear (&dex);
}
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
for (i = 0; i < expunged->len; i++)
g_free (expunged->pdata[i]);
g_ptr_array_free (expunged, TRUE);
g_array_free (expunged, TRUE);
return status;
}
/**
* camel_imap_response_free:
* @response: the result data returned from camel_imap_command_extended
*
* Frees the data.
**/
void
camel_imap_response_free (GPtrArray *response)
{
int i;
for (i = 0; i < response->len; i++)
g_free (response->pdata[i]);
g_ptr_array_free (response, TRUE);
}
/**
* camel_imap_response_extract:
* @response: the result data returned from camel_imap_command_extended
* @type: the response type to extract
* @ex: a CamelException
*
* This checks that @response contains a single untagged response of
* type @type and returns just that response data. If @response
* doesn't contain the right information, the function will set @ex and
* return %NULL. Either way, @response will be freed.
*
* Return value: the desired response string, which the caller must free.
**/
char *
camel_imap_response_extract (GPtrArray *response, const char *type,
CamelException *ex)
{
int len = strlen (type), i;
char *resp;
for (i = 0; i < response->len; i++) {
resp = response->pdata[i];
if (strncmp (resp, "* ", 2) != 0) {
g_free (resp);
continue;
}
/* Skip inititial sequence number, if present */
strtoul (resp + 2, &resp, 10);
if (*resp == ' ')
resp++;
if (!g_strncasecmp (resp, type, len))
break;
g_free (resp);
}
if (i < response->len) {
resp = response->pdata[i];
for (i++; i < response->len; i++)
g_free (response->pdata[i]);
} else {
resp = NULL;
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
"IMAP server response did not contain "
"%s information", type);
}
g_ptr_array_free (response, TRUE);
return resp;
}
/**
* camel_imap_fetch_command: Send a FETCH request to an IMAP server and get
* a multi-line response.
@ -800,7 +863,8 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
* determine whether we are actually reading server responses.
*/
gint status = CAMEL_IMAP_OK;
GPtrArray *data, *expunged;
GPtrArray *data;
GArray *expunged;
gboolean is_notification;
gchar *respbuf, *cmdid;
guint32 len = 0;
@ -862,7 +926,7 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
return CAMEL_IMAP_FAIL;
}
expunged = g_ptr_array_new ();
expunged = g_array_new (FALSE, FALSE, sizeof (int));
/* read multi-line response */
while (1) {
@ -871,10 +935,7 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
for (i = 0; i < expunged->len; i++)
g_free (expunged->pdata[i]);
g_ptr_array_free (expunged, TRUE);
g_array_free (expunged, TRUE);
return CAMEL_IMAP_FAIL;
}
@ -897,10 +958,8 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
recent = 0;
for (i = 0; i < expunged->len; i++) {
g_free (expunged->pdata[i]);
g_ptr_array_remove_index (expunged, i);
}
for (i = 0; i < expunged->len; i++)
g_array_remove_index (expunged, i);
}
/* Check for a RECENT in the untagged response */
@ -922,7 +981,7 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
id_str = imap_next_word (respbuf);
if (*id_str >= '0' && *id_str <= '9' && !strncmp ("EXPUNGE", imap_next_word (id_str), 7)) {
id = atoi (id_str);
g_ptr_array_add (expunged, g_strdup_printf ("%d", id));
g_array_append_val (expunged, id);
}
}
}
@ -986,10 +1045,7 @@ camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder, char **ret
for (i = 0; i < data->len; i++)
g_free (data->pdata[i]);
g_ptr_array_free (data, TRUE);
for (i = 0; i < expunged->len; i++)
g_free (expunged->pdata[i]);
g_ptr_array_free (expunged, TRUE);
g_array_free (expunged, TRUE);
return status;
}

View File

@ -84,7 +84,10 @@ gint camel_imap_command (CamelImapStore *store, CamelFolder *folder,
CamelException *ex, char *fmt, ...);
gint camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder,
char **ret, CamelException *ex, char *fmt, ...);
GPtrArray **ret, CamelException *ex, char *fmt, ...);
void camel_imap_response_free (GPtrArray *response);
char *camel_imap_response_extract (GPtrArray *response, const char *type,
CamelException *ex);
gint camel_imap_fetch_command (CamelImapStore *store, CamelFolder *folder,
char **ret, CamelException *ex, char *fmt, ...);