Commit 647eef14 authored by Srinivasa Ragavan's avatar Srinivasa Ragavan

Add support to mobile extension of POP/IMAP and implement the new APIs.

parent 38ff814b
......@@ -1617,6 +1617,64 @@ ps_done (gboolean success, gpointer sdata, GError *error)
g_free (data);
}
/* Fetch Old messages */
typedef struct _email_folder_fetch_data {
EMailDataFolder *mfolder;
EGdbusFolderCF *object;
GDBusMethodInvocation *invocation;
gint count;
}EMailFolderFetchData;
static gboolean
fetch_old_operate (CamelFolder *folder, gpointer sdata, GError **error)
{
EMailFolderFetchData *data = (EMailFolderFetchData *)sdata;
return camel_folder_fetch_old_messages (folder, data->count, error);
}
static void
fetch_old_done (gboolean success, gpointer sdata, GError *error)
{
EMailFolderFetchData *data = (EMailFolderFetchData *)sdata;
EMailDataFolderPrivate *priv = DATA_FOLDER_PRIVATE(data->mfolder);
if (error && error->message) {
g_warning ("Fetch old messages failed: %s: %s\n", priv->path, error->message);
g_dbus_method_invocation_return_gerror (data->invocation, error);
ipc(printf("Fetch old messages: %s failed: %s\n", priv->path, error->message));
return;
}
egdbus_folder_cf_complete_fetch_old_messages (data->object, data->invocation, success);
ipc(printf("Fetch old messages: %s success: %d\n", priv->path, success));
g_free (data);
}
static
gboolean
impl_Mail_fetchOldMessages (EGdbusFolderCF *object, GDBusMethodInvocation *invocation, int count, EMailDataFolder *mfolder)
{
EMailFolderFetchData *data;
EMailDataFolderPrivate *priv = DATA_FOLDER_PRIVATE(mfolder);
data = g_new0 (EMailFolderFetchData, 1);
data->mfolder = mfolder;
data->invocation = invocation;
data->object = object;
data->count = count;
mail_operate_on_folder (priv->folder, fetch_old_operate, fetch_old_done, data);
return TRUE;
}
static gboolean
impl_Mail_prepareSummary (EGdbusFolderCF *object, GDBusMethodInvocation *invocation, EMailDataFolder *mfolder)
{
......@@ -1674,6 +1732,7 @@ e_mail_data_folder_init (EMailDataFolder *self)
g_signal_connect (priv->gdbus_object, "handle-get-message-info", G_CALLBACK (impl_Mail_getMessageInfo), self);
g_signal_connect (priv->gdbus_object, "handle-transfer-messages-to", G_CALLBACK (impl_Mail_transferMessagesTo), self);
g_signal_connect (priv->gdbus_object, "handle-prepare-summary", G_CALLBACK (impl_Mail_prepareSummary), self);
g_signal_connect (priv->gdbus_object, "handle-fetch-old-messages", G_CALLBACK (impl_Mail_fetchOldMessages), self);
}
......
......@@ -130,6 +130,10 @@
<arg name="uid" type="s" direction="in"/>
<arg name="message" type="s" direction="out"/>
</method>
<method name="fetchOldMessages">
<arg name="count" type="i" direction="in"/>
<arg name="success" type="b" direction="out"/>
</method>
<method name="searchByExpression">
<arg name="expression" type="s" direction="in"/>
<arg name="uids" type="as" direction="out"/>
......
......@@ -7,6 +7,8 @@
#include <camel/camel.h>
#include <gio/gio.h>
#include "mail-ops.h"
#include "mail-tools.h"
#include "mail-send-recv.h"
#include "utils.h"
#include <libedataserver/e-account-list.h>
#include <libedataserverui/e-passwords.h>
......@@ -381,6 +383,52 @@ impl_Mail_fetchAccount (EGdbusSessionCS *object, GDBusMethodInvocation *invocati
return TRUE;
}
static void
fetch_old_messages_done (gboolean still_more, EMailGetStoreData *data)
{
ipc(printf("Done: Fetch old messages in POP: %d\n", still_more));
egdbus_session_cs_complete_fetch_old_messages (data->object, data->invocation, still_more);
g_free (data);
}
static gboolean
impl_Mail_fetchOldMessages (EGdbusSessionCS *object, GDBusMethodInvocation *invocation, char *uid, int count, EMailDataSession *msession)
{
EIterator *iter;
EAccountList *accounts;
EAccount *account;
EMailGetStoreData *data = g_new0(EMailGetStoreData, 1);
data->invocation = invocation;
data->msession = msession;
data->object = object;
accounts = e_get_account_list ();
for (iter = e_list_get_iterator ((EList *)accounts);
e_iterator_is_valid (iter);
e_iterator_next (iter)) {
account = (EAccount *) e_iterator_get (iter);
if (account->uid && strcmp (account->uid, uid) == 0) {
const gchar *uri;
gboolean keep_on_server;
uri = e_account_get_string (
account, E_ACCOUNT_SOURCE_URL);
keep_on_server = e_account_get_bool (
account, E_ACCOUNT_SOURCE_KEEP_ON_SERVER);
mail_fetch_mail (uri, keep_on_server,
E_FILTER_SOURCE_INCOMING,
NULL, count,
NULL, NULL,
NULL, NULL,
(void (*)(const gchar *, void *)) fetch_old_messages_done, data);
}
}
return TRUE;
}
static gboolean
impl_Mail_cancelOperations (EGdbusSessionCS *object, GDBusMethodInvocation *invocation, EMailDataSession *msession)
{
......@@ -453,6 +501,7 @@ e_mail_data_session_init (EMailDataSession *self)
g_signal_connect (priv->gdbus_object, "handle-add-password", G_CALLBACK (impl_Mail_addPassword), self);
g_signal_connect (priv->gdbus_object, "handle-send-receive", G_CALLBACK (impl_Mail_sendReceive), self);
g_signal_connect (priv->gdbus_object, "handle-fetch-account", G_CALLBACK (impl_Mail_fetchAccount), self);
g_signal_connect (priv->gdbus_object, "handle-fetch-old-messages", G_CALLBACK (impl_Mail_fetchOldMessages), self);
g_signal_connect (priv->gdbus_object, "handle-cancel-operations", G_CALLBACK (impl_Mail_cancelOperations), self);
priv->stores_lock = g_mutex_new ();
......
......@@ -45,6 +45,12 @@
<method name="fetchAccount">
<arg name="uid" type="s" direction="in"/>
</method>
<method name="fetchOldMessages">
<arg name="uid" type="s" direction="in"/>
<arg name="count" type="i" direction="in"/>
<arg name="success" type="b" direction="out"/>
</method>
<method name="cancelOperations">
</method>
......
......@@ -49,6 +49,10 @@
/* XXX Make this a preprocessor definition. */
const gchar *x_mailer = "Evolution Mail Data Server 0.1 ";
/* POP is a non storage store, and has to be sequential between same accounts. We'll use this to lock it*/
static GStaticMutex pop3_hash_lock = G_STATIC_MUTEX_INIT;
static GHashTable *pop3_hash = NULL;
/* used for both just filtering a folder + uid's, and for filtering a whole folder */
/* used both for fetching mail, and for filtering mail */
struct _filter_mail_msg {
......@@ -69,6 +73,8 @@ struct _fetch_mail_msg {
CamelOperation *cancel; /* we have our own cancellation struct, the other should be empty */
gint keep; /* keep on server? */
gint more;
gboolean still_more;
gchar *source_uri;
......@@ -217,6 +223,54 @@ mail_filter_junk (CamelFolder *folder, GPtrArray *uids)
#endif
/* ********************************************************************** */
static void
my_mutex_free (GMutex *lock)
{
g_mutex_free (lock);
}
static GHashTable *
get_pop3_hash ()
{
g_static_mutex_lock (&pop3_hash_lock);
if (!pop3_hash)
pop3_hash = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)my_mutex_free);
g_static_mutex_unlock (&pop3_hash_lock);
return pop3_hash;
}
static void
pop3_fetch_lock (const char *source)
{
GMutex *lock;
GHashTable *hash = get_pop3_hash();
g_static_mutex_lock (&pop3_hash_lock);
lock = g_hash_table_lookup (hash, source);
if (!lock) {
lock = g_mutex_new();
g_hash_table_insert (hash, g_strdup(source), lock);
}
g_static_mutex_unlock (&pop3_hash_lock);
g_mutex_lock (lock);
}
static void
pop3_fetch_unlock (const char *source)
{
GMutex *lock;
GHashTable *hash = get_pop3_hash();
g_static_mutex_lock (&pop3_hash_lock);
/* lock can't disappear from hash */
lock = g_hash_table_lookup (hash, source);
g_static_mutex_unlock (&pop3_hash_lock);
g_mutex_unlock (lock);
}
/* Temporary workaround for various issues. Gone before 0.11 */
static gchar *
......@@ -332,6 +386,8 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
} else {
CamelFolder *folder;
/* This is a account level lock to ensure that no two same accounts get fetched at the same time */
pop3_fetch_lock (m->source_uri);
folder = fm->source_folder =
mail_tool_get_inbox (m->source_uri, &fm->base.error);
......@@ -341,6 +397,11 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
CamelUIDCache *cache = NULL;
CamelStore *parent_store;
gchar *cachename;
if (m->more) {
printf("Fetching %d old messages\n", m->more);
m->still_more = camel_folder_fetch_old_messages(folder, m->more, &fm->base.error);
}
parent_store = camel_folder_get_parent_store (folder);
cachename = uid_cachename_hack (parent_store);
......@@ -356,6 +417,7 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
folder_uids = camel_folder_get_uids (folder);
cache_uids = camel_uid_cache_get_new_uids (cache, folder_uids);
printf("Gonna cache uids: %d\n", cache_uids->len);
if (cache_uids) {
/* need to copy this, sigh */
fm->source_uids = uids = g_ptr_array_new ();
......@@ -402,6 +464,8 @@ fetch_mail_exec (struct _fetch_mail_msg *m)
g_object_unref (fm->source_folder);
fm->source_folder = NULL;
}
pop3_fetch_unlock(m->source_uri);
}
fail:
if (m->cancel)
......@@ -419,8 +483,12 @@ fail:
static void
fetch_mail_done (struct _fetch_mail_msg *m)
{
if (m->done)
m->done (m->source_uri, m->data);
if (m->done) {
if (m->more)
m->done (m->still_more, m->data);
else
m->done (m->source_uri, m->data);
}
}
static void
......@@ -443,7 +511,7 @@ static MailMsgInfo fetch_mail_info = {
/* ouch, a 'do everything' interface ... */
void
mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperation *cancel,
mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperation *cancel, gint more,
CamelFilterGetFolderFunc get_folder, gpointer get_data,
CamelFilterStatusFunc *status, gpointer status_data,
void (*done)(const gchar *source, gpointer data), gpointer data)
......@@ -452,6 +520,7 @@ mail_fetch_mail (const gchar *source, gint keep, const gchar *type, CamelOperati
struct _filter_mail_msg *fm;
m = mail_msg_new (&fetch_mail_info);
m->more = more;
fm = (struct _filter_mail_msg *)m;
m->source_uri = g_strdup (source);
fm->delete = !keep;
......
......@@ -139,7 +139,7 @@ void mail_send_queue (CamelFolder *queue, const gchar *destination,
gpointer data);
void mail_fetch_mail (const gchar *source, gint keep,
const gchar *type, CamelOperation *cancel,
const gchar *type, CamelOperation *cancel, gint more,
CamelFilterGetFolderFunc get_folder, gpointer get_data,
CamelFilterStatusFunc *status, gpointer status_data,
void (*done)(const gchar *source, gpointer data),
......
......@@ -1018,7 +1018,7 @@ mail_send_receive (GtkWindow *parent)
case SEND_RECEIVE:
mail_fetch_mail(info->uri, info->keep_on_server,
E_FILTER_SOURCE_INCOMING,
info->cancel,
info->cancel, 0,
receive_get_folder, info,
receive_status, info,
receive_done, info);
......@@ -1252,7 +1252,7 @@ mail_receive_uri (const gchar *uri, gboolean keep_on_server)
case SEND_RECEIVE:
mail_fetch_mail (info->uri, info->keep_on_server,
E_FILTER_SOURCE_INCOMING,
info->cancel,
info->cancel, 0,
receive_get_folder, info,
receive_status, info,
receive_done, info);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment