1 /*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * $Id: pop3driver_tools.c,v 1.19 2010/04/05 14:43:49 hoa Exp $
34 */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include "pop3driver_tools.h"
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif
48
49 #include "maildriver_types.h"
50 #include "mailpop3.h"
51 #include "pop3driver.h"
52 #include "pop3driver_cached.h"
53 #include "generic_cache.h"
54 #include "imfcache.h"
55 #include "mailmessage.h"
56 #include "mail_cache_db.h"
57
pop3driver_pop3_error_to_mail_error(int error)58 int pop3driver_pop3_error_to_mail_error(int error)
59 {
60 switch (error) {
61 case MAILPOP3_NO_ERROR:
62 return MAIL_NO_ERROR;
63
64 case MAILPOP3_ERROR_BAD_STATE:
65 return MAIL_ERROR_BAD_STATE;
66
67 case MAILPOP3_ERROR_UNAUTHORIZED:
68 return MAIL_ERROR_CONNECT;
69
70 case MAILPOP3_ERROR_STREAM:
71 return MAIL_ERROR_STREAM;
72
73 case MAILPOP3_ERROR_DENIED:
74 return MAIL_ERROR_CONNECT;
75
76 case MAILPOP3_ERROR_BAD_USER:
77 case MAILPOP3_ERROR_BAD_PASSWORD:
78 return MAIL_ERROR_LOGIN;
79
80 case MAILPOP3_ERROR_CANT_LIST:
81 return MAIL_ERROR_LIST;
82
83 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
84 return MAIL_ERROR_MSG_NOT_FOUND;
85
86 case MAILPOP3_ERROR_MEMORY:
87 return MAIL_ERROR_MEMORY;
88
89 case MAILPOP3_ERROR_CONNECTION_REFUSED:
90 return MAIL_ERROR_CONNECT;
91
92 case MAILPOP3_ERROR_APOP_NOT_SUPPORTED:
93 return MAIL_ERROR_NO_APOP;
94
95 case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED:
96 return MAIL_ERROR_CAPABILITY;
97
98 case MAILPOP3_ERROR_STLS_NOT_SUPPORTED:
99 return MAIL_ERROR_NO_TLS;
100
101 case MAILPOP3_ERROR_SSL:
102 return MAIL_ERROR_SSL;
103
104 default:
105 return MAIL_ERROR_INVAL;
106 }
107 }
108
109 static inline struct pop3_session_state_data *
session_get_data(mailsession * session)110 session_get_data(mailsession * session)
111 {
112 return session->sess_data;
113 }
114
session_get_pop3_session(mailsession * session)115 static inline mailpop3 * session_get_pop3_session(mailsession * session)
116 {
117 return session_get_data(session)->pop3_session;
118 }
119
120 static inline struct pop3_cached_session_state_data *
cached_session_get_data(mailsession * session)121 cached_session_get_data(mailsession * session)
122 {
123 return session->sess_data;
124 }
125
126 static inline mailsession *
cached_session_get_ancestor(mailsession * session)127 cached_session_get_ancestor(mailsession * session)
128 {
129 return cached_session_get_data(session)->pop3_ancestor;
130 }
131
132 static inline struct pop3_session_state_data *
cached_session_get_ancestor_data(mailsession * session)133 cached_session_get_ancestor_data(mailsession * session)
134 {
135 return session_get_data(cached_session_get_ancestor(session));
136 }
137
138 static inline mailpop3 *
cached_session_get_pop3_session(mailsession * session)139 cached_session_get_pop3_session(mailsession * session)
140 {
141 return session_get_pop3_session(cached_session_get_ancestor(session));
142 }
143
144
pop3driver_retr(mailsession * session,uint32_t indx,char ** result,size_t * result_len)145 int pop3driver_retr(mailsession * session, uint32_t indx,
146 char ** result, size_t * result_len)
147 {
148 char * msg_content;
149 size_t msg_length;
150 int r;
151
152 r = mailpop3_retr(session_get_pop3_session(session), indx,
153 &msg_content, &msg_length);
154
155 switch (r) {
156 case MAILPOP3_NO_ERROR:
157 break;
158 default:
159 return pop3driver_pop3_error_to_mail_error(r);
160 }
161
162 * result = msg_content;
163 * result_len = msg_length;
164
165 return MAIL_NO_ERROR;
166 }
167
pop3driver_header(mailsession * session,uint32_t indx,char ** result,size_t * result_len)168 int pop3driver_header(mailsession * session, uint32_t indx,
169 char ** result,
170 size_t * result_len)
171 {
172 char * headers;
173 size_t headers_length;
174 int r;
175
176 r = mailpop3_header(session_get_pop3_session(session),
177 indx, &headers, &headers_length);
178
179 switch (r) {
180 case MAILPOP3_NO_ERROR:
181 break;
182 default:
183 return pop3driver_pop3_error_to_mail_error(r);
184 }
185
186 * result = headers;
187 * result_len = headers_length;
188
189 return MAIL_NO_ERROR;
190 }
191
pop3driver_size(mailsession * session,uint32_t indx,size_t * result)192 int pop3driver_size(mailsession * session, uint32_t indx,
193 size_t * result)
194 {
195 mailpop3 * pop3;
196 carray * msg_tab;
197 struct mailpop3_msg_info * info;
198 int r;
199
200 pop3 = session_get_pop3_session(session);
201
202 r = mailpop3_list(pop3, &msg_tab);
203 if (r != MAILPOP3_NO_ERROR) {
204 return pop3driver_pop3_error_to_mail_error(r);
205 }
206
207 r = mailpop3_get_msg_info(pop3, indx, &info);
208 switch (r) {
209 case MAILPOP3_NO_ERROR:
210 break;
211 default:
212 return pop3driver_pop3_error_to_mail_error(r);
213 }
214
215 * result = info->msg_size;
216
217 return MAIL_NO_ERROR;
218 }
219
220 int
pop3driver_get_cached_flags(struct mail_cache_db * cache_db,MMAPString * mmapstr,mailsession * session,uint32_t num,struct mail_flags ** result)221 pop3driver_get_cached_flags(struct mail_cache_db * cache_db,
222 MMAPString * mmapstr,
223 mailsession * session,
224 uint32_t num,
225 struct mail_flags ** result)
226 {
227 int r;
228 char keyname[PATH_MAX];
229 struct mail_flags * flags;
230 int res;
231 struct mailpop3_msg_info * info;
232
233 r = mailpop3_get_msg_info(cached_session_get_pop3_session(session),
234 num, &info);
235 switch (r) {
236 case MAILPOP3_ERROR_BAD_STATE:
237 return MAIL_ERROR_BAD_STATE;
238 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
239 return MAIL_ERROR_MSG_NOT_FOUND;
240 case MAILPOP3_NO_ERROR:
241 break;
242 default:
243 return MAIL_ERROR_FETCH;
244 }
245
246 snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl);
247
248 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
249 if (r != MAIL_NO_ERROR) {
250 res = r;
251 goto err;
252 }
253
254 * result = flags;
255
256 return MAIL_NO_ERROR;
257
258 err:
259 return res;
260 }
261
262 int
pop3driver_write_cached_flags(struct mail_cache_db * cache_db,MMAPString * mmapstr,char * uid,struct mail_flags * flags)263 pop3driver_write_cached_flags(struct mail_cache_db * cache_db,
264 MMAPString * mmapstr,
265 char * uid,
266 struct mail_flags * flags)
267 {
268 int r;
269 char keyname[PATH_MAX];
270 int res;
271
272 snprintf(keyname, PATH_MAX, "%s-flags", uid);
273
274 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
275 if (r != MAIL_NO_ERROR) {
276 res = r;
277 goto err;
278 }
279
280 return MAIL_NO_ERROR;
281
282 err:
283 return res;
284 }
285
pop3_get_messages_list(mailpop3 * pop3,mailsession * session,mailmessage_driver * driver,struct mailmessage_list ** result)286 int pop3_get_messages_list(mailpop3 * pop3,
287 mailsession * session,
288 mailmessage_driver * driver,
289 struct mailmessage_list ** result)
290 {
291 carray * msg_tab;
292 carray * tab;
293 struct mailmessage_list * env_list;
294 unsigned int i;
295 int res;
296 int r;
297
298 r = mailpop3_list(pop3, &msg_tab);
299 if (r != MAILPOP3_NO_ERROR) {
300 res = pop3driver_pop3_error_to_mail_error(r);
301 goto err;
302 }
303
304 tab = carray_new(128);
305 if (tab == NULL) {
306 res = MAIL_ERROR_MEMORY;
307 goto err;
308 }
309
310 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
311 struct mailpop3_msg_info * pop3_info;
312 mailmessage * msg;
313
314 pop3_info = carray_get(msg_tab, i);
315
316 if (pop3_info == NULL)
317 continue;
318
319 if (pop3_info->msg_deleted)
320 continue;
321
322 msg = mailmessage_new();
323 if (msg == NULL) {
324 res = MAIL_ERROR_MEMORY;
325 goto free_list;
326 }
327
328 r = mailmessage_init(msg, session, driver,
329 (uint32_t) pop3_info->msg_index, pop3_info->msg_size);
330 if (r != MAIL_NO_ERROR) {
331 mailmessage_free(msg);
332 res = r;
333 goto free_list;
334 }
335
336 r = carray_add(tab, msg, NULL);
337 if (r < 0) {
338 mailmessage_free(msg);
339 res = MAIL_ERROR_MEMORY;
340 goto free_list;
341 }
342 }
343
344 env_list = mailmessage_list_new(/*list*/ tab);
345 if (env_list == NULL) {
346 res = MAIL_ERROR_MEMORY;
347 goto free_list;
348 }
349
350 * result = env_list;
351
352 return MAIL_NO_ERROR;
353
354 free_list:
355 for(i = 0 ; i < carray_count(tab) ; i ++)
356 mailmessage_free(carray_get(tab, i));
357 carray_free(tab);
358 err:
359 return res;
360 }
361