[evolution-data-server] Add CamelIMAPXListResponse.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Add CamelIMAPXListResponse.
- Date: Sat, 3 Aug 2013 20:46:42 +0000 (UTC)
commit 999efb956818ec830cd80c8ded4a54b43b23657d
Author: Matthew Barnes <mbarnes redhat com>
Date: Mon Jul 29 10:40:44 2013 -0400
Add CamelIMAPXListResponse.
Represents an IMAP LIST response, including LIST-EXTENDED information.
Replaces the "list_info" struct and associated functions.
New functions:
camel_imapx_list_response_new()
camel_imapx_list_response_hash()
camel_imapx_list_response_equal()
camel_imapx_list_response_compare()
camel_imapx_list_response_get_mailbox()
camel_imapx_list_response_get_separator()
camel_imapx_list_response_add_flag()
camel_imapx_list_response_has_flag()
camel_imapx_list_response_get_childinfo()
camel_imapx_list_response_get_summary_flags()
Removed functions:
imapx_parse_list()
imapx_list_get_path()
imapx_free_list()
camel/Makefile.am | 2 +
camel/camel-imapx-list-response.c | 484 +++++++++++++++++++++++++++++++
camel/camel-imapx-list-response.h | 115 ++++++++
camel/camel-imapx-server.c | 90 ++----
camel/camel-imapx-store.c | 42 ++-
camel/camel-imapx-utils.c | 104 -------
camel/camel-imapx-utils.h | 17 -
camel/camel.h | 1 +
docs/reference/camel/camel-docs.sgml | 1 +
docs/reference/camel/camel-sections.txt | 35 +++
docs/reference/camel/camel.types | 1 +
11 files changed, 699 insertions(+), 193 deletions(-)
---
diff --git a/camel/Makefile.am b/camel/Makefile.am
index 7483e58..02f8c1e 100644
--- a/camel/Makefile.am
+++ b/camel/Makefile.am
@@ -178,6 +178,7 @@ libcamel_1_2_la_SOURCES = \
camel-imapx-command.c \
camel-imapx-folder.c \
camel-imapx-job.c \
+ camel-imapx-list-response.c \
camel-imapx-search.c \
camel-imapx-server.c \
camel-imapx-settings.c \
@@ -312,6 +313,7 @@ libcamelinclude_HEADERS = \
camel-imapx-command.h \
camel-imapx-folder.h \
camel-imapx-job.h \
+ camel-imapx-list-response.h \
camel-imapx-search.h \
camel-imapx-server.h \
camel-imapx-settings.h \
diff --git a/camel/camel-imapx-list-response.c b/camel/camel-imapx-list-response.c
new file mode 100644
index 0000000..cc42579
--- /dev/null
+++ b/camel/camel-imapx-list-response.c
@@ -0,0 +1,484 @@
+/*
+ * camel-imapx-list-response.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/**
+ * SECTION: camel-imapx-list-response
+ * @include: camel/camel.h
+ * @short_description: Stores an IMAP LIST response
+ *
+ * #CamelIMAPXListResponse encapsulates an IMAP LIST response, which consists
+ * of a set of mailbox attributes, a mailbox separator character, and the
+ * mailbox name. (Extended information for LIST responses, as described in
+ * <ulink url="http://tools.ietf.org/html/rfc5258">RFC 5258</ulink>, to be
+ * supported at a later date.)
+ *
+ * #CamelIMAPXListResponse can also convert the mailbox attributes to
+ * a #CamelStoreInfoFlags / #CamelFolderInfoFlags value for use with
+ * camel_store_get_folder_info().
+ **/
+
+#include "camel-imapx-list-response.h"
+
+#define CAMEL_IMAPX_LIST_RESPONSE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), CAMEL_TYPE_IMAPX_LIST_RESPONSE, CamelIMAPXListResponsePrivate))
+
+struct _CamelIMAPXListResponsePrivate {
+ gchar *mailbox;
+ gchar separator;
+ GQueue attributes;
+};
+
+G_DEFINE_TYPE (
+ CamelIMAPXListResponse,
+ camel_imapx_list_response,
+ G_TYPE_OBJECT)
+
+static void
+imapx_list_response_finalize (GObject *object)
+{
+ CamelIMAPXListResponsePrivate *priv;
+
+ priv = CAMEL_IMAPX_LIST_RESPONSE_GET_PRIVATE (object);
+
+ g_free (priv->mailbox);
+
+ /* Flag strings are interned, so don't free them. */
+ g_queue_clear (&priv->attributes);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (camel_imapx_list_response_parent_class)->
+ finalize (object);
+}
+
+static void
+camel_imapx_list_response_class_init (CamelIMAPXListResponseClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (
+ class, sizeof (CamelIMAPXListResponsePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = imapx_list_response_finalize;
+}
+
+static void
+camel_imapx_list_response_init (CamelIMAPXListResponse *response)
+{
+ response->priv = CAMEL_IMAPX_LIST_RESPONSE_GET_PRIVATE (response);
+}
+
+/**
+ * camel_imapx_list_response_new:
+ * @stream: a #CamelIMAPXStream
+ * @cancellable: a #GCancellable
+ * @error: return location for a #GError, or %NULL
+ *
+ * Attempts to parse an IMAP LIST response from @stream and, if successful,
+ * stores the response data in a new #CamelIMAPXListResponse. If an error
+ * occurs, the function sets @error and returns %NULL.
+ *
+ * Returns: a #CamelIMAPXListResponse, or %NULL
+ *
+ * Since: 3.10
+ **/
+CamelIMAPXListResponse *
+camel_imapx_list_response_new (CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelIMAPXListResponse *response;
+ camel_imapx_token_t tok;
+ guchar *token;
+ guint len;
+ const gchar *attribute;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_STREAM (stream), NULL);
+
+ response = g_object_new (CAMEL_TYPE_IMAPX_LIST_RESPONSE, NULL);
+
+ /* Parse attributes. */
+
+ tok = camel_imapx_stream_token (
+ stream, &token, &len, cancellable, error);
+ if (tok == IMAPX_TOK_ERROR)
+ goto fail;
+ if (tok != '(') {
+ g_set_error (
+ error, CAMEL_IMAPX_ERROR, 1,
+ "list: expecting '('");
+ goto fail;
+ }
+
+ tok = camel_imapx_stream_token (
+ stream, &token, &len, cancellable, error);
+ while (tok == IMAPX_TOK_STRING || tok == IMAPX_TOK_TOKEN) {
+ camel_imapx_list_response_add_attribute (
+ response, (gchar *) token);
+ tok = camel_imapx_stream_token (
+ stream, &token, &len, cancellable, error);
+ }
+
+ if (tok == IMAPX_TOK_ERROR)
+ goto fail;
+ if (tok != ')') {
+ g_set_error (
+ error, CAMEL_IMAPX_ERROR, 1,
+ "list: expecting ')'");
+ goto fail;
+ }
+
+ /* Add implied attributes (see RFC 5258 section 3.4). */
+
+ /* "\NoInferiors" implies "\HasNoChildren" */
+ attribute = CAMEL_IMAPX_LIST_ATTR_NOINFERIORS;
+ if (camel_imapx_list_response_has_attribute (response, attribute)) {
+ attribute = CAMEL_IMAPX_LIST_ATTR_HASNOCHILDREN;
+ camel_imapx_list_response_add_attribute (response, attribute);
+ }
+
+ /* "\NonExistent" implies "\NoSelect" */
+ attribute = CAMEL_IMAPX_LIST_ATTR_NONEXISTENT;
+ if (camel_imapx_list_response_has_attribute (response, attribute)) {
+ attribute = CAMEL_IMAPX_LIST_ATTR_NOSELECT;
+ camel_imapx_list_response_add_attribute (response, attribute);
+ }
+
+ /* Parse separator. */
+
+ if (!camel_imapx_stream_nstring (stream, &token, cancellable, error))
+ goto fail;
+
+ if (token != NULL)
+ response->priv->separator = *token;
+ else
+ response->priv->separator = '\0';
+
+ /* Parse mailbox. */
+
+ response->priv->mailbox =
+ camel_imapx_parse_mailbox (stream, cancellable, error);
+ if (response->priv->mailbox == NULL)
+ goto fail;
+
+ /* Parse extended info (optional). */
+
+ /* FIXME Actually implement this. */
+
+ return response;
+
+fail:
+ g_clear_object (&response);
+
+ return NULL;
+}
+
+/**
+ * camel_imapx_list_response_hash:
+ * @response: a #CamelIMAPXListResponse
+ *
+ * Generates a hash value for @response based on the mailbox name. This
+ * function is intended for easily hashing a #CamelIMAPXListResponse to
+ * add to a #GHashTable or similar data structure.
+ *
+ * Returns: a hash value for @response
+ *
+ * Since: 3.10
+ **/
+guint
+camel_imapx_list_response_hash (CamelIMAPXListResponse *response)
+{
+ const gchar *mailbox;
+
+ mailbox = camel_imapx_list_response_get_mailbox (response);
+
+ return g_str_hash (mailbox);
+}
+
+/**
+ * camel_imapx_list_response_equal:
+ * @response_a: the first #CamelIMAPXListResponse
+ * @response_b: the second #CamelIMAPXListResponse
+ *
+ * Checks two #CamelIMAPXListResponse instances for equality based on
+ * their mailbox names.
+ *
+ * Returns: %TRUE if @response_a and @response_b are equal
+ *
+ * Since: 3.10
+ **/
+gboolean
+camel_imapx_list_response_equal (CamelIMAPXListResponse *response_a,
+ CamelIMAPXListResponse *response_b)
+{
+ const gchar *mailbox_a;
+ const gchar *mailbox_b;
+
+ mailbox_a = camel_imapx_list_response_get_mailbox (response_a);
+ mailbox_b = camel_imapx_list_response_get_mailbox (response_b);
+
+ return g_str_equal (mailbox_a, mailbox_b);
+}
+
+/**
+ * camel_imapx_list_response_compare:
+ * @response_a: the first #CamelIMAPXListResponse
+ * @response_b: the second #CamelIMAPXListResponse
+ *
+ * Compares two #CamelIMAPXListResponse instances by their mailbox names.
+ *
+ * Returns: a negative value if @response_a compares before @response_b,
+ * zero if they compare equal, or a positive value if @response_a
+ * compares after @response_b
+ *
+ * Since: 3.10
+ **/
+gint
+camel_imapx_list_response_compare (CamelIMAPXListResponse *response_a,
+ CamelIMAPXListResponse *response_b)
+{
+ const gchar *mailbox_a;
+ const gchar *mailbox_b;
+
+ mailbox_a = camel_imapx_list_response_get_mailbox (response_a);
+ mailbox_b = camel_imapx_list_response_get_mailbox (response_b);
+
+ return g_strcmp0 (mailbox_a, mailbox_b);
+}
+
+/**
+ * camel_imapx_list_response_get_mailbox:
+ * @response: a #CamelIMAPXListResponse
+ *
+ * Returns the mailbox name for @response.
+ *
+ * Returns: the mailbox name
+ *
+ * Since: 3.10
+ **/
+const gchar *
+camel_imapx_list_response_get_mailbox (CamelIMAPXListResponse *response)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response), NULL);
+
+ return response->priv->mailbox;
+}
+
+/**
+ * camel_imapx_list_response_get_separator:
+ * @response: a #CamelIMAPXListResponse
+ *
+ * Returns the mailbox path separator character for @response.
+ *
+ * Returns: the mailbox patch separator character
+ *
+ * Since: 3.10
+ **/
+gchar
+camel_imapx_list_response_get_separator (CamelIMAPXListResponse *response)
+{
+ g_return_val_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response), '\0');
+
+ return response->priv->separator;
+}
+
+/* Flag macros appear here in the reference manual,
+ * so also documenting them here in the source code
+ * since the documentation is so repetitive. */
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_NOINFERIORS:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc3501#section-7.2.2">
+ * RFC 3501 section 7.2.2</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_NOSELECT:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc3501#section-7.2.2">
+ * RFC 3501 section 7.2.2</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_MARKED:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc3501#section-7.2.2">
+ * RFC 3501 section 7.2.2</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_UNMARKED:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc3501#section-7.2.2">
+ * RFC 3501 section 7.2.2</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_NONEXISTENT:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc5258#section-3">
+ * RFC 5258 section 3</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc5258#section-3.1">
+ * RFC 5258 section 3.1</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_REMOTE:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc5258#section-3.1">
+ * RFC 5258 section 3.1</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_HASCHILDREN:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc5258#section-4">
+ * RFC 5258 section 4</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * CAMEL_IMAPX_LIST_ATTR_HASNOCHILDREN:
+ *
+ * Refer to <ulink url="http://tools.ietf.org/html/rfc5258#section-4">
+ * RFC 5258 section 4</ulink>.
+ *
+ * Since: 3.10
+ **/
+
+/**
+ * camel_imapx_list_response_add_attribute:
+ * @response: a #CamelIMAPXListResponse
+ * @attribute: a mailbox attribute
+ *
+ * Adds a mailbox attribute to @response. The @attribute should be one of
+ * the LIST attribute macros defined above.
+ *
+ * Since: 3.10
+ **/
+void
+camel_imapx_list_response_add_attribute (CamelIMAPXListResponse *response,
+ const gchar *attribute)
+{
+ g_return_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response));
+ g_return_if_fail (attribute != NULL);
+
+ /* Avoid duplicates. */
+ if (camel_imapx_list_response_has_attribute (response, attribute))
+ return;
+
+ g_queue_push_tail (
+ &response->priv->attributes,
+ (gpointer) g_intern_string (attribute));
+}
+
+/**
+ * camel_imapx_list_response_has_attribute:
+ * @response: a #CamelIMAPXListResponse
+ * @attribute: a mailbox attribute
+ *
+ * Returns whether @response includes the given mailbox attribute. The
+ * @attribute should be one of the LIST attribute macros defined above.
+ *
+ * Returns: %TRUE if @response has @attribute, or else %FALSE
+ *
+ * Since: 3.10
+ **/
+gboolean
+camel_imapx_list_response_has_attribute (CamelIMAPXListResponse *response,
+ const gchar *attribute)
+{
+ GList *match;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response), FALSE);
+ g_return_val_if_fail (attribute != NULL, FALSE);
+
+ match = g_queue_find_custom (
+ &response->priv->attributes, attribute,
+ (GCompareFunc) g_ascii_strcasecmp);
+
+ return (match != NULL);
+}
+
+/**
+ * camel_imapx_list_response_get_summary_flags:
+ * @response: a #CamelIMAPXListResponse
+ *
+ * Converts the relevant mailbox attribute flags in @response to a
+ * #CamelStoreInfoFlags value.
+ *
+ * Returns: a #CamelStoreInfoFlags value
+ *
+ * Since: 3.10
+ **/
+CamelStoreInfoFlags
+camel_imapx_list_response_get_summary_flags (CamelIMAPXListResponse *response)
+{
+ CamelStoreInfoFlags store_info_flags = 0;
+ const gchar *flag;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_LIST_RESPONSE (response), 0);
+
+ flag = CAMEL_IMAPX_LIST_ATTR_NOSELECT;
+ if (camel_imapx_list_response_has_attribute (response, flag))
+ store_info_flags |= CAMEL_STORE_INFO_FOLDER_NOSELECT;
+
+ flag = CAMEL_IMAPX_LIST_ATTR_NOINFERIORS;
+ if (camel_imapx_list_response_has_attribute (response, flag))
+ store_info_flags |= CAMEL_STORE_INFO_FOLDER_NOINFERIORS;
+
+ flag = CAMEL_IMAPX_LIST_ATTR_HASCHILDREN;
+ if (camel_imapx_list_response_has_attribute (response, flag))
+ store_info_flags |= CAMEL_STORE_INFO_FOLDER_CHILDREN;
+
+ flag = CAMEL_IMAPX_LIST_ATTR_HASNOCHILDREN;
+ if (camel_imapx_list_response_has_attribute (response, flag))
+ store_info_flags |= CAMEL_STORE_INFO_FOLDER_NOCHILDREN;
+
+ flag = CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED;
+ if (camel_imapx_list_response_has_attribute (response, flag))
+ store_info_flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
+
+ /* XXX Does "\Marked" mean CAMEL_STORE_INFO_FOLDER_FLAGGED?
+ * Who the heck knows; the enum value is undocumented. */
+
+ return store_info_flags;
+}
+
diff --git a/camel/camel-imapx-list-response.h b/camel/camel-imapx-list-response.h
new file mode 100644
index 0000000..a9e8db7
--- /dev/null
+++ b/camel/camel-imapx-list-response.h
@@ -0,0 +1,115 @@
+/*
+ * camel-imapx-list-response.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_IMAPX_LIST_RESPONSE_H
+#define CAMEL_IMAPX_LIST_RESPONSE_H
+
+#include <camel/camel.h>
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_IMAPX_LIST_RESPONSE \
+ (camel_imapx_list_response_get_type ())
+#define CAMEL_IMAPX_LIST_RESPONSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_IMAPX_LIST_RESPONSE, CamelIMAPXResponse))
+#define CAMEL_IMAPX_LIST_RESPONSE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_IMAPX_LIST_RESPONSE, CamelIMAPXResponseClass))
+#define CAMEL_IS_IMAPX_LIST_RESPONSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_IMAPX_LIST_RESPONSE))
+#define CAMEL_IS_IMAPX_LIST_RESPONSE_CLASS(cls) \
+ (G_TYPE_CHECK_INSTANCE_CLASS \
+ ((cls), CAMEL_TYPE_IMAPX_LIST_RESPONSE))
+#define CAMEL_IMAPX_LIST_RESPONSE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_IMAPX_LIST_RESPONSE, CamelIMAPXResponseClass))
+
+/* RFC 3501 Standard Flags */
+#define CAMEL_IMAPX_LIST_ATTR_MARKED "\\Marked"
+#define CAMEL_IMAPX_LIST_ATTR_NOINFERIORS "\\NoInferiors"
+#define CAMEL_IMAPX_LIST_ATTR_NOSELECT "\\NoSelect"
+#define CAMEL_IMAPX_LIST_ATTR_UNMARKED "\\Unmarked"
+
+/* RFC 5258 "LIST-EXTENDED" Flags */
+#define CAMEL_IMAPX_LIST_ATTR_HASCHILDREN "\\HasChildren"
+#define CAMEL_IMAPX_LIST_ATTR_HASNOCHILDREN "\\HasNoChildren"
+#define CAMEL_IMAPX_LIST_ATTR_NONEXISTENT "\\NonExistent"
+#define CAMEL_IMAPX_LIST_ATTR_REMOTE "\\Remote"
+#define CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED "\\Subscribed"
+
+G_BEGIN_DECLS
+
+typedef struct _CamelIMAPXListResponse CamelIMAPXListResponse;
+typedef struct _CamelIMAPXListResponseClass CamelIMAPXListResponseClass;
+typedef struct _CamelIMAPXListResponsePrivate CamelIMAPXListResponsePrivate;
+
+/**
+ * CamelIMAPXListResponse:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ *
+ * Since: 3.10
+ **/
+struct _CamelIMAPXListResponse {
+ GObject parent;
+ CamelIMAPXListResponsePrivate *priv;
+};
+
+struct _CamelIMAPXListResponseClass {
+ GObjectClass parent_class;
+};
+
+GType camel_imapx_list_response_get_type
+ (void) G_GNUC_CONST;
+CamelIMAPXListResponse *
+ camel_imapx_list_response_new
+ (CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+guint camel_imapx_list_response_hash
+ (CamelIMAPXListResponse *response);
+gboolean camel_imapx_list_response_equal
+ (CamelIMAPXListResponse *response_a,
+ CamelIMAPXListResponse *response_b);
+gint camel_imapx_list_response_compare
+ (CamelIMAPXListResponse *response_a,
+ CamelIMAPXListResponse *response_b);
+const gchar * camel_imapx_list_response_get_mailbox
+ (CamelIMAPXListResponse *response);
+gchar camel_imapx_list_response_get_separator
+ (CamelIMAPXListResponse *response);
+void camel_imapx_list_response_add_attribute
+ (CamelIMAPXListResponse *response,
+ const gchar *attribute);
+gboolean camel_imapx_list_response_has_attribute
+ (CamelIMAPXListResponse *response,
+ const gchar *attribute);
+CamelStoreInfoFlags
+ camel_imapx_list_response_get_summary_flags
+ (CamelIMAPXListResponse *response);
+
+G_END_DECLS
+
+#endif /* CAMEL_IMAPX_LIST_RESPONSE_H */
+
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index 09b5872..c8519df 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -2026,17 +2026,22 @@ imapx_untagged_list (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
- struct _list_info *linfo = NULL;
+ CamelIMAPXListResponse *response;
CamelIMAPXJob *job = NULL;
ListData *data = NULL;
+ const gchar *mailbox;
+ gchar separator;
g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
- linfo = imapx_parse_list (stream, cancellable, error);
- if (linfo == NULL)
+ response = camel_imapx_list_response_new (stream, cancellable, error);
+ if (response == NULL)
return FALSE;
- job = imapx_match_active_job (is, IMAPX_JOB_LIST, linfo->name);
+ mailbox = camel_imapx_list_response_get_mailbox (response);
+ separator = camel_imapx_list_response_get_separator (response);
+
+ job = imapx_match_active_job (is, IMAPX_JOB_LIST, mailbox);
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
@@ -2044,20 +2049,22 @@ imapx_untagged_list (CamelIMAPXServer *is,
// TODO: we want to make sure the names match?
if (data->flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
- c (is->tagprefix, "lsub: '%s' (%c)\n", linfo->name, linfo->separator);
+ c (is->tagprefix, "lsub: '%s' (%c)\n", mailbox, separator);
} else {
- c (is->tagprefix, "list: '%s' (%c)\n", linfo->name, linfo->separator);
+ c (is->tagprefix, "list: '%s' (%c)\n", mailbox, separator);
}
- if (job && g_hash_table_lookup (data->folders, linfo->name) == NULL) {
+ if (job && !g_hash_table_contains (data->folders, response)) {
if (is->priv->context->lsub)
- linfo->flags |= CAMEL_FOLDER_SUBSCRIBED;
- g_hash_table_insert (data->folders, linfo->name, linfo);
+ camel_imapx_list_response_add_attribute (
+ response, CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED);
+ g_hash_table_add (data->folders, g_object_ref (response));
} else {
g_warning ("got list response but no current listing job happening?\n");
- imapx_free_list (linfo);
}
+ g_object_unref (response);
+
return TRUE;
}
@@ -7976,48 +7983,6 @@ camel_imapx_server_expunge (CamelIMAPXServer *is,
return success;
}
-static guint
-imapx_name_hash (gconstpointer key)
-{
- if (g_ascii_strcasecmp (key, "INBOX") == 0)
- return g_str_hash ("INBOX");
- else
- return g_str_hash (key);
-}
-
-static gint
-imapx_name_equal (gconstpointer a,
- gconstpointer b)
-{
- gconstpointer aname = a, bname = b;
-
- if (g_ascii_strcasecmp (a, "INBOX") == 0)
- aname = "INBOX";
- if (g_ascii_strcasecmp (b, "INBOX") == 0)
- bname = "INBOX";
- return g_str_equal (aname, bname);
-}
-
-static void
-imapx_list_flatten (gpointer k,
- gpointer v,
- gpointer d)
-{
- GPtrArray *folders = d;
-
- g_ptr_array_add (folders, v);
-}
-
-static gint
-imapx_list_cmp (gconstpointer ap,
- gconstpointer bp)
-{
- struct _list_info *a = ((struct _list_info **) ap)[0];
- struct _list_info *b = ((struct _list_info **) bp)[0];
-
- return strcmp (a->name, b->name);
-}
-
GPtrArray *
camel_imapx_server_list (CamelIMAPXServer *is,
const gchar *top,
@@ -8036,7 +8001,11 @@ camel_imapx_server_list (CamelIMAPXServer *is,
data = g_slice_new0 (ListData);
data->flags = flags;
data->ext = g_strdup (ext);
- data->folders = g_hash_table_new (imapx_name_hash, imapx_name_equal);
+ data->folders = g_hash_table_new_full (
+ (GHashFunc) camel_imapx_list_response_hash,
+ (GEqualFunc) camel_imapx_list_response_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) NULL);
if (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)
data->pattern = g_strdup_printf ("%s*", encoded_name);
@@ -8057,11 +8026,18 @@ camel_imapx_server_list (CamelIMAPXServer *is,
job->pri += 300;
if (imapx_submit_job (is, job, error)) {
+ GList *list, *link;
+
+ /* Transfer LIST responses from a GHashTable
+ * to a sorted GPtrArray by way of a GList. */
folders = g_ptr_array_new_with_free_func (
- (GDestroyNotify) imapx_free_list);
- g_hash_table_foreach (
- data->folders, imapx_list_flatten, folders);
- g_ptr_array_sort (folders, imapx_list_cmp);
+ (GDestroyNotify) g_object_unref);
+ list = g_list_sort (
+ g_hash_table_get_keys (data->folders),
+ (GCompareFunc) camel_imapx_list_response_compare);
+ for (link = list; link != NULL; link = g_list_next (link))
+ g_ptr_array_add (folders, g_object_ref (link->data));
+ g_list_free (list);
}
g_free (encoded_name);
diff --git a/camel/camel-imapx-store.c b/camel/camel-imapx-store.c
index 02b4094..55bd2cf 100644
--- a/camel/camel-imapx-store.c
+++ b/camel/camel-imapx-store.c
@@ -1054,19 +1054,30 @@ get_folder_info_offline (CamelStore *store,
static void
add_folder_to_summary (CamelIMAPXStore *imapx_store,
CamelIMAPXServer *server,
- struct _list_info *li,
+ CamelIMAPXListResponse *response,
GHashTable *table,
gboolean update_for_lsub)
{
CamelIMAPXStoreInfo *si;
- guint32 new_flags;
CamelFolderInfo *fi;
+ const gchar *mailbox;
+ gchar separator;
+ CamelStoreInfoFlags flags;
+ CamelStoreInfoFlags new_flags;
+
+ mailbox = camel_imapx_list_response_get_mailbox (response);
+ separator = camel_imapx_list_response_get_separator (response);
+
+ /* XXX The flags type transforms from CamelStoreInfoFlags
+ * to CamelFolderInfoFlags about half-way through this.
+ * We should really eliminate the confusing redundancy. */
+ flags = camel_imapx_list_response_get_summary_flags (response);
if (update_for_lsub) {
gchar *full_name;
full_name = camel_imapx_store_summary_path_to_full (
- imapx_store->summary, li->name, li->separator);
+ imapx_store->summary, mailbox, separator);
fi = g_hash_table_lookup (table, full_name);
if (fi != NULL)
fi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
@@ -1076,16 +1087,16 @@ add_folder_to_summary (CamelIMAPXStore *imapx_store,
}
si = camel_imapx_store_summary_add_from_full (
- imapx_store->summary, li->name, li->separator);
+ imapx_store->summary, mailbox, separator);
if (si == NULL)
return;
new_flags =
(si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) |
- (li->flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
+ (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
if (CAMEL_IMAPX_LACK_CAPABILITY (server->cinfo, NAMESPACE))
- imapx_store->dir_sep = li->separator;
+ imapx_store->dir_sep = separator;
if (si->info.flags != new_flags) {
si->info.flags = new_flags;
@@ -1097,8 +1108,8 @@ add_folder_to_summary (CamelIMAPXStore *imapx_store,
fi->full_name = g_strdup (camel_store_info_path (
imapx_store->summary, si));
if (g_ascii_strcasecmp (fi->full_name, "inbox") == 0) {
- li->flags |= CAMEL_FOLDER_SYSTEM;
- li->flags |= CAMEL_FOLDER_TYPE_INBOX;
+ flags |= CAMEL_FOLDER_SYSTEM;
+ flags |= CAMEL_FOLDER_TYPE_INBOX;
fi->display_name = g_strdup (_("Inbox"));
} else {
fi->display_name = g_strdup (
@@ -1109,12 +1120,12 @@ add_folder_to_summary (CamelIMAPXStore *imapx_store,
/* HACK: Some servers report noinferiors for all folders (uw-imapd).
* We just translate this into nochildren, and let the imap
* layer enforce it. See create folder. */
- if (li->flags & CAMEL_FOLDER_NOINFERIORS) {
- li->flags &= ~CAMEL_FOLDER_NOINFERIORS;
- li->flags |= CAMEL_FOLDER_NOCHILDREN;
+ if (flags & CAMEL_FOLDER_NOINFERIORS) {
+ flags &= ~CAMEL_FOLDER_NOINFERIORS;
+ flags |= CAMEL_FOLDER_NOCHILDREN;
}
- fi->flags |= li->flags;
+ fi->flags |= flags;
fi->total = -1;
fi->unread = -1;
@@ -1149,12 +1160,13 @@ fetch_folders_for_pattern (CamelIMAPXStore *imapx_store,
update_for_lsub = FALSE;
for (ii = 0; ii < folders->len; ii++) {
- struct _list_info *li;
+ CamelIMAPXListResponse *response;
- li = g_ptr_array_index (folders, ii);
+ response = g_ptr_array_index (folders, ii);
add_folder_to_summary (
- imapx_store, server, li, table, update_for_lsub);
+ imapx_store, server, response,
+ table, update_for_lsub);
}
g_ptr_array_unref (folders);
diff --git a/camel/camel-imapx-utils.c b/camel/camel-imapx-utils.c
index 86dbd91..7ae683e 100644
--- a/camel/camel-imapx-utils.c
+++ b/camel/camel-imapx-utils.c
@@ -2491,110 +2491,6 @@ imapx_free_status (struct _status_info *sinfo)
g_free (sinfo);
}
-/* FIXME: use tokeniser? */
-/* FIXME: real flags */
-static struct {
- const gchar *name;
- guint32 flag;
-} list_flag_table[] = {
- { "\\NOINFERIORS", CAMEL_FOLDER_NOINFERIORS },
- { "\\NOSELECT", CAMEL_FOLDER_NOSELECT },
- { "\\MARKED", 1<< 16},
- { "\\UNMARKED", 1<< 17},
- { "\\SUBSCRIBED", CAMEL_FOLDER_SUBSCRIBED },
-};
-
-struct _list_info *
-imapx_parse_list (CamelIMAPXStream *is,
- GCancellable *cancellable,
- GError **error)
-/* throws io, parse */
-{
- gint tok, i;
- guint len;
- guchar *token, *p, c;
- struct _list_info * linfo;
-
- /* mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
- * "\Noselect" / "\Unmarked" / flag_extension) ")"
- * SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox */
-
- tok = camel_imapx_stream_token (is, &token, &len, cancellable, NULL);
- if (tok != '(') {
- g_set_error (error, CAMEL_IMAPX_ERROR, 1, "list: expecting '('");
- return NULL;
- }
-
- linfo = g_malloc0 (sizeof (*linfo));
-
- while ((tok = camel_imapx_stream_token (is, &token, &len, cancellable, NULL)) != ')') {
- if (tok == IMAPX_TOK_STRING || tok == IMAPX_TOK_TOKEN) {
- p = token;
- while ((c=*p))
- *p++ = toupper(c);
- for (i = 0; i < G_N_ELEMENTS (list_flag_table); i++)
- if (!strcmp ((gchar *) token, list_flag_table[i].name))
- linfo->flags |= list_flag_table[i].flag;
- } else {
- g_set_error (error, CAMEL_IMAPX_ERROR, 1, "list: execting flag or ')'");
- goto fail;
- }
- }
-
- if (!camel_imapx_stream_nstring (is, &token, cancellable, error))
- goto fail;
-
- linfo->separator = token != NULL ? *token : 0;
-
- if (!camel_imapx_stream_astring (is, &token, cancellable, error))
- goto fail;
-
- linfo->name = camel_utf7_utf8 ((gchar *) token);
-
- goto exit;
-
-fail:
- imapx_free_list (linfo);
- linfo = NULL;
-
-exit:
- return linfo;
-}
-
-gchar *
-imapx_list_get_path (struct _list_info *li)
-{
- gchar *path, *p;
- gint c;
- const gchar *f;
-
- if (li->separator != 0 && li->separator != '/') {
- p = path = alloca (strlen (li->name) * 3 + 1);
- f = li->name;
- while ((c = *f++ & 0xff)) {
- if (c == li->separator)
- *p++ = '/';
- else if (c == '/' || c == '%')
- p += sprintf (p, "%%%02X", c);
- else
- *p++ = c;
- }
- *p = 0;
- } else
- path = li->name;
-
- return camel_utf7_utf8 (path);
-}
-
-void
-imapx_free_list (struct _list_info *linfo)
-{
- if (linfo) {
- g_free (linfo->name);
- g_free (linfo);
- }
-}
-
gboolean
camel_imapx_command_add_qresync_parameter (CamelIMAPXCommand *ic,
CamelFolder *folder)
diff --git a/camel/camel-imapx-utils.h b/camel/camel-imapx-utils.h
index 8a02a44..cd974d9 100644
--- a/camel/camel-imapx-utils.h
+++ b/camel/camel-imapx-utils.h
@@ -330,23 +330,6 @@ struct _state_info *
/* ********************************************************************** */
-/* should this just return a FolderInfo?
- * should this just return the name & flags & separator by reference? */
-struct _list_info {
- guint32 flags : 24;
- gchar separator;
- gchar *name;
-};
-
-struct _list_info *
- imapx_parse_list (struct _CamelIMAPXStream *is,
- GCancellable *cancellable,
- GError **error);
-gchar * imapx_list_get_path (struct _list_info *linfo);
-void imapx_free_list (struct _list_info *linfo);
-
-/* ********************************************************************** */
-
gboolean camel_imapx_command_add_qresync_parameter
(struct _CamelIMAPXCommand *ic,
CamelFolder *folder);
diff --git a/camel/camel.h b/camel/camel.h
index c38229d..1684185 100644
--- a/camel/camel.h
+++ b/camel/camel.h
@@ -145,6 +145,7 @@
#include <camel/camel-imapx-command.h>
#include <camel/camel-imapx-job.h>
#include <camel/camel-imapx-folder.h>
+#include <camel/camel-imapx-list-response.h>
#include <camel/camel-imapx-search.h>
#include <camel/camel-imapx-server.h>
#include <camel/camel-imapx-store-summary.h>
diff --git a/docs/reference/camel/camel-docs.sgml b/docs/reference/camel/camel-docs.sgml
index a11b143..c7047db 100644
--- a/docs/reference/camel/camel-docs.sgml
+++ b/docs/reference/camel/camel-docs.sgml
@@ -204,6 +204,7 @@
<xi:include href="xml/camel-imapx-command.xml"/>
<xi:include href="xml/camel-imapx-folder.xml"/>
<xi:include href="xml/camel-imapx-job.xml"/>
+ <xi:include href="xml/camel-imapx-list-response.xml"/>
<xi:include href="xml/camel-imapx-search.xml"/>
<xi:include href="xml/camel-imapx-server.xml"/>
<xi:include href="xml/camel-imapx-settings.xml"/>
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index c812079..2304c14 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -816,6 +816,41 @@ uidset_state
</SECTION>
<SECTION>
+<FILE>camel-imapx-list-response</FILE>
+<TITLE>CamelIMAPXListResponse</TITLE>
+CamelIMAPXListResponse
+camel_imapx_list_response_new
+camel_imapx_list_response_hash
+camel_imapx_list_response_equal
+camel_imapx_list_response_compare
+camel_imapx_list_response_get_mailbox
+camel_imapx_list_response_get_separator
+CAMEL_IMAPX_LIST_ATTR_NOINFERIORS
+CAMEL_IMAPX_LIST_ATTR_NOSELECT
+CAMEL_IMAPX_LIST_ATTR_MARKED
+CAMEL_IMAPX_LIST_ATTR_UNMARKED
+CAMEL_IMAPX_LIST_ATTR_NONEXISTENT
+CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED
+CAMEL_IMAPX_LIST_ATTR_REMOTE
+CAMEL_IMAPX_LIST_ATTR_HASCHILDREN
+CAMEL_IMAPX_LIST_ATTR_HASNOCHILDREN
+camel_imapx_list_response_add_attribute
+camel_imapx_list_response_has_attribute
+camel_imapx_list_response_get_summary_flags
+<SUBSECTION Standard>
+CAMEL_IMAPX_LIST_RESPONSE
+CAMEL_IS_IMAPX_LIST_RESPONSE
+CAMEL_TYPE_IMAPX_LIST_RESPONSE
+CAMEL_IMAPX_LIST_RESPONSE_CLASS
+CAMEL_IS_IMAPX_LIST_RESPONSE_CLASS
+CAMEL_IMAPX_LIST_RESPONSE_GET_CLASS
+CamelIMAPXListResponseClass
+camel_imapx_list_response_get_type
+<SUBSECTION Private>
+CamelIMAPXListResponsePrivate
+</SECTION>
+
+<SECTION>
<FILE>camel-imapx-search</FILE>
<TITLE>CamelIMAPXSearch</TITLE>
CamelIMAPXSearch
diff --git a/docs/reference/camel/camel.types b/docs/reference/camel/camel.types
index 1c71e7a..424905e 100644
--- a/docs/reference/camel/camel.types
+++ b/docs/reference/camel/camel.types
@@ -17,6 +17,7 @@ camel_folder_summary_get_type
camel_gpg_context_get_type
camel_html_parser_get_type
camel_imapx_folder_get_type
+camel_imapx_list_response_get_type
camel_imapx_search_get_type
camel_imapx_server_get_type
camel_imapx_settings_get_type
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]