source: trunk/third/evolution/mail/mail-send-recv.c @ 17188

Revision 17188, 23.4 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17187, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 *  Authors: Michael Zucchi <NotZed@ximian.com>
4 *
5 *  Copyright 2001 Ximian, Inc. (www.ximian.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <stdio.h>
28#include <string.h>
29
30/* for the dialogue stuff */
31#include <glib.h>
32#include <gtk/gtkmain.h>
33#include <libgnomeui/gnome-stock.h>
34#include <libgnomeui/gnome-dialog.h>
35#include <libgnomeui/gnome-window-icon.h>
36
37#include "filter/filter-filter.h"
38#include "camel/camel-filter-driver.h"
39#include "camel/camel-folder.h"
40#include "camel/camel-operation.h"
41
42#include "evolution-storage.h"
43
44#include "mail.h"
45#include "mail-mt.h"
46#include "mail-config.h"
47#include "mail-session.h"
48#include "mail-tools.h"
49#include "mail-ops.h"
50#include "mail-send-recv.h"
51#include "mail-folder-cache.h"
52
53#define d(x)
54
55/* ms between status updates to the gui */
56#define STATUS_TIMEOUT (250)
57
58/* send/receive email */
59
60/* ********************************************************************** */
61/*  This stuff below is independent of the stuff above */
62
63/* this stuff is used to keep track of which folders filters have accessed, and
64   what not. the thaw/refreeze thing doesn't really seem to work though */
65struct _folder_info {
66        char *uri;
67        CamelFolder *folder;
68        time_t update;
69        int count;              /* how many times updated, to slow it down as we go, if we have lots */
70};
71
72struct _send_data {
73        GList *infos;
74
75        GnomeDialog *gd;
76        int cancelled;
77
78        CamelFolder *inbox;     /* since we're never asked to update this one, do it ourselves */
79        time_t inbox_update;
80
81        CamelFolder *current_folder;
82
83        GMutex *lock;
84        GHashTable *folders;
85
86        GHashTable *active;     /* send_info's by uri */
87};
88
89typedef enum {
90        SEND_RECEIVE,           /* receiver */
91        SEND_SEND,              /* sender */
92        SEND_UPDATE,            /* imap-like 'just update folder info' */
93        SEND_INVALID
94} send_info_t ;
95
96typedef enum {
97        SEND_ACTIVE,
98        SEND_CANCELLED,
99        SEND_COMPLETE
100} send_state_t;
101
102struct _send_info {
103        send_info_t type;               /* 0 = fetch, 1 = send */
104        CamelOperation *cancel;
105        char *uri;
106        int keep;
107        send_state_t state;
108        GtkProgressBar *bar;
109        GtkButton *stop;
110        GtkLabel *status;
111
112        int timeout_id;
113        char *what;
114        int pc;
115
116        /*time_t update;*/
117        struct _send_data *data;
118};
119
120static struct _send_data *send_data = NULL;
121static GtkWidget *send_recv_dialogue = NULL;
122
123static struct _send_data *setup_send_data(void)
124{
125        struct _send_data *data;
126       
127        if (send_data == NULL) {
128                send_data = data = g_malloc0(sizeof(*data));
129                data->lock = g_mutex_new();
130                data->folders = g_hash_table_new(g_str_hash, g_str_equal);
131                data->inbox = mail_tool_get_local_inbox(NULL);
132                data->active = g_hash_table_new(g_str_hash, g_str_equal);
133        }
134        return send_data;
135}
136
137static void
138receive_cancel(GtkButton *button, struct _send_info *info)
139{
140        if (info->state == SEND_ACTIVE) {
141                camel_operation_cancel(info->cancel);
142                if (info->status)
143                        gtk_label_set_text(info->status, _("Cancelling..."));
144                info->state = SEND_CANCELLED;
145        }
146        if (info->stop)
147                gtk_widget_set_sensitive((GtkWidget *)info->stop, FALSE);
148}
149
150static void
151free_folder_info(void *key, struct _folder_info *info, void *data)
152{
153        /*camel_folder_thaw (info->folder);     */
154        mail_sync_folder(info->folder, NULL, NULL);
155        camel_object_unref((CamelObject *)info->folder);
156        g_free(info->uri);
157}
158
159static void free_send_info(void *key, struct _send_info *info, void *data)
160{
161        d(printf("Freeing send info %p\n", info));
162        g_free(info->uri);
163        camel_operation_unref(info->cancel);
164        if (info->timeout_id != 0)
165                gtk_timeout_remove(info->timeout_id);
166        g_free(info->what);
167        g_free(info);
168}
169
170static void
171free_send_data(void)
172{
173        struct _send_data *data = send_data;
174
175        g_assert(g_hash_table_size(data->active) == 0);
176
177        if (data->inbox) {
178                mail_sync_folder(data->inbox, NULL, NULL);
179                /*camel_folder_thaw (data->inbox);              */
180                camel_object_unref((CamelObject *)data->inbox);
181        }
182        if (data->current_folder) {
183                mail_refresh_folder(data->current_folder, NULL, NULL);
184                camel_object_unref((CamelObject *)data->current_folder);
185        }
186        g_list_free(data->infos);
187        g_hash_table_foreach(data->active, (GHFunc)free_send_info, NULL);
188        g_hash_table_destroy(data->active);
189        g_hash_table_foreach(data->folders, (GHFunc)free_folder_info, NULL);
190        g_hash_table_destroy(data->folders);
191        g_mutex_free(data->lock);
192        g_free(data);
193        send_data = NULL;
194}
195
196static void cancel_send_info(void *key, struct _send_info *info, void *data)
197{
198        receive_cancel(info->stop, info);
199}
200
201static void hide_send_info(void *key, struct _send_info *info, void *data)
202{
203        info->stop = NULL;
204        info->bar = NULL;
205        info->status = NULL;
206
207        if (info->timeout_id != 0) {
208                gtk_timeout_remove (info->timeout_id);
209                info->timeout_id = 0;
210        }
211}
212
213static void
214dialog_destroy (GtkProgressBar *bar, struct _send_data *data)
215{
216        g_hash_table_foreach (data->active, (GHFunc) hide_send_info, NULL);
217        data->gd = NULL;
218}
219
220static void
221dialogue_clicked(GnomeDialog *gd, int button, struct _send_data *data)
222{
223        switch(button) {
224        case 0:
225                d(printf("cancelled whole thing\n"));
226                if (!data->cancelled) {
227                        data->cancelled = TRUE;
228                        g_hash_table_foreach(data->active, (GHFunc)cancel_send_info, NULL);
229                }
230                gnome_dialog_set_sensitive(gd, 0, FALSE);
231                break;
232        case -1:                /* dialogue vanished, so make out its just hidden */
233                d(printf("hiding dialogue\n"));
234                g_hash_table_foreach(data->active, (GHFunc)hide_send_info, NULL);
235                data->gd = NULL;
236                break;
237        }
238}
239
240static void operation_status(CamelOperation *op, const char *what, int pc, void *data);
241static int operation_status_timeout(void *data);
242
243static char *
244format_url(const char *internal_url)
245{
246        CamelURL *url;
247        char *pretty_url;
248
249        url = camel_url_new(internal_url, NULL);
250        if (url->host)
251                pretty_url = g_strdup_printf(_("Server: %s, Type: %s"), url->host, url->protocol);
252        else if (url->path)
253                pretty_url = g_strdup_printf(_("Path: %s, Type: %s"), url->path, url->protocol);
254        else
255                pretty_url = g_strdup_printf(_("Type: %s"), url->protocol);
256
257        camel_url_free(url);
258
259        return pretty_url;
260}
261
262static send_info_t get_receive_type(const char *url)
263{
264        CamelProvider *provider;
265
266        provider = camel_session_get_provider (session, url, NULL);
267        if (!provider)
268                return SEND_INVALID;
269       
270        if (provider->flags & CAMEL_PROVIDER_IS_STORAGE)
271                return SEND_UPDATE;
272        else
273                return SEND_RECEIVE;
274}
275
276static struct _send_data *
277build_dialogue (GSList *sources, CamelFolder *current_folder, CamelFolder *outbox, const char *destination)
278{
279        GnomeDialog *gd;
280        GtkTable *table;
281        int row;
282        GList *list = NULL;
283        struct _send_data *data;
284        GtkWidget *send_icon, *recv_icon;
285        GtkLabel *label, *status_label;
286        GtkProgressBar *bar;
287        GtkButton *stop;
288        GtkHSeparator *line;
289        struct _send_info *info;
290        char *pretty_url;
291       
292        gd = (GnomeDialog *)send_recv_dialogue = gnome_dialog_new (_("Send & Receive Mail"), NULL);
293        gtk_signal_connect((GtkObject *)gd, "destroy", gtk_widget_destroyed, &send_recv_dialogue);
294        gnome_dialog_append_button_with_pixmap (gd, _("Cancel All"), GNOME_STOCK_BUTTON_CANCEL);
295       
296        gtk_window_set_policy (GTK_WINDOW (gd), FALSE, FALSE, FALSE); 
297        gnome_window_icon_set_from_file (GTK_WINDOW (gd), EVOLUTION_ICONSDIR "/send-receive.xpm");
298       
299        table = (GtkTable *)gtk_table_new (g_slist_length (sources), 4, FALSE);
300        gtk_box_pack_start (GTK_BOX (gd->vbox), GTK_WIDGET (table), TRUE, TRUE, 0);
301
302        /* must bet setup after send_recv_dialogue as it may re-trigger send-recv button */
303        data = setup_send_data ();
304       
305        row = 0;
306        while (sources) {
307                MailConfigService *source = sources->data;
308               
309                if (!source->url || !source->enabled) {
310                        sources = sources->next;
311                        continue;
312                }
313               
314                /* see if we have an outstanding download active */
315                info = g_hash_table_lookup (data->active, source->url);
316                if (info == NULL) {
317                        send_info_t type;
318                       
319                        type = get_receive_type (source->url);
320                        if (type == SEND_INVALID) {
321                                sources = sources->next;
322                                continue;
323                        }
324                       
325                        info = g_malloc0 (sizeof (*info));
326                        info->type = type;
327                        d(printf("adding source %s\n", source->url));
328                       
329                        info->uri = g_strdup (source->url);
330                        info->keep = source->keep_on_server;
331                        info->cancel = camel_operation_new (operation_status, info);
332                        info->state = SEND_ACTIVE;
333                        info->timeout_id = gtk_timeout_add (STATUS_TIMEOUT, operation_status_timeout, info);
334                       
335                        g_hash_table_insert (data->active, info->uri, info);
336                        list = g_list_prepend (list, info);
337                } else if (info->bar != NULL) {
338                        /* incase we get the same source pop up again */
339                        sources = sources->next;
340                        continue;
341                } else if (info->timeout_id == 0)
342                        info->timeout_id = gtk_timeout_add (STATUS_TIMEOUT, operation_status_timeout, info);
343               
344                recv_icon = gnome_pixmap_new_from_file (EVOLUTION_BUTTONSDIR "/receive-24.png");
345               
346                pretty_url = format_url (source->url);
347                label = (GtkLabel *)gtk_label_new (pretty_url);
348                g_free (pretty_url);
349               
350                bar = (GtkProgressBar *)gtk_progress_bar_new ();
351                gtk_progress_set_show_text (GTK_PROGRESS (bar), FALSE);
352               
353                stop = (GtkButton *)gnome_stock_button (GNOME_STOCK_BUTTON_CANCEL);
354                status_label = (GtkLabel *)gtk_label_new ((info->type == SEND_UPDATE) ? _("Updating...") :
355                                                          _("Waiting..."));
356               
357                /* gtk_object_set (data->label, "bold", TRUE, NULL); */
358                gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
359                gtk_misc_set_alignment (GTK_MISC (status_label), 0, .5);
360               
361                gtk_table_attach (table, (GtkWidget *)recv_icon, 0, 1, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
362                gtk_table_attach (table, (GtkWidget *)label, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 3, 1);
363                gtk_table_attach (table, (GtkWidget *)bar, 2, 3, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
364                gtk_table_attach (table, (GtkWidget *)stop, 3, 4, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
365                gtk_table_attach (table, (GtkWidget *)status_label, 1, 2, row+1, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
366               
367                info->bar = bar;
368                info->status = status_label;
369                info->stop = stop;
370                info->data = data;
371               
372                gtk_signal_connect (GTK_OBJECT (stop), "clicked", receive_cancel, info);
373                sources = sources->next;
374                row = row + 2;
375        }
376       
377        line = (GtkHSeparator *)gtk_hseparator_new ();
378        gtk_table_attach (table, GTK_WIDGET (line), 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 3, 3);
379        row++;
380        gtk_widget_show_all (GTK_WIDGET (table));
381       
382        if (outbox && destination) {
383                info = g_hash_table_lookup (data->active, destination);
384                if (info == NULL) {
385                        info = g_malloc0 (sizeof (*info));
386                        info->type = SEND_SEND;
387                        d(printf("adding dest %s\n", destination));
388                       
389                        info->uri = g_strdup (destination);
390                        info->keep = FALSE;
391                        info->cancel = camel_operation_new (operation_status, info);
392                        info->state = SEND_ACTIVE;
393                        info->timeout_id = gtk_timeout_add (STATUS_TIMEOUT, operation_status_timeout, info);
394                       
395                        g_hash_table_insert (data->active, info->uri, info);
396                        list = g_list_prepend (list, info);
397                } else if (info->timeout_id == 0)
398                        info->timeout_id = gtk_timeout_add (STATUS_TIMEOUT, operation_status_timeout, info);
399               
400                send_icon  = gnome_pixmap_new_from_file (EVOLUTION_BUTTONSDIR "/send-24.png");
401               
402                pretty_url = format_url (destination);
403                label = (GtkLabel *)gtk_label_new (pretty_url);
404                g_free (pretty_url);
405               
406                bar = (GtkProgressBar *)gtk_progress_bar_new ();
407                stop = (GtkButton *)gnome_stock_button (GNOME_STOCK_BUTTON_CANCEL);
408                status_label = (GtkLabel *)gtk_label_new (_("Waiting..."));
409               
410                gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
411                gtk_misc_set_alignment (GTK_MISC (status_label), 0, .5);
412                gtk_progress_set_show_text (GTK_PROGRESS (bar), FALSE);
413               
414                gtk_table_attach (table, GTK_WIDGET (send_icon), 0, 1, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
415                gtk_table_attach (table, GTK_WIDGET (label), 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 3, 1);
416                gtk_table_attach (table, GTK_WIDGET (bar), 2, 3, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
417                gtk_table_attach (table, GTK_WIDGET (stop), 3, 4, row, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
418                gtk_table_attach (table, GTK_WIDGET (status_label), 1, 2, row+1, row+2, GTK_EXPAND | GTK_FILL, 0, 3, 1);
419               
420                info->bar = bar;
421                info->stop = stop;
422                info->data = data;
423                info->status = status_label;
424               
425                gtk_signal_connect (GTK_OBJECT (stop), "clicked", receive_cancel, info);
426                gtk_widget_show_all (GTK_WIDGET (table));
427        }
428       
429        gtk_widget_show (GTK_WIDGET (gd));
430       
431        gtk_signal_connect (GTK_OBJECT (gd), "clicked", dialogue_clicked, data);
432        gtk_signal_connect (GTK_OBJECT (gd), "destroy", dialog_destroy, data);
433       
434        data->infos = list;
435        data->gd = gd;
436        data->current_folder = current_folder;
437        camel_object_ref (CAMEL_OBJECT (current_folder));
438       
439        return data;
440}
441
442static void
443update_folders(char *uri, struct _folder_info *info, void *data)
444{
445        time_t now = *((time_t *)data);
446
447        d(printf("checking update for folder: %s\n", info->uri));
448
449        /* let it flow through to the folders every 10 seconds */
450        /* we back off slowly as we progress */
451        if (now > info->update+10+info->count*5) {
452                d(printf("upating a folder: %s\n", info->uri));
453                /*camel_folder_thaw(info->folder);
454                  camel_folder_freeze(info->folder);*/
455                info->update = now;
456                info->count++;
457        }
458}
459
460static void set_send_status(struct _send_info *info, const char *desc, int pc)
461{
462        /* FIXME: LOCK */
463        g_free(info->what);
464        info->what = g_strdup(desc);
465        info->pc = pc;
466}
467
468static void
469receive_status (CamelFilterDriver *driver, enum camel_filter_status_t status, int pc, const char *desc, void *data)
470{
471        struct _send_info *info = data;
472        time_t now = time(0);
473
474        /* let it flow through to the folder, every now and then too? */
475        g_hash_table_foreach(info->data->folders, (GHFunc)update_folders, &now);
476
477        if (info->data->inbox && now > info->data->inbox_update+20) {
478                d(printf("updating inbox too\n"));
479                /* this doesn't seem to work right :( */
480                /*camel_folder_thaw(info->data->inbox);
481                  camel_folder_freeze(info->data->inbox);*/
482                info->data->inbox_update = now;
483        }
484
485        /* we just pile them onto the port, assuming it can handle it.
486           We could also have a receiver port and see if they've been processed
487           yet, so if this is necessary its not too hard to add */
488        /* the mail_gui_port receiver will free everything for us */
489        switch (status) {
490        case CAMEL_FILTER_STATUS_START:
491        case CAMEL_FILTER_STATUS_END:
492                set_send_status(info, desc, pc);
493                break;
494        default:
495                break;
496        }
497}
498
499static int operation_status_timeout(void *data)
500{
501        struct _send_info *info = data;
502
503        if (info->bar) {
504                gtk_progress_set_percentage((GtkProgress *)info->bar, (gfloat)(info->pc/100.0));
505                gtk_label_set_text(info->status, info->what);
506                return TRUE;
507        }
508
509        return FALSE;
510}
511
512/* for camel operation status */
513static void operation_status(CamelOperation *op, const char *what, int pc, void *data)
514{
515        struct _send_info *info = data;
516
517        /*printf("Operation '%s', percent %d\n");*/
518        switch (pc) {
519        case CAMEL_OPERATION_START:
520                pc = 0;
521                break;
522        case CAMEL_OPERATION_END:
523                pc = 100;
524                break;
525        }
526
527        set_send_status(info, what, pc);
528}
529
530/* when receive/send is complete */
531static void
532receive_done (char *uri, void *data)
533{
534        struct _send_info *info = data;
535
536        if (info->bar) {
537                gtk_progress_set_percentage((GtkProgress *)info->bar, (gfloat)1.0);
538
539                switch(info->state) {
540                case SEND_CANCELLED:
541                        gtk_label_set_text(info->status, _("Cancelled."));
542                        break;
543                default:
544                        info->state = SEND_COMPLETE;
545                        gtk_label_set_text(info->status, _("Complete."));
546                }
547        }
548
549        if (info->stop)
550                gtk_widget_set_sensitive((GtkWidget *)info->stop, FALSE);
551
552        /* remove/free this active download */
553        d(printf("%s: freeing info %p\n", __FUNCTION__, info));
554        g_hash_table_remove(info->data->active, info->uri);
555        info->data->infos = g_list_remove(info->data->infos, info);
556
557        if (g_hash_table_size(info->data->active) == 0) {
558                if (info->data->gd)
559                        gnome_dialog_close(info->data->gd);
560                free_send_data();
561        }
562
563        free_send_info(NULL, info, NULL);
564}
565
566/* same for updating */
567static void
568receive_update_done(CamelStore *store, CamelFolderInfo *info, void *data)
569{
570        receive_done("", data);
571}
572
573/* although we dont do anythign smart here yet, there is no need for this interface to
574   be available to anyone else.
575   This can also be used to hook into which folders are being updated, and occasionally
576   let them refresh */
577static CamelFolder *
578receive_get_folder(CamelFilterDriver *d, const char *uri, void *data, CamelException *ex)
579{
580        struct _send_info *info = data;
581        CamelFolder *folder;
582        struct _folder_info *oldinfo;
583        char *oldkey;
584
585        g_mutex_lock(info->data->lock);
586        oldinfo = g_hash_table_lookup(info->data->folders, uri);
587        g_mutex_unlock(info->data->lock);
588        if (oldinfo) {
589                camel_object_ref((CamelObject *)oldinfo->folder);
590                return oldinfo->folder;
591        }
592        folder = mail_tool_uri_to_folder (uri, 0, ex);
593        if (!folder)
594                return NULL;
595
596        /* we recheck that the folder hasn't snuck in while we were loading it... */
597        /* and we assume the newer one is the same, but unref the old one anyway */
598        g_mutex_lock(info->data->lock);
599       
600        if (g_hash_table_lookup_extended(info->data->folders, uri, (void **)&oldkey, (void **)&oldinfo)) {
601                camel_object_unref((CamelObject *)oldinfo->folder);
602                oldinfo->folder = folder;
603        } else {
604                /*camel_folder_freeze (folder);         */
605                oldinfo = g_malloc0(sizeof(*oldinfo));
606                oldinfo->folder = folder;
607                oldinfo->uri = g_strdup(uri);
608                g_hash_table_insert(info->data->folders, oldinfo->uri, oldinfo);
609        }
610       
611        camel_object_ref (CAMEL_OBJECT (folder));
612       
613        g_mutex_unlock(info->data->lock);
614       
615        return folder;
616}
617
618static void
619receive_update_got_store (char *uri, CamelStore *store, void *data)
620{
621        struct _send_info *info = data;
622       
623        if (store) {
624                EvolutionStorage *storage = mail_lookup_storage (store);
625               
626                mail_note_store(store, storage, CORBA_OBJECT_NIL, receive_update_done, info);
627        } else {
628                receive_done ("", info);
629        }
630}
631
632void mail_send_receive (CamelFolder *current_folder)
633{
634        GSList *sources;
635        GList *scan;
636        struct _send_data *data;
637        extern CamelFolder *outbox_folder;
638        const MailConfigAccount *account;
639
640        if (send_recv_dialogue != NULL) {
641                if (GTK_WIDGET_REALIZED(send_recv_dialogue)) {
642                        gdk_window_show(send_recv_dialogue->window);
643                        gdk_window_raise(send_recv_dialogue->window);
644                }
645                return;
646        }
647
648        sources = mail_config_get_sources();
649        if (!sources)
650                return;
651        account = mail_config_get_default_account();
652        if (!account || !account->transport)
653                return;
654       
655        /* what to do about pop before smtp ?
656           Well, probably hook into receive_done or receive_status on
657           the right pop account, and when it is, then kick off the
658           smtp one. */
659        data = build_dialogue(sources, current_folder, outbox_folder, account->transport->url);
660        scan = data->infos;
661        while (scan) {
662                struct _send_info *info = scan->data;
663
664                switch(info->type) {
665                case SEND_RECEIVE:
666                        mail_fetch_mail(info->uri, info->keep,
667                                        FILTER_SOURCE_INCOMING,
668                                        info->cancel,
669                                        receive_get_folder, info,
670                                        receive_status, info,
671                                        receive_done, info);
672                        break;
673                case SEND_SEND:
674                        /* todo, store the folder in info? */
675                        mail_send_queue(outbox_folder, info->uri,
676                                        FILTER_SOURCE_OUTGOING,
677                                        info->cancel,
678                                        receive_get_folder, info,
679                                        receive_status, info,
680                                        receive_done, info);
681                        break;
682                case SEND_UPDATE:
683                        /* FIXME: error reporting? */
684                        mail_get_store(info->uri, receive_update_got_store, info);
685                        break;
686                default:
687                        g_assert_not_reached ();
688                }
689                scan = scan->next;
690        }
691}
692
693struct _auto_data {
694        char *uri;
695        int keep;               /* keep on server flag */
696        int period;             /* in seconds */
697        int timeout_id;
698};
699
700static GHashTable *auto_active;
701
702static gboolean
703auto_timeout(void *data)
704{
705        struct _auto_data *info = data;
706
707        if (camel_session_is_online(session))
708                mail_receive_uri(info->uri, info->keep);
709
710        return TRUE;
711}
712
713static void auto_setup_set(void *key, struct _auto_data *info, GHashTable *set)
714{
715        g_hash_table_insert(set, info->uri, info);
716}
717
718static void auto_clean_set(void *key, struct _auto_data *info, GHashTable *set)
719{
720        d(printf("removing auto-check for %s %p\n", info->uri, info));
721        g_hash_table_remove(set, info->uri);
722        gtk_timeout_remove(info->timeout_id);
723        g_free(info->uri);
724        g_free(info);
725}
726
727/* call to setup initial, and after changes are made to the config */
728/* FIXME: Need a cleanup funciton for when object is deactivated */
729void
730mail_autoreceive_setup (void)
731{
732        GHashTable *set_hash;
733        GSList *sources;
734       
735        sources = mail_config_get_sources();
736       
737        if (!sources)
738                return;
739
740        if (auto_active == NULL)
741                auto_active = g_hash_table_new(g_str_hash, g_str_equal);
742
743        set_hash = g_hash_table_new(g_str_hash, g_str_equal);
744        g_hash_table_foreach(auto_active, (GHFunc)auto_setup_set, set_hash);
745
746        while (sources) {
747                MailConfigService *source = sources->data;
748                if (source->url && source->auto_check && source->enabled) {
749                        struct _auto_data *info;
750
751                        d(printf("setting up auto-receive mail for : %s\n", source->url));
752
753                        g_hash_table_remove(set_hash, source->url);
754                        info = g_hash_table_lookup(auto_active, source->url);
755                        if (info) {
756                                info->keep = source->keep_on_server;
757                                if (info->period != source->auto_check_time*60) {
758                                        info->period = source->auto_check_time*60;
759                                        gtk_timeout_remove(info->timeout_id);
760                                        info->timeout_id = gtk_timeout_add(info->period*1000, auto_timeout, info);
761                                }
762                        } else {
763                                info = g_malloc0(sizeof(*info));
764                                info->uri = g_strdup(source->url);
765                                info->keep = source->keep_on_server;
766                                info->period = source->auto_check_time*60;
767                                info->timeout_id = gtk_timeout_add(info->period*1000, auto_timeout, info);
768                                g_hash_table_insert(auto_active, info->uri, info);
769                                /* If we do this at startup, it can cause the logon dialogue to be hidden,
770                                   so lets not */
771                                /*mail_receive_uri(source->url, source->keep_on_server);*/
772                        }
773                }
774
775                sources = sources->next;
776        }
777
778        g_hash_table_foreach(set_hash, (GHFunc)auto_clean_set, auto_active);
779        g_hash_table_destroy(set_hash);
780}
781
782/* we setup the download info's in a hashtable, if we later need to build the gui, we insert
783   them in to add them. */
784void
785mail_receive_uri (const char *uri, int keep)
786{
787        struct _send_info *info;
788        struct _send_data *data;
789        extern CamelFolder *outbox_folder;
790        send_info_t type;
791       
792        data = setup_send_data();
793        info = g_hash_table_lookup(data->active, uri);
794        if (info != NULL) {
795                d(printf("download of %s still in progress\n", uri));
796                return;
797        }
798       
799        d(printf("starting non-interactive download of '%s'\n", uri));
800       
801        type = get_receive_type (uri);
802        if (type == SEND_INVALID) {
803                d(printf ("unsupported provider: '%s'\n", uri));
804                return;
805        }
806       
807        info = g_malloc0 (sizeof (*info));
808        info->type = type;
809        info->bar = NULL;
810        info->status = NULL;
811        info->uri = g_strdup (uri);
812        info->keep = keep;
813        info->cancel = camel_operation_new (operation_status, info);
814        info->stop = NULL;
815        info->data = data;
816        info->state = SEND_ACTIVE;
817        info->timeout_id = 0;
818       
819        d(printf("Adding new info %p\n", info));
820       
821        g_hash_table_insert (data->active, info->uri, info);
822       
823        switch (info->type) {
824        case SEND_RECEIVE:
825                mail_fetch_mail (info->uri, info->keep,
826                                 FILTER_SOURCE_INCOMING,
827                                 info->cancel,
828                                 receive_get_folder, info,
829                                 receive_status, info,
830                                 receive_done, info);
831                break;
832        case SEND_SEND:
833                /* todo, store the folder in info? */
834                mail_send_queue (outbox_folder, info->uri,
835                                 FILTER_SOURCE_OUTGOING,
836                                 info->cancel,
837                                 receive_get_folder, info,
838                                 receive_status, info,
839                                 receive_done, info);
840                break;
841        case SEND_UPDATE:
842                /* FIXME: error reporting? */
843                mail_get_store (info->uri, receive_update_got_store, info);
844                break;
845        default:
846                g_assert_not_reached ();
847        }
848}
Note: See TracBrowser for help on using the repository browser.