removed imap.c/h from providers/imap

began implementing search functionality

svn path=/trunk/; revision=3613
This commit is contained in:
Jeffrey Stedfast
2000-06-17 19:00:58 +00:00
parent 26788bf81f
commit cde9231ca7
4 changed files with 101 additions and 971 deletions

View File

@ -1,3 +1,16 @@
2000-06-17 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-folder.c (imap_search_by_expression):
Began to implement, need to get information on how to
deconstruct @expression into an IMAP search expression and
parse the results.
(imap_init): Now queries the IMAP provider for CAPABILITY to
determine if SEARCH is implemented or not.
* providers/imap/imap.c: Removed - no longer a need to have
this as an example for anyone interesting to help mecode IMAP
support.
2000-06-16 Jeffrey Stedfast <fejj@helixcode.com>
* providers/imap/camel-imap-folder.c (imap_sync): Added code

View File

@ -85,11 +85,11 @@ static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *mes
CamelException *ex);
#endif
static void imap_delete_message_by_uid(CamelFolder *folder, const gchar *uid, CamelException *ex);
static void imap_delete_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex);
static const CamelMessageInfo *imap_summary_get_by_uid(CamelFolder *f, const char *uid);
static const CamelMessageInfo *imap_summary_get_by_uid (CamelFolder *f, const char *uid);
static GList *imap_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex);
static GList *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex);
static void imap_finalize (GtkObject *object);
@ -139,8 +139,8 @@ camel_imap_folder_init (gpointer object, gpointer klass)
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
folder->has_summary_capability = FALSE;
folder->has_search_capability = FALSE;
folder->has_summary_capability = TRUE;
folder->has_search_capability = FALSE; /* default - we have to query IMAP to know for sure */
imap_folder->count = -1;
}
@ -182,6 +182,7 @@ camel_imap_folder_new (CamelStore *parent, CamelException *ex)
static void
imap_finalize (GtkObject *object)
{
/* TODO: do we need to do more here? */
GTK_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -202,9 +203,26 @@ 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 = FALSE; /* TODO: double-check this */
folder->has_search_capability = TRUE; /* This is really a "maybe" */
folder->has_summary_capability = TRUE;
/* now lets find out if we can do searches... */
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "CAPABILITY");
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
"Could not get capabilities on IMAP server %s: %s.",
service->url->host,
status == CAMEL_IMAP_ERR ? result :
"Unknown error");
}
if (strstr (result, "SEARCH"))
folder->has_search_capability = TRUE;
else
folder->has_search_capability = FALSE;
g_free (result);
/* some IMAP daemons support user-flags *
* I would not, however, rely on this feature as *
@ -230,7 +248,7 @@ imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_fo
status == CAMEL_IMAP_ERR ? result :
"Unknown error");
}
g_free(result);
g_free (result);
}
static void
@ -296,12 +314,12 @@ imap_exists (CamelFolder *folder, CamelException *ex)
/* look to see if any of those subfolders match... */
max = lsub->len;
for (i = 0; i < max; i++)
if (!strcmp(g_ptr_array_index(lsub, i), folder->full_name))
{
for (i = 0; i < max; i++) {
if (!strcmp(g_ptr_array_index (lsub, i), folder->full_name)) {
exists = TRUE;
break;
}
}
g_ptr_array_free (lsub, TRUE);
@ -330,7 +348,6 @@ imap_delete (CamelFolder *folder, gboolean recurse, CamelException *ex)
if (!folder_already_exists)
return TRUE;
/* call default implementation.
It should delete the messages in the folder
and recurse the operation to subfolders */
@ -382,16 +399,16 @@ imap_get_message_count (CamelFolder *folder, CamelException *ex)
/* 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")) != NULL) {
msg_count += strlen("MESSAGES") + 1;
if ((msg_count = strstr (result, "MESSAGES")) != NULL) {
msg_count += strlen ("MESSAGES") + 1;
for ( ; *msg_count == ' '; msg_count++);
/* we should now be pointing to the message count */
imap_folder->count = atoi(msg_count);
imap_folder->count = atoi (msg_count);
}
}
g_free(result);
g_free (result);
return imap_folder->count;
}
@ -420,13 +437,13 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept
return;
}
mem->buffer = g_byte_array_append(mem->buffer, g_strdup("\r\n"), 3);
status = camel_imap_command(CAMEL_IMAP_STORE (folder->parent_store),
folder, &result,
"APPEND %s (\\Seen) {%d}\r\n%s",
folder->full_name,
mem->buffer->len,
mem->buffer->data);
mem->buffer = g_byte_array_append (mem->buffer, g_strdup("\r\n"), 3);
status = camel_imap_command (CAMEL_IMAP_STORE (folder->parent_store),
folder, &result,
"APPEND %s (\\Seen) {%d}\r\n%s",
folder->full_name,
mem->buffer->len,
mem->buffer->data);
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
@ -458,7 +475,7 @@ imap_get_uids (CamelFolder *folder, CamelException *ex)
g_ptr_array_set_size (array, count);
for (i = 0; i < count; i++) {
info = (CamelMessageInfo *) g_ptr_array_index (infolist, i);
array->pdata[i] = g_strdup(info->uid);
array->pdata[i] = g_strdup (info->uid);
}
imap_free_summary (folder, infolist);
@ -479,7 +496,7 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex)
if (imap_folder->count != -1)
return g_ptr_array_new ();
status = camel_imap_command_extended(CAMEL_IMAP_STORE (folder->parent_store), folder,
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "LSUB \"\" \"%s\"", folder->full_name);
if (status != CAMEL_IMAP_OK) {
@ -495,35 +512,35 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex)
/* parse out the subfolders */
listing = g_ptr_array_new ();
g_ptr_array_add(listing, g_strdup("INBOX"));
g_ptr_array_add (listing, g_strdup("INBOX"));
if (result) {
char *ptr = result;
while (*ptr == '*') {
gchar *flags, *end, *dir_sep, *param = NULL;
ptr = flags = strchr(ptr, '(') + 1; /* jump to the flags section */
end = strchr(flags, ')'); /* locate end of flags */
ptr = flags = strchr (ptr, '(') + 1; /* jump to the flags section */
end = strchr (flags, ')'); /* locate end of flags */
flags = g_strndup(flags, (gint)(end - flags));
if (strstr(flags, "\\NoSelect")) {
g_free(flags);
if (strstr (flags, "\\NoSelect")) {
g_free (flags);
continue;
}
g_free(flags);
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));
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));
param = g_strndup (ptr, (gint)(end - ptr));
g_ptr_array_add(listing, param);
g_ptr_array_add (listing, param);
g_free(dir_sep); /* TODO: decide if we really need dir_sep */
g_free (dir_sep); /* TODO: decide if we really need dir_sep */
if (*end)
ptr = end + 1;
@ -614,7 +631,7 @@ get_header_field (gchar *header, gchar *field)
{
gchar *part, *index, *p, *q;
index = strstrcase(header, field);
index = strstrcase (header, field);
if (index == NULL)
return NULL;
@ -654,6 +671,13 @@ imap_get_summary (CamelFolder *folder, CamelException *ex)
&result, "FETCH %d BODY.PEEK[HEADER]", i);
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
"Could not get summary for %s on IMAP server %s: %s",
folder->full_name, service->url->host,
status == CAMEL_IMAP_ERR ? result :
"Unknown error");
g_free (result);
break;
}
@ -737,20 +761,34 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc
{
return NULL;
#if 0
/* TODO: find a good way of doing this */
/* NOTE: This is experimental code... */
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
char *result;
int status;
if (imap_folder->search == NULL) {
imap_folder->search = camel_folder_search_new();
if (!imap_folder->has_search_capability)
return NULL;
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
&result, "SEARCH %s", expression);
if (status != CAMEL_IMAP_OK) {
CamelService *service = CAMEL_SERVICE (folder->parent_store);
camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
"Could not get summary for %s on IMAP server %s: %s",
folder->full_name, service->url->host,
status == CAMEL_IMAP_ERR ? result :
"Unknown error");
g_free (result);
return NULL;
}
camel_folder_search_set_folder(imap_folder->search, folder);
if (imap_folder->summary)
/* FIXME: dont access summary array directly? */
camel_folder_search_set_summary(imap_folder->search,
CAMEL_FOLDER_SUMMARY (imap_folder->summary)->messages);
camel_folder_search_set_body_index(imap_folder->search, imap_folder->index);
return camel_folder_search_execute_expression(imap_folder->search, expression, ex);
#endif
/* now to parse @result */
#endif
}

View File

@ -1,835 +0,0 @@
/* Spruce
* Copyright (C) 1999-2000 Jeffrey Stedfast
*
* 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 Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "imap.h"
#define IMAP_LOGGING
/* this is used in the tag before each command */
static guint32 imap_commands = 0;
extern gint timeout;
extern GList *mime_parts;
gint imap_ok (gint tag, gchar *line)
{
/* returns 1 if <tag> OK was found */
gchar find[64];
gint ret;
g_snprintf(find, sizeof(find)-1, "A%.5d OK", tag);
ret = find_string (line, find);
if (ret < 0)
return 0;
return 1;
}
gint imap_login_cram_md5 (gint socket, gchar *username, gchar *password)
{
/* Log in to server using CRAM-MD5 keyed hash. */
gchar buffer[512];
gchar *retstr;
gint pos;
if (username == NULL || password == NULL)
return ERROR;
memset(buffer, 0, sizeof(buffer));
if (recvline(socket, buffer, sizeof(buffer)-1) < 0)
return ERROR; /* Fetch the OK line from the server */
if (find_string(buffer, "OK") == -1)
return ERROR;
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d AUTHENTICATE CRAM-MD5\r\n", imap_commands);
if (send(socket, buffer, strlen(buffer), 0) < 0)
return ERROR;
memset(buffer, 0, sizeof(buffer));
if (recvline(socket, buffer, sizeof(buffer)-1) < 0)
return ERROR;
pos = find_string(buffer, "\r\n");
if (pos != -1)
buffer[pos] = '\0';
retstr = cram_md5(username, password, buffer);
if (retstr[strlen(retstr)-1] == '\n')
retstr[strlen(retstr)-1] = '\0';
g_snprintf(buffer, sizeof(buffer)-1, "%s\r\n", retstr);
g_free(retstr);
if (send (socket, buffer, strlen(buffer), 0) < 0)
return ERROR;
if (recvline(socket, buffer, sizeof(buffer)-1) < 0)
return ERROR;
if (!imap_ok(imap_commands, buffer))
return ERROR;
imap_commands++;
return SUCCESS;
}
gint imap_login (gint socket, gchar *username, gchar *password)
{
/* this logs us in to the server */
gchar buffer[512];
gchar temp[64];
if (username == NULL || password == NULL)
return ERROR;
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d LOGIN \"%s\" \"%s\"\r\n", imap_commands, username, password);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send (socket, buffer, strlen(buffer), 0) < 0)
{
return ERROR;
}
g_snprintf(temp, sizeof(temp)-1, "A%.5d", imap_commands);
memset(buffer, 0, sizeof(buffer));
recvline_timeo(socket, buffer, sizeof(buffer)-1, timeout);
while (!strstr(buffer, temp))
{
memset(buffer, 0, sizeof(buffer));
recvline_timeo(socket, buffer, sizeof(buffer)-1, timeout);
}
if (!imap_ok(imap_commands, buffer))
return ERROR;
imap_commands++;
return SUCCESS;
}
GList *imap_list (gint socket, gchar *namespace)
{
/* this gets the names of all the mailboxes */
gchar buffer[512];
gchar flags[256];
gchar temp[64], *ptr = NULL, *flagptr = NULL;
gchar slashdot = '\0';
GList *list = NULL;
gint ret, size = 0, flaglen = 0;
if (namespace && *namespace)
{
if (*namespace && namespace[strlen(namespace)-1] != '/' && namespace[strlen(namespace)-1] != '.')
slashdot = '/';
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d LIST \"\" %s%c*\r\n", imap_commands, namespace, slashdot);
}
else
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d LIST \"\" INBOX.*\r\n", imap_commands);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
return NULL;
}
do
{
memset(buffer, 0, sizeof(buffer));
ret = recvline(socket, buffer, sizeof(buffer)-1);
if (ret > 0)
{
#ifdef IMAP_LOGGING
fprintf(stderr, "received: %s", buffer);
#endif
if (buffer[0] == '*')
{
strip(buffer, '\r');
strip(buffer, '\n');
/* skip ahead to the flag section */
ptr = strstr(buffer, "(");
/* find the end of the flags section */
flagptr = ptr + 1;
ptr = strstr(ptr, ")") + 1;
/* eventually we will need to parse this */
memset(flags, 0, sizeof(flags));
flaglen = (gint)(ptr - flagptr) - 1;
size = sizeof(flags);
strncpy(flags, flagptr, flaglen > size ? size : flaglen);
if (!strstrcase(flags, "\\NoSelect")) /* is this a selectable mailbox? */
{
/* skip the reference name */
ptr += imap_get_string (ptr, temp, sizeof(temp)-1, "");
/* the rest of the return string is fair play... */
g_strstrip(ptr); /* trim off any extra white space */
unquote(ptr); /* unquote the mailbox name if it is quoted */
if (slashdot)
strcut(ptr, 0, strlen(namespace)+1); /* cut out the namespace and the '/' */
else
strcut(ptr, 0, strlen(namespace)); /* cut out the namespace */
list = g_list_append (list, g_strdup(ptr));
}
}
else
break;
}
} while (ret > 0);
imap_commands++;
return list;
}
gint imap_select_mailbox (gint socket, gchar *mailbox, gchar *namespace)
{
/* selects a mailbox, returns the number of messages in that mailbox
* or -1 on error */
gchar *cmdbuf, buffer[512], temp[64], *index, mesgs[16];
gchar slashdot = '\0';
gint ret, i;
if (mailbox == NULL)
return ERROR;
if (namespace && strcmp(mailbox, "INBOX"))
{
if (*namespace && namespace[strlen(namespace)-1] != '/' && namespace[strlen(namespace)-1] != '.')
slashdot = '/';
cmdbuf = g_strdup_printf("A%.5d SELECT %s%c%s\r\n", imap_commands, namespace, slashdot, mailbox);
}
else
cmdbuf = g_strdup_printf("A%.5d SELECT %s\r\n", imap_commands, mailbox);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", cmdbuf);
#endif
if (send(socket, cmdbuf, strlen(cmdbuf), 0) < 0)
{
g_free(cmdbuf);
return -1;
}
g_free(cmdbuf);
g_snprintf(temp, sizeof(temp)-1, "A%.5d", imap_commands);
memset(buffer, 0, sizeof(buffer));
ret = recvline(socket, buffer, sizeof(buffer)-1);
while (ret > 0)
{
#ifdef IMAP_LOGGING
fprintf(stderr, "received: %s", buffer);
#endif
if (strstr(buffer, temp))
break;
if (buffer[0] == '*')
{
if (strstr(buffer, "EXISTS"))
{
index = buffer;
while (*index != ' ')
index++;
index++;
i = 0;
memset(mesgs, 0, sizeof(mesgs));
while (*index != ' ' && i < sizeof(mesgs)-1)
{
mesgs[i] = *index;
index++;
i++;
}
}
}
memset(buffer, 0, sizeof(buffer));
ret = recvline(socket, buffer, sizeof(buffer)-1);
}
if (!imap_ok(imap_commands, buffer))
return -1;
imap_commands++;
return atoi(mesgs);
}
gint imap_logout (gint socket)
{
/* logs out */
gchar buffer[256];
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d LOGOUT\r\n", imap_commands);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
return ERROR;
}
return SUCCESS;
}
gint imap_mailbox_create (gint socket, gchar *mailbox)
{
/* creates a new mailbox */
gchar buffer[256];
if (mailbox == NULL)
return ERROR;
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d CREATE %s\r\n", imap_commands, mailbox);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
return ERROR;
}
memset(buffer, 0, sizeof(buffer));
if (recvline(socket, buffer, sizeof(buffer)-1) < 0 || !imap_ok(imap_commands, buffer))
{
return ERROR;
}
imap_commands++;
return SUCCESS;
}
gint imap_mailbox_delete (gint socket, gchar *mailbox)
{
/* deletes a mailbox */
gchar buffer[256];
if (mailbox == NULL)
return ERROR;
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d DELETE %s\r\n", imap_commands, mailbox);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
return ERROR;
}
memset(buffer, 0, sizeof(buffer));
if (recvline(socket, buffer, sizeof(buffer)-1) < 0 ||
!imap_ok(imap_commands, buffer))
{
return ERROR;
}
imap_commands++;
return SUCCESS;
}
/* fetches the specified part of a message, which can be alot of
* if you use peek the \Seen flag is not set */
gchar *imap_fetch (gint socket, gint mesgnum, gchar *part, gint *seen)
{
/* fetches the specified part of the mesg. */
gchar *mesg = NULL;
gchar buffer[512], *index;
gchar flags[128], size[16], temp[64];
gint i, n, msgsize = 1000;
if (mesgnum < 0)
return (gchar *)NULL;
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d FETCH %d (FLAGS %s)\r\n", imap_commands, mesgnum, part);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
return (gchar *)NULL;
}
memset(buffer, 0, sizeof(buffer));
n = recvline(socket, buffer, sizeof(buffer)-1);
if (buffer[0] != '*' && imap_ok(imap_commands, buffer))
{
memset(buffer, 0, sizeof(buffer));
n = recvline(socket, buffer, sizeof(buffer)-1);
}
if (buffer[0] == '*')
/*if (imap_ok(imap_commands, buffer))*/
{
index = strstrcase(buffer, "FLAGS");
if (index == NULL) /* hmm */
{
fprintf(stderr, _("IMAP server replied using unknown tokens.\n"));
return (gchar *)NULL;
}
else
{
#ifdef IMAP_LOGGING
fprintf(stderr, "received: %s", buffer);
#endif
/* skip to the FLAGS token */
for ( ; *index && *index != '('; index++);
index++;
i = 0;
memset(flags, 0, sizeof(flags));
while (*index != ')' && i < sizeof(flags)-1)
{
flags[i] = *index;
index++;
i++;
}
flags[i] = '\0';
/* skip to the next significant token */
for (index++; *index && *index != '{'; index++);
index++;
i = 0;
memset(size, 0, sizeof(size));
while (*index != '}' && i < sizeof(size)-1)
{
size[i] = *index;
index++;
i++;
}
size[i] = '\0';
msgsize = atoi(size);
}
}
else
{
g_snprintf(temp, sizeof(temp)-1, "A%.5d", imap_commands);
if (strstr(buffer, temp)) /* this means there's no such message */
{
fprintf(stderr, _("IMAP responded with \"no such message\".\n"));
return (gchar *)NULL;
}
}
mesg = g_malloc0(msgsize + 50); /* just to be safe */
n = recvline(socket, buffer, sizeof(buffer)-1);
while (!(n <= 0) && !imap_ok(imap_commands, buffer))
{
strip(buffer, '\r'); /* strip all the \r's */
strcat(mesg, buffer);
memset(buffer, 0, sizeof(buffer));
n = recvline(socket, buffer, sizeof(buffer)-1);
}
if (mesg)
mesg[strlen(mesg)-3] = '\0'; /* strip the ending ) */
if (seen != NULL)
{
if (strstrcase(flags, "\\Seen"))
*seen = 1;
else
*seen = 0;
}
imap_commands++;
return (gchar*)mesg;
}
gboolean imap_delete(const ImapAccount_t *imap, GList *sorted)
{
GList *p = sorted;
gchar buffer[256];
gchar temp[16];
gint ret;
do
{
gint id = GPOINTER_TO_INT(p->data);
g_snprintf(buffer, sizeof(buffer)-1, "A%.5d STORE %d +FLAGS (\\Deleted)\r\n", imap_commands, id);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(imap->socket, buffer, strlen(buffer), 0) < 0)
{
return FALSE;
}
g_snprintf(temp, sizeof(temp)-1, "A%.5d", imap_commands);
memset(buffer, 0, sizeof(buffer));
ret = recvline(imap->socket, buffer, sizeof(buffer)-1);
while (ret > 0)
{
if (find_string(buffer, temp) >= 0)
break;
memset(buffer, 0, sizeof(buffer));
ret = recvline(imap->socket, buffer, sizeof(buffer)-1);
}
if (!imap_ok(imap_commands, buffer))
{
return FALSE;
}
imap_commands++;
} while ((p = g_list_next(p)));
g_snprintf(buffer, 255, "A%.5d EXPUNGE\r\n", imap_commands);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(imap->socket, buffer, strlen(buffer), 0) < 0)
{
return FALSE;
}
g_snprintf (temp, 15, "A%.5d", imap_commands);
memset(buffer, 0, sizeof(buffer));
ret = recvline(imap->socket, buffer, sizeof(buffer)-1);
while (ret > 0)
{
if (find_string(buffer, temp) >= 0)
break;
memset(buffer, 0, sizeof(buffer));
ret = recvline(imap->socket, buffer, sizeof(buffer)-1);
}
if (!imap_ok(imap_commands, buffer))
{
return FALSE;
}
imap_commands++;
return TRUE;
}
gint imap_connect (Server *server)
{
/* connects to the server and returns the socket or -1 on error */
gchar buffer[512];
gint sock;
if (!Resolve(server))
return -1;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0)
return -1;
server->sin.sin_family = AF_INET;
server->sin.sin_port = htons(server->port);
#ifdef IMAP_LOGGING
fprintf(stderr, _("Connecting to IMAP server (%s)..."), server->ip);
#endif
if (connect_timeo(sock, (struct sockaddr*)&server->sin, sizeof(server->sin), timeout) < 0)
{
fprintf(stderr, _("failed.\n"));
close(sock);
return -1;
}
fprintf(stderr, _("success.\n"));
{
/* read the connect responce */
memset(buffer, 0, sizeof(buffer));
recvline_timeo(sock, buffer, sizeof(buffer)-1, timeout);
}
return sock;
}
gint imap_add_part(gchar *c)
{
gchar name[64], value[64];
gchar temp[64];
gchar *start = c;
struct mime_part *part;
part = g_malloc0(sizeof(struct mime_part));
c += imap_get_string (c, part->type, sizeof(part->type)-1, "text");
c += imap_get_string (c, part->subtype, sizeof(part->subtype)-1, "plain");
/* seek to the beginning of the parameter... */
for ( ; *c && *c == ' '; c++);
if (*c)
{
gchar *p = part->parameter;
if (*c == '(')
{
c++;
while (*c && *c != ')')
{
c += imap_get_string (c, name, sizeof(name)-1, "");
c += imap_get_string (c, value, sizeof(value)-1, "");
/* don't buffer overrun */
g_snprintf(p, sizeof(part->parameter)-1, "%s=\"%s\"; ", name, value);
p += strlen(p);
while (*c && *c == ' ') /* skip any spaces */
c++;
}
}
else
{
c += imap_get_string (c, name, sizeof(name)-1, "");
strcpy(value, name);
*p++ = '\0';
}
c++; /* skip over the ')' belonging to the parameter values */
if (*c)
{
/* ignore id and description */
c += imap_get_string (c, temp, sizeof(temp)-1, "");
c += imap_get_string (c, temp, sizeof(temp)-1, "");
/* encoding */
c += imap_get_string (c, part->encoding, sizeof(part->encoding)-1, "");
/* size */
c += imap_get_number (c, &part->len);
/* skip the optional info */
c += imap_skip_section(c);
part->pos = 0; /* isn't useful in imap */
#ifdef IMAP_LOGGING
fprintf(stderr, "type = %s/%s\n", part->type, part->subtype);
fprintf(stderr, "encoding = %s\n", part->encoding);
fprintf(stderr, "param = %s\n", part->parameter);
#endif
mime_parts = g_list_append (mime_parts, part);
return (c - start);
}
}
return -1;
}
gint imap_parts (gint socket, gint mesg_num)
{
GList *tmp;
gchar *buffer = NULL, *c;
gint res = 1, cnt;
tmp = mime_parts;
while (tmp != NULL)
{
g_free(tmp->data);
tmp = tmp->next;
}
if (mime_parts != NULL)
{
g_list_free(mime_parts);
mime_parts = NULL;
}
buffer = g_malloc0(sizeof(gchar)*2048);
g_snprintf(buffer, 2047, "A%.5d FETCH %d (BODYSTRUCTURE)\r\n", imap_commands, mesg_num);
#ifdef IMAP_LOGGING
fprintf(stderr, "%s", buffer);
#endif
if (send(socket, buffer, strlen(buffer), 0) < 0)
{
g_free(buffer);
return 0;
}
/* get the structure of the body */
memset (buffer, 0, sizeof(gchar)*2048);
recvline (socket, buffer, sizeof(gchar)*2048);
#ifdef IMAP_LOGGING
fprintf(stderr, "received: %s", buffer);
#endif
c = buffer;
/* skip to the BODYSTRUCTURE */
c = strstr(c, "BODYSTRUCTURE");
if (c == NULL)
return 0;
c += strlen("BODYSTRUCTURE");
if (*c)
{
/* looks good so far, skip to the parts */
for ( ; *c && *c != '('; c++);
if (*c && *(c+1) == '(')
{
c++;
#ifdef IMAP_LOGGING
fprintf(stderr, "message is multipart\n");
#endif
/* multipart */
while (*c == '(')
{
cnt = imap_skip_section(c);
if (cnt > 1)
{
c[cnt-1] = '\0';
cnt = imap_add_part(c);
if (cnt == -1)
{
res = 0;
break;
}
c += cnt;
}
else
{
res = 0;
break;
}
/* skip to the next mime part */
for ( ; *c && *c == ' '; c++);
}
}
else
if (*c)
{
/* one part */
cnt = imap_add_part(c);
res = res != -1;
}
/* just forget the rest, who cares?? */
}
g_free(buffer);
return res;
}
gint imap_get_string (gchar *index, gchar *dest, gint destlen, gchar *def)
{
/* gets a string ("data" or NIL) , if NIL it copies def instead */
gint i;
gchar *start = index;
while (*index && *index == ' ') /* skip white space */
index++;
if (strncmp(index, "NIL", 3))
{
/* progress to the first quote (we should already be there but just in case) */
while (*index && *index != '"')
index++;
index++;
i = 0;
while (*index && *index != '"')
{
if (i < destlen-1)
{
dest[i] = *index;
i++;
}
index++;
}
dest[i] = '\0';
}
else
{
/* if there were no data we just copy def */
index += 3;
strncpy (dest, def, destlen);
}
return index - start + 1;
}
gint imap_get_number (gchar *index, gint *dest)
{
/* gets a number */
gchar number[32];
gchar *start = index;
gint i;
/* skip white space **/
while (*index == ' ')
index++;
i = 0;
while (*index != ' ' && i < sizeof(number)-1)
{
number[i] = *index;
index++;
i++;
}
number[i] = '\0';
*dest = atoi(number);
return index - start;
}
gint imap_skip_section(gchar *index)
{
gint depth = 1;
gchar *start = index;
while (depth != 0 && *index)
{
if (*index == '(')
depth++;
else if ( *index == ')' )
depth--;
index++;
}
return index - start;
}

View File

@ -1,86 +0,0 @@
/* Spruce
* Copyright (C) 1999-2000 Jeffrey Stedfast
*
* 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 Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __IMAP_H__
#define __IMAP_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <gtk/gtk.h>
#undef MIN
#undef MAX
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "parse.h"
#include "server.h"
#include "mime.h"
#include "cram-md5.h"
struct imap_account
{
Server server;
gchar *username;
gchar *password;
gint socket;
};
gint imap_ok (gint tag, gchar *line);
gint imap_login_cram_md5(gint socket, gchar *username, gchar *password);
gint imap_login (gint socket, gchar *username, gchar *password);
GList *imap_list (gint socket, gchar *namespace);
gint imap_select_mailbox (gint socket, gchar *mailbox, gchar *namespace);
gint imap_logout (gint socket);
gint imap_mailbox_create (gint socket, gchar *mailbox);
gint imap_mailbox_delete (gint socket, gchar *mailbox);
gchar *imap_fetch (gint socket, gint mesgnum, gchar *part, gint *seen);
gboolean imap_delete (const ImapAccount_t *imap, GList *sorted);
gint imap_connect(Server *server);
gint imap_add_part(gchar *c);
gint imap_parts (gint socket, gint mesg_num);
gint imap_get_string (gchar *index, gchar *dest, gint destlen, gchar *def);
gint imap_get_number (gchar *index, gint *dest);
gint imap_skip_section(gchar *index);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif