aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap
diff options
context:
space:
mode:
authorJeffrey Stedfast <fejj@ximian.com>2002-05-16 07:46:27 +0800
committerJeffrey Stedfast <fejj@src.gnome.org>2002-05-16 07:46:27 +0800
commit442cb01bee426d4a716485759ea093c773f5321a (patch)
tree3bcd14da99c58e946a8ae7aaa192d2f27834b20e /camel/providers/imap
parent80836cd3871291deb97325372a25d6f4a5ff2a4d (diff)
downloadgsoc2013-evolution-442cb01bee426d4a716485759ea093c773f5321a.tar.gz
gsoc2013-evolution-442cb01bee426d4a716485759ea093c773f5321a.tar.zst
gsoc2013-evolution-442cb01bee426d4a716485759ea093c773f5321a.zip
New function to parse a NAMESPACE response properly.
2002-05-15 Jeffrey Stedfast <fejj@ximian.com> * providers/imap/camel-imap-utils.c (imap_parse_namespace_response): New function to parse a NAMESPACE response properly. (imap_namespaces_destroy): New function to destroy the returned structure from the above function. svn path=/trunk/; revision=16927
Diffstat (limited to 'camel/providers/imap')
-rw-r--r--camel/providers/imap/camel-imap-folder.c6
-rw-r--r--camel/providers/imap/camel-imap-store.c12
-rw-r--r--camel/providers/imap/camel-imap-utils.c276
-rw-r--r--camel/providers/imap/camel-imap-utils.h21
4 files changed, 283 insertions, 32 deletions
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index a957e1f776..f8d3a59594 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -1770,7 +1770,7 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex)
}
if (body)
- imap_parse_body (&body, folder, mi->content);
+ imap_parse_body ((const char **) &body, folder, mi->content);
if (fetch_data)
g_datalist_clear (&fetch_data);
@@ -2326,7 +2326,7 @@ parse_fetch_response (CamelImapFolder *imap_folder, char *response)
response += 7;
}
- body = imap_parse_nstring (&response, &body_len);
+ body = imap_parse_nstring ((const char **) &response, &body_len);
if (!response) {
g_free (part_spec);
break;
@@ -2341,7 +2341,7 @@ parse_fetch_response (CamelImapFolder *imap_folder, char *response)
!g_strncasecmp (response, "BODYSTRUCTURE ", 14)) {
response = strchr (response, ' ') + 1;
start = response;
- imap_skip_list (&response);
+ imap_skip_list ((const char **) &response);
g_datalist_set_data_full (&data, "BODY", g_strndup (start, response - start), g_free);
} else if (!g_strncasecmp (response, "UID ", 4)) {
int len;
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 6b7c293cca..4d983bebf0 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -745,6 +745,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
CamelImapStore *store = CAMEL_IMAP_STORE (service);
CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service);
CamelImapResponse *response;
+ struct _namespaces *namespaces;
char *result, *name, *path;
FILE *storeinfo;
int i, flags;
@@ -778,15 +779,20 @@ imap_connect_online (CamelService *service, CamelException *ex)
result = camel_imap_response_extract (store, response, "NAMESPACE", ex);
if (!result)
goto done;
-
+
+ /* new code... */
+ namespaces = imap_parse_namespace_response (result);
+ imap_namespaces_destroy (namespaces);
+ /* end new code */
+
name = strstrcase (result, "NAMESPACE ((");
if (name) {
char *sep;
name += 12;
- store->namespace = imap_parse_string (&name, &len);
+ store->namespace = imap_parse_string ((const char **) &name, &len);
if (name && *name++ == ' ') {
- sep = imap_parse_string (&name, &len);
+ sep = imap_parse_string ((const char **) &name, &len);
if (sep) {
store->dir_sep = *sep;
((CamelStore *)store)->dir_sep = store->dir_sep;
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 304ef97448..753e341316 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -39,14 +39,243 @@ imap_next_word (const char *buf)
const char *word;
/* skip over current word */
- for (word = buf; *word && *word != ' '; word++);
+ word = buf;
+ while (*word && *word != ' ')
+ word++;
/* skip over white space */
- for ( ; *word && *word == ' '; word++);
+ while (*word && *word == ' ')
+ word++;
return word;
}
+
+static void
+imap_namespace_destroy (struct _namespace *namespace)
+{
+ struct _namespace *node, *next;
+
+ node = namespace;
+ while (node) {
+ next = node->next;
+ g_free (node->prefix);
+ g_free (node);
+ node = next;
+ }
+}
+
+void
+imap_namespaces_destroy (struct _namespaces *namespaces)
+{
+ if (namespaces) {
+ imap_namespace_destroy (namespaces->personal);
+ imap_namespace_destroy (namespaces->other);
+ imap_namespace_destroy (namespaces->shared);
+ g_free (namespaces);
+ }
+}
+
+static gboolean
+imap_namespace_decode (const char **in, struct _namespace **namespace)
+{
+ struct _namespace *list, *tail, *node;
+ const char *inptr;
+ char *astring;
+ size_t len;
+
+ inptr = *in;
+
+ list = NULL;
+ tail = (struct _namespace *) &list;
+
+ if (g_strncasecmp (inptr, "NIL", 3) != 0) {
+ if (*inptr++ != '(')
+ goto exception;
+
+ while (*inptr && *inptr != ')') {
+ if (*inptr++ != '(')
+ goto exception;
+
+ node = g_new (struct _namespace, 1);
+ node->next = NULL;
+
+ /* get the namespace prefix */
+ astring = imap_parse_astring (&inptr, &len);
+ if (!astring) {
+ g_free (node);
+ goto exception;
+ }
+
+ /* decode IMAP's modified UTF-7 into UTF-8 */
+ node->prefix = imap_mailbox_decode (astring, len);
+ g_free (astring);
+ if (!node->prefix) {
+ g_free (node);
+ goto exception;
+ }
+
+ tail->next = node;
+ tail = node;
+
+ /* get the namespace directory delimiter */
+ inptr = imap_next_word (inptr);
+
+ if (!g_strncasecmp (inptr, "NIL", 3)) {
+ inptr = imap_next_word (inptr);
+ node->delim = '\0';
+ } else if (*inptr++ == '"') {
+ if (*inptr == '\\')
+ inptr++;
+
+ node->delim = *inptr++;
+
+ if (*inptr++ != '"')
+ goto exception;
+ } else
+ goto exception;
+
+ if (*inptr == ' ') {
+ /* parse extra flags... for now we
+ don't save them, but in the future
+ we may want to? */
+ while (*inptr == ' ')
+ inptr++;
+
+ while (*inptr && *inptr != ')') {
+ /* this should be a QSTRING or ATOM */
+ inptr = imap_next_word (inptr);
+ if (*inptr == '(') {
+ /* skip over the param list */
+ imap_skip_list (&inptr);
+ }
+
+ while (*inptr == ' ')
+ inptr++;
+ }
+ }
+
+ if (*inptr++ != ')')
+ goto exception;
+
+ /* there shouldn't be spaces according to the
+ ABNF grammar, but we all know how closely
+ people follow specs */
+ while (*inptr == ' ')
+ inptr++;
+ }
+
+ if (*inptr == ')')
+ inptr++;
+ } else {
+ inptr += 3;
+ }
+
+ *in = inptr;
+ *namespace = list;
+
+ return TRUE;
+
+ exception:
+
+ /* clean up any namespaces we may have allocated */
+ imap_namespace_destroy (list);
+
+ return FALSE;
+}
+
+static void
+namespace_dump (struct _namespace *namespace)
+{
+ struct _namespace *node;
+
+ if (namespace) {
+ printf ("(");
+ node = namespace;
+ while (node) {
+ printf ("(\"%s\" ", node->prefix);
+ if (node->delim)
+ printf ("\"%c\")", node->delim);
+ else
+ printf ("NUL)");
+
+ node = node->next;
+ if (node)
+ printf (" ");
+ }
+
+ printf (")");
+ } else {
+ printf ("NIL");
+ }
+}
+
+static void
+namespaces_dump (struct _namespaces *namespaces)
+{
+ printf ("namespace dump: ");
+ namespace_dump (namespaces->personal);
+ printf (" ");
+ namespace_dump (namespaces->other);
+ printf (" ");
+ namespace_dump (namespaces->shared);
+ printf ("\n");
+}
+
+struct _namespaces *
+imap_parse_namespace_response (const char *response)
+{
+ struct _namespaces *namespaces;
+ const char *inptr;
+
+ printf ("parsing: %s\n", response);
+
+ if (*response != '*')
+ return NULL;
+
+ inptr = imap_next_word (response);
+ if (g_strncasecmp (inptr, "NAMESPACE", 9) != 0)
+ return NULL;
+
+ inptr = imap_next_word (inptr);
+
+ namespaces = g_new (struct _namespaces, 1);
+ namespaces->personal = NULL;
+ namespaces->other = NULL;
+ namespaces->shared = NULL;
+
+ if (!imap_namespace_decode (&inptr, &namespaces->personal))
+ goto exception;
+
+ if (*inptr != ' ')
+ goto exception;
+
+ while (*inptr == ' ')
+ inptr++;
+
+ if (!imap_namespace_decode (&inptr, &namespaces->other))
+ goto exception;
+
+ if (*inptr != ' ')
+ goto exception;
+
+ while (*inptr == ' ')
+ inptr++;
+
+ if (!imap_namespace_decode (&inptr, &namespaces->shared))
+ goto exception;
+
+ namespaces_dump (namespaces);
+
+ return namespaces;
+
+ exception:
+
+ imap_namespaces_destroy (namespaces);
+
+ return NULL;
+}
+
/**
* imap_parse_list_response:
* @store: the IMAP store whose list response we're parsing
@@ -122,7 +351,7 @@ imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, ch
/* get the folder name */
word = imap_next_word (word);
- astring = imap_parse_astring ((char **) &word, &len);
+ astring = imap_parse_astring (&word, &len);
if (!astring)
return FALSE;
@@ -351,9 +580,9 @@ imap_is_atom(const char *in)
* latter, it will point to the character after the NIL.)
**/
char *
-imap_parse_string_generic (char **str_p, size_t *len, int type)
+imap_parse_string_generic (const char **str_p, size_t *len, int type)
{
- char *str = *str_p;
+ const char *str = *str_p;
char *out;
if (!str)
@@ -401,13 +630,13 @@ imap_parse_string_generic (char **str_p, size_t *len, int type)
*len = 0;
return NULL;
} else if (type == IMAP_ASTRING && imap_is_atom_char ((unsigned char)*str)) {
- while (imap_is_atom_char ((unsigned char)*str))
+ while (imap_is_atom_char ((unsigned char) *str))
str++;
*len = str - *str_p;
- str = g_strndup (*str_p, *len);
+ out = g_strndup (*str_p, *len);
*str_p += *len;
- return str;
+ return out;
} else {
*str_p = NULL;
return NULL;
@@ -415,19 +644,19 @@ imap_parse_string_generic (char **str_p, size_t *len, int type)
}
static inline void
-skip_char (char **str_p, char ch)
+skip_char (const char **in, char ch)
{
- if (*str_p && **str_p == ch)
- *str_p = *str_p + 1;
+ if (*in && **in == ch)
+ *in = *in + 1;
else
- *str_p = NULL;
+ *in = NULL;
}
/* Skip atom, string, or number */
static void
-skip_asn (char **str_p)
+skip_asn (const char **str_p)
{
- char *str = *str_p;
+ const char *str = *str_p;
if (!str)
return;
@@ -446,7 +675,7 @@ skip_asn (char **str_p)
} else if (*str == '{') {
unsigned long len;
- len = strtoul (str + 1, &str, 10);
+ len = strtoul (str + 1, (char **) &str, 10);
if (*str != '}' || *(str + 1) != '\n' ||
strlen (str + 2) < len) {
*str_p = NULL;
@@ -464,7 +693,7 @@ skip_asn (char **str_p)
}
void
-imap_skip_list (char **str_p)
+imap_skip_list (const char **str_p)
{
skip_char (str_p, '(');
while (*str_p && **str_p != ')') {
@@ -479,9 +708,10 @@ imap_skip_list (char **str_p)
}
static void
-parse_params (char **parms_p, CamelContentType *type)
+parse_params (const char **parms_p, CamelContentType *type)
{
- char *parms = *parms_p, *name, *value;
+ const char *parms = *parms_p;
+ char *name, *value;
int len;
if (!g_strncasecmp (parms, "nil", 3)) {
@@ -526,10 +756,10 @@ parse_params (char **parms_p, CamelContentType *type)
* set to %NULL and @ci will be unchanged.
**/
void
-imap_parse_body (char **body_p, CamelFolder *folder,
+imap_parse_body (const char **body_p, CamelFolder *folder,
CamelMessageContentInfo *ci)
{
- char *body = *body_p;
+ const char *body = *body_p;
CamelMessageContentInfo *child;
CamelContentType *type;
size_t len;
@@ -615,7 +845,7 @@ imap_parse_body (char **body_p, CamelFolder *folder,
encoding = imap_parse_string (&body, &len);
skip_char (&body, ' ');
if (body)
- size = strtoul (body, &body, 10);
+ size = strtoul (body, (char **) &body, 10);
child = NULL;
if (header_content_type_is (type, "message", "rfc822")) {
@@ -628,11 +858,11 @@ imap_parse_body (char **body_p, CamelFolder *folder,
camel_folder_summary_content_info_free (folder->summary, child);
skip_char (&body, ' ');
if (body)
- strtoul (body, &body, 10);
+ strtoul (body, (char **) &body, 10);
child->parent = ci;
} else if (header_content_type_is (type, "text", "*")) {
if (body)
- strtoul (body, &body, 10);
+ strtoul (body, (char **) &body, 10);
}
if (body) {
diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h
index 7078e12335..9692cc4e38 100644
--- a/camel/providers/imap/camel-imap-utils.h
+++ b/camel/providers/imap/camel-imap-utils.h
@@ -35,6 +35,21 @@ extern "C" {
const char *imap_next_word (const char *buf);
+struct _namespace {
+ struct _namespace *next;
+ char *prefix;
+ char delim;
+};
+
+struct _namespaces {
+ struct _namespace *personal;
+ struct _namespace *other;
+ struct _namespace *shared;
+};
+
+void imap_namespaces_destroy (struct _namespaces *namespaces);
+struct _namespaces *imap_parse_namespace_response (const char *response);
+
#define IMAP_LIST_FLAG_NOINFERIORS (1 << 0)
#define IMAP_LIST_FLAG_NOSELECT (1 << 1)
#define IMAP_LIST_FLAG_MARKED (1 << 2)
@@ -51,7 +66,7 @@ guint32 imap_parse_flag_list (char **flag_list);
enum { IMAP_STRING, IMAP_NSTRING, IMAP_ASTRING };
-char *imap_parse_string_generic (char **str_p, size_t *len, int type);
+char *imap_parse_string_generic (const char **str_p, size_t *len, int type);
#define imap_parse_string(str_p, len_p) \
imap_parse_string_generic (str_p, len_p, IMAP_STRING)
@@ -60,13 +75,13 @@ char *imap_parse_string_generic (char **str_p, size_t *len, int type);
#define imap_parse_astring(str_p, len_p) \
imap_parse_string_generic (str_p, len_p, IMAP_ASTRING)
-void imap_parse_body (char **body_p, CamelFolder *folder,
+void imap_parse_body (const char **body_p, CamelFolder *folder,
CamelMessageContentInfo *ci);
gboolean imap_is_atom (const char *in);
char *imap_quote_string (const char *str);
-void imap_skip_list (char **str_p);
+void imap_skip_list (const char **str_p);
char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid);
GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids);