
that it only happens in the mailer (which is the only component actually using this). For some reason it still doesn't work properly (i.e. the menu item currently does nothing), but I haven't quite figured out why yet. svn path=/trunk/; revision=10840
967 lines
26 KiB
C
967 lines
26 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
/* component-factory.c
|
|
*
|
|
* Authors: Ettore Perazzoli <ettore@ximian.com>
|
|
*
|
|
* Copyright (C) 2000 Ximian, Inc.
|
|
*
|
|
* 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 <bonobo/bonobo-generic-factory.h>
|
|
#include <gal/widgets/e-gui-utils.h>
|
|
|
|
#include "camel.h"
|
|
|
|
#include "Evolution.h"
|
|
#include "evolution-storage.h"
|
|
|
|
#include "folder-browser-factory.h"
|
|
#include "evolution-shell-component.h"
|
|
#include "evolution-shell-component-dnd.h"
|
|
#include "folder-browser.h"
|
|
#include "mail.h" /* YUCK FIXME */
|
|
#include "mail-config.h"
|
|
#include "mail-tools.h"
|
|
#include "mail-ops.h"
|
|
#include "mail-offline-handler.h"
|
|
#include "mail-local.h"
|
|
#include "mail-session.h"
|
|
#include "mail-mt.h"
|
|
#include "mail-importer.h"
|
|
#include "mail-vfolder.h" /* vfolder_create_storage */
|
|
|
|
#include "component-factory.h"
|
|
|
|
#include "mail-send-recv.h"
|
|
|
|
char *default_drafts_folder_uri;
|
|
CamelFolder *drafts_folder = NULL;
|
|
char *default_sent_folder_uri;
|
|
CamelFolder *sent_folder = NULL;
|
|
char *default_outbox_folder_uri;
|
|
CamelFolder *outbox_folder = NULL;
|
|
char *evolution_dir;
|
|
|
|
#define COMPONENT_FACTORY_ID "OAFIID:GNOME_Evolution_Mail_ShellComponentFactory"
|
|
#define SUMMARY_FACTORY_ID "OAFIID:GNOME_Evolution_Mail_ExecutiveSummaryComponentFactory"
|
|
|
|
static BonoboGenericFactory *component_factory = NULL;
|
|
static GHashTable *storages_hash;
|
|
static EvolutionShellComponent *shell_component;
|
|
|
|
enum {
|
|
ACCEPTED_DND_TYPE_MESSAGE_RFC822,
|
|
ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE,
|
|
ACCEPTED_DND_TYPE_TEXT_URI_LIST,
|
|
};
|
|
|
|
static char *accepted_dnd_types[] = {
|
|
"message/rfc822",
|
|
"x-evolution-message", /* ...from an evolution message list... */
|
|
"text/uri-list", /* ...from nautilus... */
|
|
NULL
|
|
};
|
|
|
|
enum {
|
|
EXPORTED_DND_TYPE_TEXT_URI_LIST,
|
|
};
|
|
|
|
static char *exported_dnd_types[] = {
|
|
"text/uri-list", /* we have to export to nautilus as text/uri-list */
|
|
NULL
|
|
};
|
|
|
|
static const EvolutionShellComponentFolderType folder_types[] = {
|
|
{ "mail", "evolution-inbox.png", accepted_dnd_types, exported_dnd_types },
|
|
{ "mailstorage", "evolution-inbox.png", NULL, NULL },
|
|
{ "vtrash", "evolution-trash.png", NULL, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
static const char *schema_types[] = {
|
|
"mailto",
|
|
NULL
|
|
};
|
|
|
|
/* EvolutionShellComponent methods and signals. */
|
|
|
|
static EvolutionShellComponentResult
|
|
create_view (EvolutionShellComponent *shell_component,
|
|
const char *physical_uri,
|
|
const char *folder_type,
|
|
BonoboControl **control_return,
|
|
void *closure)
|
|
{
|
|
EvolutionShellClient *shell_client;
|
|
GNOME_Evolution_Shell corba_shell;
|
|
BonoboControl *control;
|
|
|
|
shell_client = evolution_shell_component_get_owner (shell_component);
|
|
corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client));
|
|
|
|
if (g_strcasecmp (folder_type, "mail") == 0) {
|
|
control = folder_browser_factory_new_control (physical_uri,
|
|
corba_shell);
|
|
} else if (g_strcasecmp (folder_type, "mailstorage") == 0) {
|
|
CamelService *store;
|
|
EvolutionStorage *storage;
|
|
|
|
store = camel_session_get_service (session, physical_uri,
|
|
CAMEL_PROVIDER_STORE, NULL);
|
|
if (!store)
|
|
return EVOLUTION_SHELL_COMPONENT_NOTFOUND;
|
|
storage = g_hash_table_lookup (storages_hash, store);
|
|
if (!storage) {
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
return EVOLUTION_SHELL_COMPONENT_NOTFOUND;
|
|
}
|
|
|
|
if (!gtk_object_get_data (GTK_OBJECT (storage), "connected"))
|
|
mail_scan_subfolders (CAMEL_STORE(store), storage);
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
|
|
control = folder_browser_factory_new_control ("", corba_shell);
|
|
} else if (g_strcasecmp (folder_type, "vtrash") == 0) {
|
|
control = folder_browser_factory_new_control ("vtrash:file:/", corba_shell);
|
|
} else
|
|
return EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE;
|
|
|
|
if (!control)
|
|
return EVOLUTION_SHELL_COMPONENT_NOTFOUND;
|
|
|
|
*control_return = control;
|
|
return EVOLUTION_SHELL_COMPONENT_OK;
|
|
}
|
|
|
|
static void
|
|
do_create_folder (char *uri, CamelFolder *folder, void *data)
|
|
{
|
|
GNOME_Evolution_ShellComponentListener listener = data;
|
|
CORBA_Environment ev;
|
|
GNOME_Evolution_ShellComponentListener_Result result;
|
|
|
|
if (folder)
|
|
result = GNOME_Evolution_ShellComponentListener_OK;
|
|
else
|
|
result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
|
|
CORBA_Object_release (listener, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
create_folder (EvolutionShellComponent *shell_component,
|
|
const char *physical_uri,
|
|
const char *type,
|
|
const GNOME_Evolution_ShellComponentListener listener,
|
|
void *closure)
|
|
{
|
|
char *uri;
|
|
CORBA_Environment ev;
|
|
|
|
CORBA_exception_init (&ev);
|
|
if (!strcmp (type, "mail")) {
|
|
/* This makes the uri start with mbox://file://, which
|
|
looks silly but turns into a CamelURL that has
|
|
url->provider of "mbox" */
|
|
uri = g_strdup_printf ("mbox://%s", physical_uri);
|
|
mail_create_folder (uri, do_create_folder, CORBA_Object_duplicate (listener, &ev));
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener,
|
|
GNOME_Evolution_ShellComponentListener_OK, &ev);
|
|
|
|
} else {
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (
|
|
listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev);
|
|
}
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
do_remove_folder (char *uri, gboolean removed, void *data)
|
|
{
|
|
GNOME_Evolution_ShellComponentListener listener = data;
|
|
GNOME_Evolution_ShellComponentListener_Result result;
|
|
CORBA_Environment ev;
|
|
|
|
if (removed)
|
|
result = GNOME_Evolution_ShellComponentListener_OK;
|
|
else
|
|
result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
|
|
CORBA_Object_release (listener, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
remove_folder (EvolutionShellComponent *shell_component,
|
|
const char *physical_uri,
|
|
const GNOME_Evolution_ShellComponentListener listener,
|
|
void *closure)
|
|
{
|
|
CORBA_Environment ev;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
mail_remove_folder (physical_uri, do_remove_folder, CORBA_Object_duplicate (listener, &ev));
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener,
|
|
GNOME_Evolution_ShellComponentListener_OK, &ev);
|
|
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
do_xfer_folder (gboolean ok, void *data)
|
|
{
|
|
GNOME_Evolution_ShellComponentListener listener = data;
|
|
GNOME_Evolution_ShellComponentListener_Result result;
|
|
CORBA_Environment ev;
|
|
|
|
if (ok)
|
|
result = GNOME_Evolution_ShellComponentListener_OK;
|
|
else
|
|
result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
|
|
|
|
CORBA_exception_init (&ev);
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
|
|
CORBA_Object_release (listener, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
xfer_folder (EvolutionShellComponent *shell_component,
|
|
const char *source_physical_uri,
|
|
const char *destination_physical_uri,
|
|
gboolean remove_source,
|
|
const GNOME_Evolution_ShellComponentListener listener,
|
|
void *closure)
|
|
{
|
|
CORBA_Environment ev;
|
|
CamelFolder *source;
|
|
CamelException ex;
|
|
GPtrArray *uids;
|
|
|
|
camel_exception_init (&ex);
|
|
source = mail_tool_uri_to_folder (source_physical_uri, &ex);
|
|
camel_exception_clear (&ex);
|
|
|
|
CORBA_exception_init (&ev);
|
|
if (source) {
|
|
uids = camel_folder_get_uids (source);
|
|
mail_transfer_messages (source, uids, remove_source, destination_physical_uri,
|
|
do_xfer_folder,
|
|
CORBA_Object_duplicate (listener, &ev));
|
|
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_OK, &ev);
|
|
} else
|
|
GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev);
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
populate_folder_context_menu (EvolutionShellComponent *shell_component,
|
|
BonoboUIComponent *uic,
|
|
const char *physical_uri,
|
|
const char *type,
|
|
void *closure)
|
|
{
|
|
static char popup_xml[] =
|
|
"<menuitem name=\"ChangeFolderProperties\" verb=\"ChangeFolderProperties\""
|
|
" _label=\"Properties...\" _tip=\"Change this folder's properties\"/>";
|
|
|
|
if (strcmp (type, "mail") != 0)
|
|
return;
|
|
|
|
bonobo_ui_component_set_translate (uic, EVOLUTION_SHELL_COMPONENT_POPUP_PLACEHOLDER,
|
|
popup_xml, NULL);
|
|
}
|
|
|
|
static char *
|
|
get_dnd_selection (EvolutionShellComponent *shell_component,
|
|
const char *physical_uri,
|
|
int type,
|
|
int *format_return,
|
|
const char **selection_return,
|
|
int *selection_length_return,
|
|
void *closure)
|
|
{
|
|
g_print ("should get dnd selection for %s\n", physical_uri);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Destination side DnD */
|
|
static CORBA_boolean
|
|
destination_folder_handle_motion (EvolutionShellComponentDndDestinationFolder *folder,
|
|
const char *physical_uri,
|
|
const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context,
|
|
GNOME_Evolution_ShellComponentDnd_Action *suggested_action_return,
|
|
gpointer user_data)
|
|
{
|
|
g_print ("in destination_folder_handle_motion (%s)\n", physical_uri);
|
|
|
|
*suggested_action_return = GNOME_Evolution_ShellComponentDnd_ACTION_MOVE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
message_rfc822_dnd (CamelFolder *dest, CamelStream *stream, CamelException *ex)
|
|
{
|
|
CamelMimeParser *mp;
|
|
|
|
mp = camel_mime_parser_new ();
|
|
camel_mime_parser_scan_from (mp, TRUE);
|
|
camel_mime_parser_init_with_stream (mp, stream);
|
|
|
|
while (camel_mime_parser_step (mp, 0, 0) == HSCAN_FROM) {
|
|
CamelMessageInfo *info;
|
|
CamelMimeMessage *msg;
|
|
|
|
msg = camel_mime_message_new ();
|
|
if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
|
|
camel_object_unref (CAMEL_OBJECT (msg));
|
|
break;
|
|
}
|
|
|
|
/* append the message to the folder... */
|
|
info = g_new0 (CamelMessageInfo, 1);
|
|
camel_folder_append_message (dest, msg, info, ex);
|
|
camel_object_unref (CAMEL_OBJECT (msg));
|
|
|
|
if (camel_exception_is_set (ex))
|
|
break;
|
|
|
|
/* skip over the FROM_END state */
|
|
camel_mime_parser_step (mp, 0, 0);
|
|
}
|
|
|
|
camel_object_unref (CAMEL_OBJECT (mp));
|
|
}
|
|
|
|
static CORBA_boolean
|
|
destination_folder_handle_drop (EvolutionShellComponentDndDestinationFolder *folder,
|
|
const char *physical_uri,
|
|
const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context,
|
|
const GNOME_Evolution_ShellComponentDnd_Action action,
|
|
const GNOME_Evolution_ShellComponentDnd_Data *data,
|
|
gpointer user_data)
|
|
{
|
|
char *url, *name, *in, *inptr, *inend;
|
|
gboolean retval = FALSE;
|
|
CamelFolder *source;
|
|
CamelStream *stream;
|
|
CamelException ex;
|
|
GPtrArray *uids;
|
|
CamelURL *uri;
|
|
int type, fd;
|
|
|
|
if (action == GNOME_Evolution_ShellComponentDnd_ACTION_LINK)
|
|
return FALSE; /* we can't create links */
|
|
|
|
g_print ("in destination_folder_handle_drop (%s)\n", physical_uri);
|
|
|
|
for (type = 0; accepted_dnd_types[type]; type++)
|
|
if (!strcmp (destination_context->dndType, accepted_dnd_types[type]))
|
|
break;
|
|
|
|
camel_exception_init (&ex);
|
|
|
|
switch (type) {
|
|
case ACCEPTED_DND_TYPE_TEXT_URI_LIST:
|
|
source = mail_tool_uri_to_folder (physical_uri, NULL);
|
|
if (!source)
|
|
return FALSE;
|
|
|
|
url = g_strndup (data->bytes._buffer, data->bytes._length);
|
|
inend = strchr (url, '\n');
|
|
if (inend)
|
|
*inend = '\0';
|
|
|
|
/* get the path component */
|
|
g_strstrip (url);
|
|
uri = camel_url_new (url, NULL);
|
|
g_free (url);
|
|
url = uri->path;
|
|
uri->path = NULL;
|
|
camel_url_free (uri);
|
|
|
|
fd = open (url, O_RDONLY);
|
|
if (fd == -1) {
|
|
g_free (url);
|
|
return FALSE;
|
|
}
|
|
|
|
stream = camel_stream_fs_new_with_fd (fd);
|
|
message_rfc822_dnd (source, stream, &ex);
|
|
camel_object_unref (CAMEL_OBJECT (stream));
|
|
camel_object_unref (CAMEL_OBJECT (source));
|
|
|
|
retval = !camel_exception_is_set (&ex);
|
|
|
|
if (action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE && retval)
|
|
unlink (url);
|
|
|
|
g_free (url);
|
|
break;
|
|
case ACCEPTED_DND_TYPE_MESSAGE_RFC822:
|
|
source = mail_tool_uri_to_folder (physical_uri, &ex);
|
|
if (!source) {
|
|
camel_exception_clear (&ex);
|
|
return FALSE;
|
|
}
|
|
|
|
/* write the message(s) out to a CamelStream so we can use it */
|
|
stream = camel_stream_mem_new ();
|
|
camel_stream_write (stream, data->bytes._buffer, data->bytes._length);
|
|
camel_stream_reset (stream);
|
|
|
|
message_rfc822_dnd (source, stream, &ex);
|
|
camel_object_unref (CAMEL_OBJECT (stream));
|
|
camel_object_unref (CAMEL_OBJECT (source));
|
|
break;
|
|
case ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE:
|
|
/* format: "url folder_name uid1\0uid2\0uid3\0...\0uidn" */
|
|
|
|
in = data->bytes._buffer;
|
|
inend = in + data->bytes._length;
|
|
|
|
inptr = strchr (in, ' ');
|
|
url = g_strndup (in, inptr - in);
|
|
|
|
name = inptr + 1;
|
|
inptr = strchr (name, ' ');
|
|
name = g_strndup (name, inptr - name);
|
|
|
|
source = mail_tool_get_folder_from_urlname (url, name, 0, &ex);
|
|
g_free (name);
|
|
g_free (url);
|
|
|
|
if (!source) {
|
|
camel_exception_clear (&ex);
|
|
return FALSE;
|
|
}
|
|
|
|
/* split the uids */
|
|
inptr++;
|
|
uids = g_ptr_array_new ();
|
|
while (inptr < inend) {
|
|
char *start = inptr;
|
|
|
|
while (inptr < inend && *inptr)
|
|
inptr++;
|
|
|
|
g_ptr_array_add (uids, g_strndup (start, inptr - start));
|
|
inptr++;
|
|
}
|
|
|
|
mail_transfer_messages (source, uids,
|
|
action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE,
|
|
physical_uri, NULL, NULL);
|
|
|
|
camel_object_unref (CAMEL_OBJECT (source));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
camel_exception_clear (&ex);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
static struct {
|
|
char *name, **uri;
|
|
CamelFolder **folder;
|
|
} standard_folders[] = {
|
|
{ "Drafts", &default_drafts_folder_uri, &drafts_folder },
|
|
{ "Outbox", &default_outbox_folder_uri, &outbox_folder },
|
|
{ "Sent", &default_sent_folder_uri, &sent_folder },
|
|
};
|
|
|
|
static void
|
|
unref_standard_folders (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) {
|
|
if (standard_folders[i].folder)
|
|
camel_object_unref (CAMEL_OBJECT (*standard_folders[i].folder));
|
|
}
|
|
}
|
|
|
|
static void
|
|
got_folder (char *uri, CamelFolder *folder, void *data)
|
|
{
|
|
CamelFolder **fp = data;
|
|
|
|
if (folder) {
|
|
*fp = folder;
|
|
camel_object_ref (CAMEL_OBJECT (folder));
|
|
}
|
|
}
|
|
|
|
static void
|
|
owner_set_cb (EvolutionShellComponent *shell_component,
|
|
EvolutionShellClient *shell_client,
|
|
const char *evolution_homedir,
|
|
gpointer user_data)
|
|
{
|
|
GNOME_Evolution_Shell corba_shell;
|
|
const GSList *accounts;
|
|
#ifdef ENABLE_NNTP
|
|
const GSList *news;
|
|
#endif
|
|
int i;
|
|
|
|
g_print ("evolution-mail: Yeeeh! We have an owner!\n"); /* FIXME */
|
|
|
|
evolution_dir = g_strdup (evolution_homedir);
|
|
mail_session_init ();
|
|
|
|
mail_config_init ();
|
|
|
|
storages_hash = g_hash_table_new (NULL, NULL);
|
|
|
|
vfolder_create_storage (shell_component);
|
|
|
|
corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client));
|
|
|
|
accounts = mail_config_get_accounts ();
|
|
mail_load_storages (corba_shell, accounts, TRUE);
|
|
|
|
#ifdef ENABLE_NNTP
|
|
news = mail_config_get_news ();
|
|
mail_load_storages (corba_shell, news, FALSE);
|
|
#endif
|
|
|
|
mail_local_storage_startup (shell_client, evolution_dir);
|
|
mail_importer_init (shell_client);
|
|
|
|
for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) {
|
|
*standard_folders[i].uri = g_strdup_printf ("file://%s/local/%s", evolution_dir, standard_folders[i].name);
|
|
mail_msg_wait (mail_get_folder (*standard_folders[i].uri, got_folder, standard_folders[i].folder));
|
|
}
|
|
|
|
mail_session_enable_interaction (TRUE);
|
|
|
|
mail_autoreceive_setup ();
|
|
}
|
|
|
|
static void
|
|
free_storage (gpointer service, gpointer storage, gpointer data)
|
|
{
|
|
camel_service_disconnect (CAMEL_SERVICE (service), TRUE, NULL);
|
|
camel_object_unref (CAMEL_OBJECT (service));
|
|
bonobo_object_unref (BONOBO_OBJECT (storage));
|
|
}
|
|
|
|
static gboolean
|
|
idle_quit (gpointer user_data)
|
|
{
|
|
if (e_list_length (folder_browser_factory_get_control_list ()))
|
|
return TRUE;
|
|
|
|
bonobo_object_unref (BONOBO_OBJECT (component_factory));
|
|
g_hash_table_foreach (storages_hash, free_storage, NULL);
|
|
g_hash_table_destroy (storages_hash);
|
|
|
|
gtk_main_quit ();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data)
|
|
{
|
|
if (mail_config_get_empty_trash_on_exit ())
|
|
empty_trash (NULL, NULL, NULL);
|
|
|
|
unref_standard_folders ();
|
|
mail_importer_uninit ();
|
|
|
|
g_idle_add_full (G_PRIORITY_LOW, idle_quit, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
debug_cb (EvolutionShellComponent *shell_component, gpointer user_data)
|
|
{
|
|
extern gboolean camel_verbose_debug;
|
|
|
|
camel_verbose_debug = 1;
|
|
}
|
|
|
|
static void
|
|
handle_external_uri_cb (EvolutionShellComponent *shell_component,
|
|
const char *uri,
|
|
void *data)
|
|
{
|
|
if (strncmp (uri, "mailto:", 7) != 0) {
|
|
/* FIXME: Exception? The EvolutionShellComponent object should
|
|
give me a chance to do so, but currently it doesn't. */
|
|
g_warning ("Invalid URI requested to mail component -- %s", uri);
|
|
return;
|
|
}
|
|
|
|
/* FIXME: Sigh. This shouldn't be here. But the code is messy, so
|
|
I'll just put it here anyway. */
|
|
send_to_url (uri);
|
|
}
|
|
|
|
static BonoboObject *
|
|
component_fn (BonoboGenericFactory *factory, void *closure)
|
|
{
|
|
EvolutionShellComponentDndDestinationFolder *destination_interface;
|
|
MailOfflineHandler *offline_handler;
|
|
|
|
shell_component = evolution_shell_component_new (folder_types,
|
|
schema_types,
|
|
create_view,
|
|
create_folder,
|
|
remove_folder,
|
|
xfer_folder,
|
|
populate_folder_context_menu,
|
|
get_dnd_selection,
|
|
NULL);
|
|
|
|
destination_interface = evolution_shell_component_dnd_destination_folder_new (destination_folder_handle_motion,
|
|
destination_folder_handle_drop,
|
|
shell_component);
|
|
|
|
bonobo_object_add_interface (BONOBO_OBJECT (shell_component),
|
|
BONOBO_OBJECT (destination_interface));
|
|
|
|
gtk_signal_connect (GTK_OBJECT (shell_component), "owner_set",
|
|
GTK_SIGNAL_FUNC (owner_set_cb), NULL);
|
|
gtk_signal_connect (GTK_OBJECT (shell_component), "owner_unset",
|
|
GTK_SIGNAL_FUNC (owner_unset_cb), NULL);
|
|
gtk_signal_connect (GTK_OBJECT (shell_component), "debug",
|
|
GTK_SIGNAL_FUNC (debug_cb), NULL);
|
|
gtk_signal_connect (GTK_OBJECT (shell_component), "destroy",
|
|
GTK_SIGNAL_FUNC (owner_unset_cb), NULL);
|
|
gtk_signal_connect (GTK_OBJECT (shell_component), "handle_external_uri",
|
|
GTK_SIGNAL_FUNC (handle_external_uri_cb), NULL);
|
|
|
|
offline_handler = mail_offline_handler_new ();
|
|
bonobo_object_add_interface (BONOBO_OBJECT (shell_component), BONOBO_OBJECT (offline_handler));
|
|
|
|
return BONOBO_OBJECT (shell_component);
|
|
}
|
|
|
|
void
|
|
component_factory_init (void)
|
|
{
|
|
component_factory = bonobo_generic_factory_new (COMPONENT_FACTORY_ID,
|
|
component_fn, NULL);
|
|
|
|
evolution_mail_config_factory_init ();
|
|
evolution_folder_info_factory_init ();
|
|
|
|
if (component_factory == NULL) {
|
|
e_notice (NULL, GNOME_MESSAGE_BOX_ERROR,
|
|
_("Cannot initialize Evolution's mail component."));
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
static int
|
|
storage_create_folder (EvolutionStorage *storage,
|
|
const char *path,
|
|
const char *type,
|
|
const char *description,
|
|
const char *parent_physical_uri,
|
|
gpointer user_data)
|
|
{
|
|
CamelStore *store = user_data;
|
|
char *prefix, *name;
|
|
CamelURL *url;
|
|
CamelException ex;
|
|
CamelFolderInfo *fi;
|
|
|
|
if (strcmp (type, "mail") != 0)
|
|
return EVOLUTION_STORAGE_ERROR_UNSUPPORTED_TYPE;
|
|
|
|
name = strrchr (path, '/');
|
|
if (!name++)
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
|
|
camel_exception_init (&ex);
|
|
if (*parent_physical_uri) {
|
|
url = camel_url_new (parent_physical_uri, NULL);
|
|
if (!url)
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
|
|
fi = camel_store_create_folder (store, url->path + 1, name, &ex);
|
|
camel_url_free (url);
|
|
} else
|
|
fi = camel_store_create_folder (store, NULL, name, &ex);
|
|
|
|
if (camel_exception_is_set (&ex)) {
|
|
/* FIXME: do better than this */
|
|
camel_exception_clear (&ex);
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
}
|
|
|
|
if (camel_store_supports_subscriptions (store))
|
|
camel_store_subscribe_folder (store, fi->full_name, NULL);
|
|
|
|
prefix = g_strndup (path, name - path - 1);
|
|
folder_created (store, prefix, fi);
|
|
g_free (prefix);
|
|
|
|
camel_store_free_folder_info (store, fi);
|
|
|
|
return EVOLUTION_STORAGE_OK;
|
|
}
|
|
|
|
static int
|
|
storage_remove_folder (EvolutionStorage *storage,
|
|
const char *path,
|
|
const char *physical_uri,
|
|
gpointer user_data)
|
|
{
|
|
CamelStore *store = user_data;
|
|
CamelURL *url = NULL;
|
|
CamelFolderInfo *fi;
|
|
CamelException ex;
|
|
|
|
g_warning ("storage_remove_folder: path=\"%s\"; uri=\"%s\"", path, physical_uri);
|
|
|
|
if (*physical_uri) {
|
|
url = camel_url_new (physical_uri, NULL);
|
|
if (!url)
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
} else {
|
|
if (!*path)
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
}
|
|
|
|
camel_exception_init (&ex);
|
|
fi = camel_store_get_folder_info (store, url ? url->path + 1 : path + 1,
|
|
CAMEL_STORE_FOLDER_INFO_FAST, &ex);
|
|
if (url)
|
|
camel_url_free (url);
|
|
if (camel_exception_is_set (&ex))
|
|
goto exception;
|
|
|
|
camel_store_delete_folder (store, fi->full_name, &ex);
|
|
if (camel_exception_is_set (&ex))
|
|
goto exception;
|
|
|
|
if (camel_store_supports_subscriptions (store))
|
|
camel_store_unsubscribe_folder (store, fi->full_name, NULL);
|
|
|
|
folder_deleted (store, fi);
|
|
|
|
camel_store_free_folder_info (store, fi);
|
|
|
|
return EVOLUTION_STORAGE_OK;
|
|
|
|
exception:
|
|
/* FIXME: do better than this... */
|
|
|
|
if (fi)
|
|
camel_store_free_folder_info (store, fi);
|
|
|
|
return EVOLUTION_STORAGE_ERROR_INVALID_URI;
|
|
}
|
|
|
|
static void
|
|
add_storage (const char *name, const char *uri, CamelService *store,
|
|
GNOME_Evolution_Shell corba_shell, CamelException *ex)
|
|
{
|
|
EvolutionStorage *storage;
|
|
EvolutionStorageResult res;
|
|
|
|
storage = evolution_storage_new (name, uri, "mailstorage");
|
|
gtk_signal_connect (GTK_OBJECT (storage), "create_folder",
|
|
GTK_SIGNAL_FUNC (storage_create_folder),
|
|
store);
|
|
gtk_signal_connect (GTK_OBJECT (storage), "remove_folder",
|
|
GTK_SIGNAL_FUNC (storage_remove_folder),
|
|
store);
|
|
|
|
res = evolution_storage_register_on_shell (storage, corba_shell);
|
|
|
|
switch (res) {
|
|
case EVOLUTION_STORAGE_OK:
|
|
mail_hash_storage (store, storage);
|
|
mail_scan_subfolders (CAMEL_STORE (store), storage);
|
|
/* falllll */
|
|
case EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED:
|
|
case EVOLUTION_STORAGE_ERROR_EXISTS:
|
|
return;
|
|
default:
|
|
camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
|
|
_("Cannot register storage with shell"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* FIXME: 'is_account_data' is an ugly hack, if we remove support for NNTP we can take it out -- fejj */
|
|
void
|
|
mail_load_storages (GNOME_Evolution_Shell shell, const GSList *sources, gboolean is_account_data)
|
|
{
|
|
CamelException ex;
|
|
const GSList *iter;
|
|
|
|
camel_exception_init (&ex);
|
|
|
|
/* Load each service (don't connect!). Check its provider and
|
|
* see if this belongs in the shell's folder list. If so, add
|
|
* it.
|
|
*/
|
|
|
|
for (iter = sources; iter; iter = iter->next) {
|
|
const MailConfigAccount *account = NULL;
|
|
const MailConfigService *service = NULL;
|
|
CamelService *store;
|
|
CamelProvider *prov;
|
|
char *name;
|
|
|
|
if (is_account_data) {
|
|
account = iter->data;
|
|
service = account->source;
|
|
} else {
|
|
service = iter->data;
|
|
}
|
|
|
|
if (service->url == NULL || service->url[0] == '\0')
|
|
continue;
|
|
|
|
prov = camel_session_get_provider (session, service->url, &ex);
|
|
if (prov == NULL) {
|
|
/* FIXME: real error dialog */
|
|
g_warning ("couldn't get service %s: %s\n", service->url,
|
|
camel_exception_get_description (&ex));
|
|
camel_exception_clear (&ex);
|
|
continue;
|
|
}
|
|
|
|
/* FIXME: this case is ambiguous for things like the
|
|
* mbox provider, which can really be a spool
|
|
* (/var/spool/mail/user) or a storage (~/mail/, eg).
|
|
* That issue can't be resolved on the provider level
|
|
* -- it's a per-URL problem.
|
|
* MPZ Added a hack to let spool protocol through temporarily ...
|
|
*/
|
|
if ((!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) ||
|
|
!(prov->flags & CAMEL_PROVIDER_IS_REMOTE))
|
|
&& !((strcmp(prov->protocol, "spool") == 0)
|
|
|| strcmp(prov->protocol, "maildir") == 0))
|
|
continue;
|
|
|
|
store = camel_session_get_service (session, service->url,
|
|
CAMEL_PROVIDER_STORE, &ex);
|
|
if (store == NULL) {
|
|
/* FIXME: real error dialog */
|
|
g_warning ("couldn't get service %s: %s\n", service->url,
|
|
camel_exception_get_description (&ex));
|
|
camel_exception_clear (&ex);
|
|
continue;
|
|
}
|
|
|
|
if (is_account_data)
|
|
name = g_strdup (account->name);
|
|
else
|
|
name = camel_service_get_name (store, TRUE);
|
|
|
|
add_storage (name, service->url, store, shell, &ex);
|
|
g_free (name);
|
|
|
|
if (camel_exception_is_set (&ex)) {
|
|
/* FIXME: real error dialog */
|
|
g_warning ("Cannot load storage: %s",
|
|
camel_exception_get_description (&ex));
|
|
camel_exception_clear (&ex);
|
|
}
|
|
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
}
|
|
}
|
|
|
|
void
|
|
mail_hash_storage (CamelService *store, EvolutionStorage *storage)
|
|
{
|
|
camel_object_ref (CAMEL_OBJECT (store));
|
|
g_hash_table_insert (storages_hash, store, storage);
|
|
}
|
|
|
|
EvolutionStorage*
|
|
mail_lookup_storage (CamelStore *store)
|
|
{
|
|
EvolutionStorage *storage;
|
|
|
|
/* Because the storages_hash holds a reference to each store
|
|
* used as a key in it, none of them will ever be gc'ed, meaning
|
|
* any call to camel_session_get_{service,store} with the same
|
|
* URL will always return the same object. So this works.
|
|
*/
|
|
|
|
storage = g_hash_table_lookup (storages_hash, store);
|
|
if (storage)
|
|
gtk_object_ref (GTK_OBJECT (storage));
|
|
|
|
return storage;
|
|
}
|
|
|
|
void
|
|
mail_remove_storage (CamelStore *store)
|
|
{
|
|
EvolutionStorage *storage;
|
|
EvolutionShellClient *shell_client;
|
|
GNOME_Evolution_Shell corba_shell;
|
|
|
|
/* Because the storages_hash holds a reference to each store
|
|
* used as a key in it, none of them will ever be gc'ed, meaning
|
|
* any call to camel_session_get_{service,store} with the same
|
|
* URL will always return the same object. So this works.
|
|
*/
|
|
|
|
storage = g_hash_table_lookup (storages_hash, store);
|
|
g_hash_table_remove (storages_hash, store);
|
|
|
|
shell_client = evolution_shell_component_get_owner (shell_component);
|
|
corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client));
|
|
|
|
evolution_storage_deregister_on_shell (storage, corba_shell);
|
|
|
|
camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL);
|
|
camel_object_unref (CAMEL_OBJECT (store));
|
|
}
|
|
|
|
int
|
|
mail_storages_count (void)
|
|
{
|
|
return g_hash_table_size (storages_hash);
|
|
}
|
|
|
|
void
|
|
mail_storages_foreach (GHFunc func, gpointer data)
|
|
{
|
|
g_hash_table_foreach (storages_hash, func, data);
|
|
}
|