New way to connect a job_t.
[apps/madmutt.git] / lib-mx / pop-new.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  */
17 /*
18  *  Copyright © 2007 Pierre Habouzit
19  *  Copyright © 2000-2002 Vsevolod Volkov <vvv@mutt.org.ua>
20  */
21
22 #include <lib-sys/evtloop.h>
23 #include "pop.h"
24 #include "account.h"
25
26 #define POP3_PORT         110
27 #define POP3S_PORT        995
28
29 typedef struct pop_data_t {
30     int refcnt;
31     job_t *w;
32
33     ACCOUNT act;
34 } pop_data_t;
35 static void pop_data_delete(pop_data_t **tp);
36 DO_ARRAY_TYPE(pop_data_t, pop_data);
37 DO_ARRAY_FUNCS(pop_data_t, pop_data, pop_data_delete);
38
39 /****************************************************************************/
40 /* module                                                                   */
41 /****************************************************************************/
42
43 static pop_data_array conns;
44
45 static inline pop_data_t *pop_data_new(void)
46 {
47     pop_data_t *res = p_new(pop_data_t, 1);
48     res->refcnt = 1;
49     pop_data_array_append(&conns, res);
50     return res;
51 }
52 static inline pop_data_t *pop_data_dup(pop_data_t *t)
53 {
54     t->refcnt++;
55     return t;
56 }
57 static void pop_data_wipe(pop_data_t *pd)
58 {
59     if (pd->w)
60         IGNORE(el_job_release(pd->w, EL_KILLED));
61 }
62 static void pop_data_delete(pop_data_t **tp)
63 {
64     if (!*tp)
65         return;
66     if (--(*tp)->refcnt > 0) {
67         *tp = NULL;
68     } else {
69         for (int i = 0; i < conns.len; i++) {
70             if (conns.arr[i] == *tp) {
71                 pop_data_array_take(&conns, i);
72                 break;
73             }
74         }
75         pop_data_wipe(*tp);
76         p_delete(tp);
77     }
78 }
79
80 static __init void pop_initialize(void)
81 {
82     pop_data_array_init(&conns);
83 }
84 static __fini void pop_shutdown(void)
85 {
86     pop_data_array_wipe(&conns);
87 }
88
89 /****************************************************************************/
90 /* pop3 machine                                                             */
91 /****************************************************************************/
92
93 static int pop_setup(job_t *w, void *cfg)
94 {
95     w->ptr = pop_data_dup(cfg);
96     /* FIXME */ return el_job_release(w, EL_ERROR);
97     return 0;
98 }
99
100 static void pop_finalize(job_t *w, el_status reason)
101 {
102     pop_data_delete((pop_data_t **)(void *)&w->ptr);
103 }
104
105 static machine_t const pop_machine = {
106     .name     = "POP3",
107     .setup    = &pop_setup,
108     .finalize = &pop_finalize,
109 };
110
111 /****************************************************************************/
112 /* pop3 mx driver                                                           */
113 /****************************************************************************/
114
115 static int pop_parse_path(const char *path, ACCOUNT *act)
116 {
117     ciss_url_t url;
118     char s[BUFSIZ];
119
120     /* Defaults */
121     act->flags = 0;
122     act->port  = POP3_PORT;
123     act->type  = M_ACCT_TYPE_POP;
124     m_strcpy(s, sizeof(s), path);
125     url_parse_ciss(&url, s);
126
127     if (url.scheme == U_POP || url.scheme == U_POPS) {
128         if (url.scheme == U_POPS) {
129             act->has_ssl = 1;
130             act->port    = POP3S_PORT;
131         }
132
133         if (m_strisempty(url.path) && !mutt_account_fromurl(act, &url))
134             return 0;
135     }
136
137     return -1;
138 }
139
140 static pop_data_t *pop_find_conn(ACCOUNT *act)
141 {
142     pop_data_t *pd = NULL;
143
144     for (int i = 0; i < conns.len; i++) {
145         if (mutt_account_match(act, &conns.arr[i]->act)) {
146             pd = pop_data_dup(conns.arr[i]);
147             break;
148         }
149     }
150     if (!pd) {
151         pd = pop_data_new();
152         pd->act = *act;
153     }
154
155     return pd;
156 }
157
158 static int pop_open_mailbox(CONTEXT *ctx)
159 {
160     char buf[BUFSIZ];
161     ACCOUNT act;
162     ciss_url_t url;
163     pop_data_t *pd = NULL;
164
165     if (pop_parse_path(ctx->path, &act)) {
166         mutt_error(_("%s is an invalid POP path"), ctx->path);
167         mutt_sleep(2);
168         return -1;
169     }
170
171     p_clear(&url, 1);
172     mutt_account_tourl(&act, &url);
173
174     el_lock();
175     pd = pop_find_conn(&act);
176     if (false) {
177         ctx->data = pd;
178         url_ciss_tostring(&url, buf, sizeof (buf), 0);
179         m_strreplace(&ctx->path, buf);
180     } else {
181         pop_data_delete(&pd);
182     }
183     el_unlock();
184
185     return -1;
186 }
187
188 mx_t const pop_mx_ng = {
189     .type            = M_POP,
190     .mx_open_mailbox = pop_open_mailbox,
191 };