removed imap.c/h from providers/imap
began implementing search functionality svn path=/trunk/; revision=3613
This commit is contained in:
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user