/[libspopc]/objects.c
ViewVC logotype

Annotation of /objects.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (hide annotations)
Fri Apr 13 20:42:58 2012 UTC (8 years, 9 months ago) by ben
File MIME type: text/plain
File size: 10195 byte(s)
Fix popbegin/popend. Don't rely on session->last.

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

  ViewVC Help
Powered by ViewVC 1.1.26