/[libspopc]/objects.c
ViewVC logotype

Contents of /objects.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 19 - (show annotations)
Fri Nov 26 16:45:52 2010 UTC (10 years ago) by ben
File MIME type: text/plain
File size: 10030 byte(s)
fix memory leak on error (M. Diaz)
1 /* this is objects.c, part of the libspopc library sources
2 * copyright © 2002- Benoit Rouits <brouits@free.fr>
3 * released under the terms of the GNU Lesser General Public Licence.
4 *
5 * libspopc offers simple API for a pop3 client.
6 * See RFC 1725 for pop3 specifications.
7 * more information on http://herewe.servebeer.com/libspopc/
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27
28 #ifdef WIN32
29 #include <winsock.h>
30 #else
31 #include <sys/socket.h>
32 #include <netdb.h>
33 #endif
34
35 #include "libspopc.h"
36
37 /***************************************
38 * high-level methods for a simple mua *
39 ***************************************/
40
41 DLLIMPORT char* popbegin(const char* servername, const char* user, const char* pass, popsession** sp){
42 /* prepares, connect and get lists of messages stored on pop server */
43 /* you must give a valid servername, user and pass */
44 /* returns an error message if a problem occurs, else NULL */
45 char* resp=NULL;
46 char* err=NULL;
47 char *hostname, *ptr_port;
48 int nport;
49 popsession* s = NULL;
50
51 if(!(servername && user && pass)){
52 err=strdup("popbegin: some NULL args !");
53 goto error;
54 }
55 s=(popsession*)malloc(sizeof(popsession));
56 if(!s){
57 err=strdup("popbegin.malloc: failed\n");
58 goto error;
59 }
60 /* basic default construction */
61 s->sock=BAD_SOCK;
62 s->connection=NULL;
63 s->server=NULL;
64 s->list=NULL;
65 s->uidl=NULL;
66 s->bytes=-1;
67 s->last=-1;
68 s->num=-1;
69 s->del=0; /* no deletion (by default) at this time */
70 s->sync=1; /* this is sync'ed at this time (no cnx yet) */
71
72 s->server=(struct hostent*)malloc(sizeof(struct hostent));
73 if(!(s->server)){
74 err=strdup("popbegin.malloc: failed\n");
75 goto error;
76 }
77 s->connection=(struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
78 if(!(s->connection)){
79 err=strdup("popbegin.malloc: failed\n");
80 goto error;
81 }
82 hostname = strdup (servername);
83 if (!hostname) {
84 err=strdup("popbegin.strdup: failed\n"); /* ahem... */
85 goto error;
86 }
87 ptr_port = strchr (hostname, ':');
88 if (!ptr_port)
89 nport = 110;
90 else {
91 *ptr_port = 0;
92 nport = (int) strtoul (++ptr_port, NULL, 10);
93 if (!nport)
94 nport = 110;
95 }
96 s->sock=pop3_prepare(hostname,nport,s->connection,s->server);
97 free (hostname);
98 if(s->sock==BAD_SOCK){
99 err=strdup("popbegin.pop3_prepare: failed\n");
100 goto error;
101 }
102 resp=pop3_connect(s->sock,s->connection);
103 if(!resp){
104 err=strdup("popbegin.pop3_connect: failed\n");
105 goto error;
106 }
107 free(resp);
108 resp=pop3_user(s->sock,user);
109 if((!resp) || pop3_error(resp)){
110 err=resp?resp:strdup("popbegin.pop3_user: failed\n");
111 goto error;
112 }
113 free(resp);
114 resp=pop3_pass(s->sock,pass);
115 if((!resp) || pop3_error(resp)){
116 err=resp?resp:strdup("popbegin.pop3_pass: failed\n");
117 goto error;
118 }
119 free(resp);
120 resp=pop3_stat(s->sock);
121 if((!resp) || pop3_error(resp)){
122 err=resp?resp:strdup("popbegin.pop3_stat: failed\n");
123 goto error;
124 }
125 s->bytes=stat2bytes(resp);
126 s->num=stat2num(resp);
127 s->last=stat2num(resp); /* safe here: we did not delete anything */
128 free(resp);
129 resp=pop3_list(s->sock,0);
130 if((!resp) || pop3_error(resp)){
131 err=resp?resp:strdup("popbegin.pop3_list: failed\n");
132 goto error;
133 }
134 s->list=list2array(resp);
135 free(resp);
136 resp=pop3_uidl(s->sock,0);
137 if((!resp) || pop3_error(resp)){
138 err=resp?resp:strdup("popbegin.pop3_uidl: failed\n");
139 goto error;
140 }
141 s->uidl=uidl2array(resp);
142 s->del=0;
143 (*sp)=s;
144 free(resp);
145 return (NULL);
146
147 error:
148 if (s) {
149 if (s->sock != BAD_SOCK)
150 {
151 pop3_disconnect (s->sock, s->server);
152 free(s->server);
153 }
154 free (s->connection);
155 free(s);
156 }
157 return (err);
158 }
159
160 DLLIMPORT char* popgethead(popsession* session, int id){
161 /* returns the header of a message id between 1 and last or NULL if bad id or error */
162 char* resp;
163 char* msg;
164 if(!session){
165 return(NULL);
166 }
167 if((id > session->last) || (id < 1)){
168 return(NULL);
169 }
170 resp=pop3_top(session->sock,id,0); /* 0 means only header */
171 if((!resp) || pop3_error(resp)){
172 if(resp){
173 free(resp);
174 }
175 return(NULL);
176 }
177 msg=retr2msg(resp);
178 if(!msg){
179 msg=resp;
180 }else{
181 free(resp);
182 }
183 return(msg);
184 }
185
186 DLLIMPORT char* popgetmsg(popsession* session, int id){
187 /* returns a message id between 1 to last or NULL if bad id or error */
188 char* resp=NULL;
189 char* msg=NULL;
190
191 if(!session){
192 return(NULL);
193 }
194 if((id > session->last) || (id < 1)){
195 return(NULL);
196 }
197 resp=pop3_retr(session->sock,id);
198 if((!resp) || pop3_error(resp)){
199 free(resp);
200 return(NULL);
201 }
202 msg=retr2msg(resp);
203 if(!msg){
204 msg=resp;
205 }else{
206 free(resp);
207 }
208 if(session->del){
209 popdelmsg(session, id);
210 }
211 return(msg);
212 }
213
214 DLLIMPORT int popdelmsg(popsession* session, int id){
215 /* deletes a message 'id' on pop server */
216 /* returns -1 if no deletion (server error), 0 else */
217 /* sets session->sync to 0 if last id unsync-ed , 1 if OK */
218 char* resp;
219 int ret;
220 if(!session){
221 return -1;
222 }
223 if((id > session->last) || (id < 1)){
224 return -1;
225 }
226 /* actualy delete the email */
227 resp=pop3_dele(session->sock,id);
228 if((!resp) || pop3_error(resp)){
229 free(resp);
230 return -1;
231 }
232 free(resp);
233 resp=pop3_stat(session->sock);
234 if((!resp) || pop3_error(resp)){
235 session->sync=0;
236 free(resp);
237 return -1;
238 }
239 ret = stat2bytes(resp);
240 if (ret < 0)
241 session->sync=0;
242
243 else
244 session->bytes=ret;
245 ret = stat2num(resp);
246 if (ret < 0)
247 session->sync=0;
248 else
249 session->num=ret;
250 free(resp);
251 ret=poplast(session); /* check actual last id */
252 if (ret < 0){
253 session->sync=0;
254 free(resp);
255 return -1;
256 }
257 session->last=ret;
258
259 /* no more message of this id*/
260 session->list[id]=0;
261 free(session->uidl[id]);
262 session->uidl[id]=NULL;
263 session->sync=1;
264 return 0;
265 }
266
267 DLLIMPORT int popcancel(popsession* session){
268 /* cancel all previous deletions on pop server */
269 /* returns -1 if server error, 0 else */
270 char* resp;
271 int ret;
272
273 if(!session){
274 return(-1);
275 }
276 resp=pop3_rset(session->sock);
277 if((!resp) || pop3_error(resp)){
278 free(resp);
279 return(-1);
280 }
281 free(resp);
282 resp=pop3_stat(session->sock);
283 if((!resp) || pop3_error(resp)){
284 session->sync=0;
285 free(resp);
286 return(-1);
287 }
288 /* sync number of bytes */
289 ret = stat2bytes(resp);
290 if (ret < 0)
291 session->sync=0;
292 else
293 session->bytes=ret;
294 /* sync number of messages */
295 ret = stat2num(resp);
296 if (ret < 0)
297 session->sync=0;
298 else
299 session->num=ret;
300 /* sync last mail id */
301 /* safe to use stat2num here since we cancel */
302 ret = stat2num(resp);
303 if (ret < 0)
304 session->sync=0;
305 else
306 session->last=ret;
307 free(resp);
308 resp=pop3_list(session->sock,0);
309 if((!resp) || pop3_error(resp)){
310 session->sync=0;
311 free(resp);
312 return -1;
313 }
314 freelistarray(session->list);
315 session->list=list2array(resp);
316 free(resp);
317 resp=pop3_uidl(session->sock,0);
318 if((!resp) || pop3_error(resp)){
319 session->sync=0;
320 free(resp);
321 return -1;
322 }
323 freeuidlarray(session->uidl);
324 session->uidl=uidl2array(resp);
325 free(resp);
326 session->sync=1;
327 return 0;
328 }
329
330 DLLIMPORT void popend(popsession* session){
331 /* quit and destroys pop session */
332 int i;
333 char* resp;
334
335 if(!session)
336 return;
337 resp=pop3_quit(session->sock);
338 free(resp);
339 pop3_disconnect(session->sock, session->server);
340 free(session->server);
341 free(session->connection);
342 free(session->list);
343 for(i=0;i<=session->last;i++){
344 free(session->uidl[i]);
345 }
346 free(session->uidl);
347 free(session);
348 return;
349 }
350
351 DLLIMPORT int popnum(popsession* session){
352 /* returns the number of current (non-deleted) messages */
353 char* r=NULL;
354 int n;
355
356 if(!session)
357 return -1;
358 r=pop3_stat(session->sock);
359 if(pop3_error(r)) {
360 free(r);
361 return -1; /* error (timeout, etc..) */
362 }
363 n=stat2num(r);
364 free(r);
365 return(n);
366 }
367
368 DLLIMPORT int poplast(popsession* session){
369 /* return the id of the last downloadable (non-deleted) message */
370 /* thanks to Francesco Gennai <francesco.gennai@isti.cnr.it> */
371 int i=0;
372 char* lines=NULL;
373 char* p=NULL;
374
375 if(!session)
376 return -1;
377 lines=pop3_list(session->sock, 0); /* 0 means 'all' */
378 if(pop3_error(lines)) {
379 free(lines);
380 return -1; /* error (timeout, etc..) */
381 }
382 p=lines;
383 p=nextline(p); /* skip +OK */
384 while (p[0]!='.'){ /* dot means list terminated */
385 i = atoi(p); /* first number is the id */
386 p=nextline(p);
387 }
388 /* i is now the greatest id */
389 free(lines);
390 return(i);
391 }
392
393 DLLIMPORT int popchkmsg(popsession* session, int id) {
394 /* check if the message 'id' is accessible in the current session */
395 /* thanks to Francesco Gennai <francesco.gennai@isti.cnr.it> */
396 if (popmsguid(session, id)) return 1; /* anything but 0 */
397 return 0;
398 }
399
400 /* re-synchronize the session object from the server */
401 DLLIMPORT int popsync(popsession* session) {
402 char* resp;
403 int ret;
404
405 if(!session){
406 return(-1);
407 }
408 resp=pop3_stat(session->sock);
409 if((!resp) || pop3_error(resp)){
410 session->sync=0;
411 return(-1);
412 }
413 session->bytes=stat2bytes(resp);
414 session->num=stat2num(resp);
415 ret=poplast(session); /* check actual last id */
416 if (ret < 0){
417 session->sync=0;
418 free(resp);
419 return(-1);
420 }
421 session->last=ret;
422 free(resp);
423 resp=pop3_list(session->sock,0);
424 if((!resp) || pop3_error(resp)){
425 session->sync=0;
426 free(resp);
427 return(-1);
428 }
429 freelistarray(session->list);
430 session->list=list2array(resp);
431 free(resp);
432 resp=pop3_uidl(session->sock,0);
433 if((!resp) || pop3_error(resp)){
434 session->sync=0;
435 free(resp);
436 return(-1);
437 }
438 freeuidlarray(session->uidl);
439 session->uidl=uidl2array(resp);
440 free(resp);
441 session->sync=1;
442 return(0);
443 }
444

  ViewVC Help
Powered by ViewVC 1.1.26