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