aboutsummaryrefslogtreecommitdiffstats
path: root/camel/providers/imap/camel-imap-fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/providers/imap/camel-imap-fetch.c')
-rw-r--r--camel/providers/imap/camel-imap-fetch.c509
1 files changed, 0 insertions, 509 deletions
diff --git a/camel/providers/imap/camel-imap-fetch.c b/camel/providers/imap/camel-imap-fetch.c
deleted file mode 100644
index 5d703e61dc..0000000000
--- a/camel/providers/imap/camel-imap-fetch.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Authors: Dan Winship <danw@helixcode.com>
- *
- * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
- *
- */
-
-#include "config.h"
-
-#include <ctype.h>
-#include <string.h>
-#include "camel-imap-command.h"
-#include "camel-imap-folder.h"
-#include "camel-imap-summary.h"
-#include "camel-imap-utils.h"
-#include "camel-imap-private.h"
-
-#include "camel-internet-address.h"
-#include "camel-mime-message.h"
-#include "camel-mime-utils.h"
-#include "camel-stream-mem.h"
-
-static const char *imap_protocol_get_summary_specifier (CamelImapStore *store);
-
-static CamelMessageInfo *parse_headers (char **headers_p);
-static CamelMessageContentInfo *parse_body (CamelFolderSummary *summary,
- char **body_p,
- const char *part_specifier);
-
-static void skip_astring (char **str_p);
-
-/**
- * imap_add_to_summary:
- * @folder: the (IMAP) folder
- * @first: the sequence number of the first message to add
- * @last: the sequence number of the last message to add
- * @changes: a CamelFolderChangeInfo structure to update
- * @ex: a CamelException
- *
- * This fetches information about the messages in the indicated range
- * and updates the folder's summary information. As a side effect, it may
- * also cache partial messages in the folder message cache.
- **/
-void
-imap_add_to_summary (CamelFolder *folder, int first, int last,
- CamelFolderChangeInfo *changes, CamelException *ex)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- CamelImapResponse *response;
- GPtrArray *headers, *messages;
- const char *summary_specifier;
- char *p, *uid;
- int i, seq;
- CamelMessageInfo *mi;
- CamelMessageContentInfo *content;
- guint32 flags, size;
-
- summary_specifier = imap_protocol_get_summary_specifier (store);
- CAMEL_IMAP_STORE_LOCK(store, command_lock);
- if (first == last) {
- response = camel_imap_command (store, folder, ex,
- "FETCH %d (%s)", first,
- summary_specifier);
- } else {
- response = camel_imap_command (store, folder, ex,
- "FETCH %d:%d (%s)", first,
- last, summary_specifier);
- }
- CAMEL_IMAP_STORE_UNLOCK(store, command_lock);
- if (!response)
- return;
-
- messages = g_ptr_array_new ();
- g_ptr_array_set_size (messages, last - first + 1);
- headers = response->untagged;
- for (i = 0; i < headers->len; i++) {
- p = headers->pdata[i];
- if (!g_strncasecmp (p, "* fetch ", 8))
- continue;
- seq = strtoul (p + 8, &p, 10);
- if (!seq || seq < camel_folder_summary_count (folder->summary))
- continue;
-
- mi = messages->pdata[seq - first];
- flags = size = 0;
- content = NULL;
- uid = NULL;
- while (p && *p != ')') {
- if (*p == ' ')
- p++;
- if (!g_strncasecmp (p, "flags ", 6)) {
- p += 6;
- /* FIXME user flags */
- flags = imap_parse_flag_list (&p);
- } else if (!g_strncasecmp (p, "size ", 5)) {
- size = strtoul (p + 5, &p, 10);
- } else if (!g_strncasecmp (p, "uid ", 4)) {
- uid = p + 4;
- strtoul (uid, &p, 10);
- uid = g_strndup (uid, p - uid);
- } else if (!g_strncasecmp (p, "body ", 5)) {
- p += 5;
- content = parse_body (folder->summary, &p, "");
- } else if (!g_strncasecmp (p, "body[header] ", 13) ||
- !g_strncasecmp (p, "rfc822.header ", 14)) {
- p = strchr (p + 13, ' ');
- mi = parse_headers (&p);
- } else {
- g_warning ("Waiter, I did not order this %.*s",
- (int)strcspn (p, " \n"), p);
- p = NULL;
- }
- }
-
- /* Ideally we got everything on one line, but if we
- * we didn't, and we didn't get the body yet, then we
- * have to postpone this line for later.
- */
- if (mi == NULL) {
- p = headers->pdata[i];
- g_ptr_array_remove_index (headers, i);
- g_ptr_array_add (headers, p);
- continue;
- }
-
- messages->pdata[seq - first] = mi;
- if (uid)
- camel_message_info_set_uid (mi, uid);
- if (flags)
- mi->flags = flags;
- if (content)
- mi->content = content;
- if (size)
- mi->size = size;
- }
- camel_imap_response_free (response);
-
- for (i = 0; i < messages->len; i++) {
- mi = messages->pdata[i];
- camel_folder_summary_add (folder->summary, mi);
- }
- g_ptr_array_free (messages, TRUE);
-}
-
-static const char *
-imap_protocol_get_summary_specifier (CamelImapStore *store)
-{
- if (store->server_level >= IMAP_LEVEL_IMAP4REV1)
- return "UID FLAGS RFC822.SIZE BODY BODY.PEEK[HEADER]";
- else
- return "UID FLAGS RFC822.SIZE BODY RFC822.HEADER";
-}
-
-/**
- * skip_char:
- * @str_p: a pointer to a string
- * @ch: the character to skip
- *
- * Skip the specified character, or fail. Updates the position of
- * *@str_p on success, sets it to %NULL on failure.
- **/
-static inline void
-skip_char (char **str_p, char ch)
-{
- if (*str_p && **str_p == ch)
- *str_p = *str_p + 1;
- else
- *str_p = NULL;
-}
-
-/**
- * skip_astring:
- * @str_p: a pointer to a string
- *
- * Skip an astring, or fail. Updates the position of *@str_p on
- * success, sets it to %NULL on failure.
- **/
-static void
-skip_astring (char **str_p)
-{
- char *str = *str_p;
-
- if (!str)
- return;
- else if (*str == '"') {
- while (*++str && *str != '"') {
- if (*str == '\\') {
- str++;
- if (!*str)
- break;
- }
- }
- if (*str == '"')
- *str_p = str + 1;
- else
- *str_p = NULL;
- } else if (*str == '{') {
- unsigned long len;
-
- len = strtoul (str + 1, &str, 10);
- if (*str != '}' || *(str + 1) != '\n' ||
- strlen (str + 2) < len) {
- *str_p = NULL;
- return;
- }
- *str_p = str + 2 + len;
- } else {
- /* We assume the string is well-formed and don't
- * bother making sure it's a valid atom.
- */
- while (*str && *str != ')' && *str != ' ')
- str++;
- *str_p = str;
- }
-}
-
-/**
- * skip_list:
- * @str_p: a pointer to the open parenthesis of a list
- *
- * Skips over a list of astrings and lists. Updates the position of
- * *@str_p on success, sets it to %NULL on failure.
- **/
-void
-skip_list (char **str_p)
-{
- skip_char (str_p, '(');
- while (*str_p && **str_p != ')') {
- if (**str_p == '(')
- skip_list (str_p);
- else
- skip_astring (str_p);
- if (*str_p && **str_p == ' ')
- skip_char (str_p, ' ');
- }
- skip_char (str_p, ')');
-}
-
-/**
- * parse_params:
- * @parms_p: a pointer to the start of an IMAP "body_fld_param".
- * @ct: a content-type structure
- *
- * This parses the body_fld_param and sets parameters on @ct
- * appropriately.
- *
- * On a successful return, *@params_p will be set to point to the
- * character after the last character of the body_fld_param. On
- * failure, it will be set to %NULL.
- **/
-static void
-parse_params (char **parms_p, struct _header_content_type *ct)
-{
- char *parms = *parms_p, *name, *value;
- int len;
-
- if (!g_strncasecmp (parms, "nil", 3)) {
- *parms_p += 3;
- return;
- }
-
- if (*parms++ != '(') {
- *parms_p = NULL;
- return;
- }
-
- while (*parms == '(') {
- parms++;
-
- name = imap_parse_nstring (&parms, &len);
- value = imap_parse_nstring (&parms, &len);
-
- if (name && value)
- header_content_type_set_param (ct, name, value);
- g_free (name);
- g_free (value);
-
- if (!parms)
- break;
- if (*parms++ != ')') {
- parms = NULL;
- break;
- }
- }
-
- if (!parms || *parms++ != ')') {
- *parms_p = NULL;
- return;
- }
- *parms_p = parms;
-}
-
-static CamelMessageContentInfo *
-parse_body (CamelFolderSummary *summary, char **body_p,
- const char *part_specifier)
-{
- char *body = *body_p;
- CamelMessageContentInfo *ci;
- CamelImapMessageContentInfo *ici;
- char *child_specifier;
- int speclen, len;
-
- if (*body++ != '(') {
- *body_p = NULL;
- return NULL;
- }
-
- ci = camel_folder_summary_content_info_new (summary);
- ici = (CamelImapMessageContentInfo *)ci;
- ici->part_specifier = g_strdup (part_specifier);
-
- if (*body == '(') {
- /* multipart */
- GPtrArray *children;
- CamelMessageContentInfo *child;
- char *subtype;
- int i;
-
- speclen = strlen (part_specifier);
- child_specifier = g_malloc (speclen + 10);
- memcpy (child_specifier, part_specifier, speclen);
- child_specifier[speclen] = '.';
-
- /* Parse the child body parts */
- children = g_ptr_array_new ();
- i = 0;
- while (body && *body == '(') {
- sprintf (child_specifier + speclen + 1, "%d", i++);
- child = parse_body (summary, &body, child_specifier);
- if (!child)
- break;
- child->parent = ci;
- g_ptr_array_add (children, child);
- }
- g_free (child_specifier);
- skip_char (&body, ' ');
-
- /* If there is a parse error, or there are no children,
- * abort.
- */
- if (!body || !children->len) {
- for (i = 0; i < children->len; i++) {
- child = children->pdata[i];
- camel_folder_summary_content_info_free (summary, child);
- }
- g_ptr_array_free (children, TRUE);
- camel_folder_summary_content_info_free (summary, ci);
- *body_p = NULL;
- return NULL;
- }
-
- /* Chain the children. */
- ci->childs = children->pdata[0];
- for (i = 0; i < children->len - 1; i++) {
- child = children->pdata[i];
- child->next = children->pdata[i + 1];
- }
- g_ptr_array_free (children, TRUE);
-
- /* Parse the multipart subtype */
- subtype = imap_parse_string (&body, &len);
- ci->type = header_content_type_new ("multipart", subtype);
- g_free (subtype);
- } else {
- /* single part */
- char *type, *subtype;
-
- type = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- subtype = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- if (!body) {
- camel_folder_summary_content_info_free (summary, ci);
- *body_p = NULL;
- return NULL;
- }
- ci->type = header_content_type_new (type, subtype);
- parse_params (&body, ci->type);
- skip_char (&body, ' ');
-
- ci->id = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- ci->description = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- ci->encoding = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- ci->size = strtoul (body, &body, 10);
-
- if (header_content_type_is (ci->type, "message", "rfc822")) {
- skip_char (&body, ' ');
- ici->message_info = camel_folder_summary_info_new (summary);
- skip_list (&body); /* envelope */
- skip_char (&body, ' ');
- ci->childs = parse_body (summary, &body,
- part_specifier);
- skip_char (&body, ' ');
- strtoul (body, &body, 10);
- } else if (header_content_type_is (ci->type, "text", "*"))
- strtoul (body, &body, 10);
-
- g_free (type);
- g_free (subtype);
- }
-
- if (!body || *body++ != ')') {
- *body_p = NULL;
- camel_folder_summary_content_info_free (summary, ci);
- return NULL;
- }
-
- *body_p = body;
- return ci;
-}
-
-void
-parse_bodypart (char **body_p, CamelFolder *folder, CamelMessageInfo *mi)
-{
- CamelMessageContentInfo *ci;
- char *body = *body_p;
- int num;
-
- /* Skip "body[" */
- body += 5;
- ci = mi->content;
-
- /* Parse the 'nz_number *["." nz_number]' prefix. This is fun,
- * because the numbers mean different things depending on where
- * you are. See RFC 2060 for details.
- */
- while (isdigit((unsigned char)*body)) {
- num = strtoul (body, &body, 10);
- if (num == 0 || (*body != '.' && *body != ']')) {
- *body = NULL;
- return;
- }
-
- if (header_content_type_is (ci->type, "multipart", "*")) {
- ci = ci->childs;
- while (ci && --num)
- ci = ci->next;
- if (!ci) {
- *body = NULL;
- return;
- }
- } else if (num != 1) {
- *body = NULL;
- return;
- }
-
- if (*body == ']')
- break;
-
- if (isdigit ((unsigned char)*++body) &&
- header_content_type_is (ci->type, "message", "rfc822")) {
- mi = ((CamelImapMessageContentInfo *)ci)->message_info;
- ci = mi->content;
- }
- }
-
- if (!g_strncasecmp (body, "header] ", 8)) {
- char *headers;
- int len;
- CamelMimeMessage *msg;
- CamelStream *stream;
-
- body += 9;
- mi = parse_headers (&body, folder);
- /* XXX */
- } else if (!g_strncasecmp (body, "] ", 2)) {
- CamelImapMessageContentInfo *ici = (CamelImapMessageContentInfo *)ci;
- body += 2;
- /* XXX */
- } else
- *body = NULL;
-}
-
-CamelMessageInfo *
-imap_parse_headers (char **headers_p, CamelFolder *folder)
-{
- CamelMimeMessage *msg;
- CamelStream *stream;
- char *headers;
- int len;
-
- headers = imap_parse_nstring (headers_p, &len);
- msg = camel_mime_message_new ();
- stream = camel_stream_mem_new_with_buffer (headers, len);
- g_free (headers);
- camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream);
- camel_object_unref (CAMEL_OBJECT (stream));
-
- mi = camel_folder_summary_info_new_from_message (folder->summary, msg);
- camel_imap_folder_cache_message (folder, mi, msg);
-}