Statistics
| Revision:

root / libsylph / account.c @ 2721

History | View | Annotate | Download (10.5 kB)

1
/*
2
 * LibSylph -- E-Mail client library
3
 * Copyright (C) 1999-2009 Hiroyuki Yamamoto
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with this library; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23
24
#include "defs.h"
25
26
#include <glib.h>
27
#include <glib/gi18n.h>
28
#include <stdio.h>
29
#include <errno.h>
30
31
#include "folder.h"
32
#include "account.h"
33
#include "prefs.h"
34
#include "prefs_account.h"
35
#include "procmsg.h"
36
#include "procheader.h"
37
#include "utils.h"
38
#include "sylmain.h"
39
40
#define PREFSBUFSIZE                1024
41
42
PrefsAccount *cur_account;
43
44
static GList *account_list = NULL;
45
46
GHashTable *address_table;
47
48
49
void account_read_config_all(void)
50
{
51
        GSList *ac_label_list = NULL, *cur;
52
        gchar *rcpath;
53
        FILE *fp;
54
        gchar buf[PREFSBUFSIZE];
55
        PrefsAccount *ac_prefs;
56
57
        debug_print(_("Reading all config for each account...\n"));
58
59
        rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ACCOUNT_RC, NULL);
60
        if ((fp = g_fopen(rcpath, "rb")) == NULL) {
61
                if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
62
                g_free(rcpath);
63
                return;
64
        }
65
        g_free(rcpath);
66
67
        while (fgets(buf, sizeof(buf), fp) != NULL) {
68
                if (!strncmp(buf, "[Account: ", 10)) {
69
                        strretchomp(buf);
70
                        memmove(buf, buf + 1, strlen(buf));
71
                        buf[strlen(buf) - 1] = '\0';
72
                        debug_print("Found label: %s\n", buf);
73
                        ac_label_list = g_slist_append(ac_label_list,
74
                                                       g_strdup(buf));
75
                }
76
        }
77
        fclose(fp);
78
79
        /* read config data from file */
80
        cur_account = NULL;
81
        for (cur = ac_label_list; cur != NULL; cur = cur->next) {
82
                ac_prefs = prefs_account_new();
83
                prefs_account_read_config(ac_prefs, (gchar *)cur->data);
84
                account_list = g_list_append(account_list, ac_prefs);
85
                if (ac_prefs->is_default)
86
                        cur_account = ac_prefs;
87
        }
88
        /* if default is not set, assume first account as default */
89
        if (!cur_account && account_list) {
90
                ac_prefs = (PrefsAccount *)account_list->data;
91
                account_set_as_default(ac_prefs);
92
                cur_account = ac_prefs;
93
        }
94
95
        while (ac_label_list) {
96
                g_free(ac_label_list->data);
97
                ac_label_list = g_slist_remove(ac_label_list,
98
                                               ac_label_list->data);
99
        }
100
}
101
102
void account_write_config_all(void)
103
{
104
        prefs_account_write_config_all(account_list);
105
}
106
107
PrefsAccount *account_get_current_account(void)
108
{
109
        return cur_account;
110
}
111
112
PrefsAccount *account_find_from_smtp_server(const gchar *address,
113
                                            const gchar *smtp_server)
114
{
115
        GList *cur;
116
        PrefsAccount *ac;
117
118
        g_return_val_if_fail(address != NULL, NULL);
119
        g_return_val_if_fail(smtp_server != NULL, NULL);
120
121
        for (cur = account_list; cur != NULL; cur = cur->next) {
122
                ac = (PrefsAccount *)cur->data;
123
                if (!strcmp2(address, ac->address) &&
124
                    !strcmp2(smtp_server, ac->smtp_server))
125
                        return ac;
126
        }
127
128
        return NULL;
129
}
130
131
/*
132
 * account_find_from_address:
133
 * @address: Email address string.
134
 *
135
 * Find a mail (not news) account with the specified email address.
136
 *
137
 * Return value: The found account, or NULL if not found.
138
 */
139
PrefsAccount *account_find_from_address(const gchar *address)
140
{
141
        GList *cur;
142
        PrefsAccount *ac;
143
144
        g_return_val_if_fail(address != NULL, NULL);
145
146
        for (cur = account_list; cur != NULL; cur = cur->next) {
147
                ac = (PrefsAccount *)cur->data;
148
                if (ac->protocol != A_NNTP && ac->address &&
149
                    strcasestr(address, ac->address) != NULL)
150
                        return ac;
151
        }
152
153
        return NULL;
154
}
155
156
PrefsAccount *account_find_from_id(gint id)
157
{
158
        GList *cur;
159
        PrefsAccount *ac;
160
161
        for (cur = account_list; cur != NULL; cur = cur->next) {
162
                ac = (PrefsAccount *)cur->data;
163
                if (id == ac->account_id)
164
                        return ac;
165
        }
166
167
        return NULL;
168
}
169
170
PrefsAccount *account_find_from_item(FolderItem *item)
171
{
172
        PrefsAccount *ac;
173
174
        g_return_val_if_fail(item != NULL, NULL);
175
176
        ac = account_find_from_item_property(item);
177
        if (!ac)
178
                ac = item->folder->account;
179
180
        return ac;
181
}
182
183
PrefsAccount *account_find_from_item_property(FolderItem *item)
184
{
185
        PrefsAccount *ac;
186
187
        g_return_val_if_fail(item != NULL, NULL);
188
189
        ac = item->account;
190
        if (!ac) {
191
                FolderItem *cur_item = item->parent;
192
                while (cur_item != NULL) {
193
                        if (cur_item->account && cur_item->ac_apply_sub) {
194
                                ac = cur_item->account;
195
                                break;
196
                        }
197
                        cur_item = cur_item->parent;
198
                }
199
        }
200
201
        return ac;
202
}
203
204
PrefsAccount *account_find_from_message_file(const gchar *file)
205
{
206
        static HeaderEntry hentry[] = {{"From:",                  NULL, FALSE},
207
                                       {"X-Sylpheed-Account-Id:", NULL, FALSE},
208
                                       {"AID:",                          NULL, FALSE},
209
                                       {NULL,                          NULL, FALSE}};
210
211
        enum
212
        {
213
                H_FROM                        = 0,
214
                H_X_SYLPHEED_ACCOUNT_ID = 1,
215
                H_AID                        = 2
216
        };
217
218
        PrefsAccount *ac = NULL;
219
        FILE *fp;
220
        gchar *str;
221
        gchar buf[BUFFSIZE];
222
        gint hnum;
223
224
        g_return_val_if_fail(file != NULL, NULL);
225
226
        if ((fp = g_fopen(file, "rb")) == NULL) {
227
                FILE_OP_ERROR(file, "fopen");
228
                return NULL;
229
        }
230
231
        while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry))
232
               != -1) {
233
                str = buf + strlen(hentry[hnum].name);
234
                if (hnum == H_FROM)
235
                        ac = account_find_from_address(str);
236
                else if (hnum == H_X_SYLPHEED_ACCOUNT_ID || hnum == H_AID) {
237
                        PrefsAccount *tmp_ac;
238
239
                        tmp_ac = account_find_from_id(atoi(str));
240
                        if (tmp_ac) {
241
                                ac = tmp_ac;
242
                                break;
243
                        }
244
                }
245
        }
246
247
        fclose(fp);
248
        return ac;
249
}
250
251
PrefsAccount *account_find_from_msginfo(MsgInfo *msginfo)
252
{
253
        gchar *file;
254
        PrefsAccount *ac;
255
256
        file = procmsg_get_message_file(msginfo);
257
        ac = account_find_from_message_file(file);
258
        g_free(file);
259
260
        if (!ac && msginfo->folder)
261
                ac = account_find_from_item(msginfo->folder);
262
263
        return ac;
264
}
265
266
gboolean account_address_exist(const gchar *address)
267
{
268
        if (!address_table) {
269
                GList *cur;
270
271
                address_table = g_hash_table_new(g_str_hash, g_str_equal);
272
                for (cur = account_list; cur != NULL; cur = cur->next) {
273
                        PrefsAccount *ac = (PrefsAccount *)cur->data;
274
275
                        if (ac->address)
276
                                g_hash_table_insert(address_table, ac->address,
277
                                                    GINT_TO_POINTER(1));
278
                }
279
        }
280
281
        return (gboolean)g_hash_table_lookup(address_table, address);
282
}
283
284
void account_foreach(AccountFunc func, gpointer user_data)
285
{
286
        GList *cur;
287
288
        for (cur = account_list; cur != NULL; cur = cur->next)
289
                if (func((PrefsAccount *)cur->data, user_data) != 0)
290
                        return;
291
}
292
293
GList *account_get_list(void)
294
{
295
        return account_list;
296
}
297
298
void account_list_free(void)
299
{
300
        g_list_free(account_list);
301
        account_list = NULL;
302
}
303
304
void account_append(PrefsAccount *ac_prefs)
305
{
306
        account_list = g_list_append(account_list, ac_prefs);
307
        account_updated();
308
}
309
310
void account_set_as_default(PrefsAccount *ac_prefs)
311
{
312
        PrefsAccount *ap;
313
        GList *cur;
314
315
        for (cur = account_list; cur != NULL; cur = cur->next) {
316
                ap = (PrefsAccount *)cur->data;
317
                if (ap->is_default)
318
                        ap->is_default = FALSE;
319
        }
320
321
        ac_prefs->is_default = TRUE;
322
}
323
324
PrefsAccount *account_get_default(void)
325
{
326
        PrefsAccount *ap;
327
        GList *cur;
328
329
        for (cur = account_list; cur != NULL; cur = cur->next) {
330
                ap = (PrefsAccount *)cur->data;
331
                if (ap->is_default)
332
                        return ap;
333
        }
334
335
        return NULL;
336
}
337
338
#if 0
339
void account_set_missing_folder(void)
340
{
341
        PrefsAccount *ap;
342
        GList *cur;
343
344
        for (cur = account_list; cur != NULL; cur = cur->next) {
345
                ap = (PrefsAccount *)cur->data;
346
                if ((ap->protocol == A_IMAP4 || ap->protocol == A_NNTP) &&
347
                    !ap->folder) {
348
                        Folder *folder;
349
350
                        if (ap->protocol == A_IMAP4) {
351
                                folder = folder_new(F_IMAP, ap->account_name,
352
                                                    ap->recv_server);
353
                        } else {
354
                                folder = folder_new(F_NEWS, ap->account_name,
355
                                                    ap->nntp_server);
356
                        }
357
358
                        folder->account = ap;
359
                        ap->folder = REMOTE_FOLDER(folder);
360
                        folder_add(folder);
361
                        if (ap->protocol == A_IMAP4) {
362
                                if (main_window_toggle_online_if_offline
363
                                        (main_window_get())) {
364
                                        folder->klass->create_tree(folder);
365
                                        statusbar_pop_all();
366
                                }
367
                        }
368
                }
369
        }
370
}
371
#endif
372
373
FolderItem *account_get_special_folder(PrefsAccount *ac_prefs,
374
                                       SpecialFolderItemType type)
375
{
376
        FolderItem *item = NULL;
377
378
        g_return_val_if_fail(ac_prefs != NULL, NULL);
379
380
        switch (type) {
381
        case F_INBOX:
382
                if (ac_prefs->folder)
383
                        item = FOLDER(ac_prefs->folder)->inbox;
384
                if (!item)
385
                        item = folder_get_default_inbox();
386
                break;
387
        case F_OUTBOX:
388
                if (ac_prefs->set_sent_folder && ac_prefs->sent_folder) {
389
                        item = folder_find_item_from_identifier
390
                                (ac_prefs->sent_folder);
391
                }
392
                if (!item) {
393
                        if (ac_prefs->folder)
394
                                item = FOLDER(ac_prefs->folder)->outbox;
395
                        if (!item)
396
                                item = folder_get_default_outbox();
397
                }
398
                break;
399
        case F_DRAFT:
400
                if (ac_prefs->set_draft_folder && ac_prefs->draft_folder) {
401
                        item = folder_find_item_from_identifier
402
                                (ac_prefs->draft_folder);
403
                }
404
                if (!item) {
405
                        if (ac_prefs->folder)
406
                                item = FOLDER(ac_prefs->folder)->draft;
407
                        if (!item)
408
                                item = folder_get_default_draft();
409
                }
410
                break;
411
        case F_QUEUE:
412
                if (ac_prefs->set_queue_folder && ac_prefs->queue_folder) {
413
                        item = folder_find_item_from_identifier
414
                                (ac_prefs->queue_folder);
415
                        /* only allow queue-type folder */
416
                        if (item && item->stype != F_QUEUE)
417
                                item = NULL;
418
                }
419
                if (!item) {
420
                        if (ac_prefs->folder)
421
                                item = FOLDER(ac_prefs->folder)->queue;
422
                        if (!item)
423
                                item = folder_get_default_queue();
424
                }
425
                break;
426
        case F_TRASH:
427
                if (ac_prefs->set_trash_folder && ac_prefs->trash_folder) {
428
                        item = folder_find_item_from_identifier
429
                                (ac_prefs->trash_folder);
430
                }
431
                if (!item) {
432
                        if (ac_prefs->folder)
433
                                item = FOLDER(ac_prefs->folder)->trash;
434
                        if (!item)
435
                                item = folder_get_default_trash();
436
                }
437
                break;
438
        default:
439
                break;
440
        }
441
442
        return item;
443
}
444
445
void account_destroy(PrefsAccount *ac_prefs)
446
{
447
        g_return_if_fail(ac_prefs != NULL);
448
449
        folder_unref_account_all(ac_prefs);
450
451
        account_list = g_list_remove(account_list, ac_prefs);
452
        if (cur_account == ac_prefs)
453
                cur_account = NULL;
454
        prefs_account_free(ac_prefs);
455
456
        if (!cur_account && account_list) {
457
                cur_account = account_get_default();
458
                if (!cur_account) {
459
                        ac_prefs = (PrefsAccount *)account_list->data;
460
                        account_set_as_default(ac_prefs);
461
                        cur_account = ac_prefs;
462
                }
463
        }
464
465
        account_updated();
466
}
467
468
static guint account_update_lock_count = 0;
469
470
void account_update_lock(void)
471
{
472
        account_update_lock_count++;
473
}
474
475
void account_update_unlock(void)
476
{
477
        if (account_update_lock_count > 0)
478
                account_update_lock_count--;
479
}
480
481
void account_updated(void)
482
{
483
        if (account_update_lock_count)
484
                return;
485
486
        if (address_table) {
487
                g_hash_table_destroy(address_table);
488
                address_table = NULL;
489
        }
490
491
        if (syl_app_get())
492
                g_signal_emit_by_name(syl_app_get(), "account-updated");
493
}