/[libspopc]/objects.c
ViewVC logotype

Contents of /objects.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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 DLLIMPORT char* popbegin(const char* servername, const char* user, const char* pass, popsession** sp){
41 /* 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 if ( s->list ) freelistarray(s->list);
154 if ( s->uidl ) freeuidlarray(s->uidl);
155 free(s->connection);
156 free(s);
157 }
158 return (err);
159 }
160
161 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 DLLIMPORT char* popgethead(popsession* session, int id){
167 /* 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 DLLIMPORT char* popgetmsg(popsession* session, int id){
193 /* 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 DLLIMPORT int popdelmsg(popsession* session, int id){
221 /* 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 free(resp);
243 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 free(resp);
261 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 DLLIMPORT int popcancel(popsession* session){
274 /* 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 free(resp);
292 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 free(resp);
318 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 free(resp);
327 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 DLLIMPORT void popend(popsession* session){
337 /* 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 freelistarray(session->list);
348 freeuidlarray(session->uidl);
349 free(session);
350 return;
351 }
352
353 DLLIMPORT int popnum(popsession* session){
354 /* 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 DLLIMPORT int poplast(popsession* session){
371 /* 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 DLLIMPORT int popchkmsg(popsession* session, int id) {
396 /* 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 DLLIMPORT int popsync(popsession* session) {
404 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 free(resp);
421 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 free(resp);
429 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 free(resp);
438 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