/[libspopc]/objects.c
ViewVC logotype

Contents of /objects.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Sun Dec 5 16:58:12 2010 UTC (10 years, 10 months ago) by ben
File MIME type: text/plain
File size: 10226 byte(s)
added possibility to change socket timeout on the fly
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 int popsettimeout(popsession* session, int timeout){
161 /* sets the timeout in seconds for a session, returns 0 on success, < 0 on error */
162 return pop3_timeout(session->sock, timeout);
163 }
164
165 DLLIMPORT char* popgethead(popsession* session, int id){
166 /* returns the header of a message id between 1 and last or NULL if bad id or error */
167 char* resp;
168 char* msg;
169 if(!session){
170 return(NULL);
171 }
172 if((id > session->last) || (id < 1)){
173 return(NULL);
174 }
175 resp=pop3_top(session->sock,id,0); /* 0 means only header */
176 if((!resp) || pop3_error(resp)){
177 if(resp){
178 free(resp);
179 }
180 return(NULL);
181 }
182 msg=retr2msg(resp);
183 if(!msg){
184 msg=resp;
185 }else{
186 free(resp);
187 }
188 return(msg);
189 }
190
191 DLLIMPORT char* popgetmsg(popsession* session, int id){
192 /* returns a message id between 1 to last or NULL if bad id or error */
193 char* resp=NULL;
194 char* msg=NULL;
195
196 if(!session){
197 return(NULL);
198 }
199 if((id > session->last) || (id < 1)){
200 return(NULL);
201 }
202 resp=pop3_retr(session->sock,id);
203 if((!resp) || pop3_error(resp)){
204 free(resp);
205 return(NULL);
206 }
207 msg=retr2msg(resp);
208 if(!msg){
209 msg=resp;
210 }else{
211 free(resp);
212 }
213 if(session->del){
214 popdelmsg(session, id);
215 }
216 return(msg);
217 }
218
219 DLLIMPORT int popdelmsg(popsession* session, int id){
220 /* deletes a message 'id' on pop server */
221 /* returns -1 if no deletion (server error), 0 else */
222 /* sets session->sync to 0 if last id unsync-ed , 1 if OK */
223 char* resp;
224 int ret;
225 if(!session){
226 return -1;
227 }
228 if((id > session->last) || (id < 1)){
229 return -1;
230 }
231 /* actualy delete the email */
232 resp=pop3_dele(session->sock,id);
233 if((!resp) || pop3_error(resp)){
234 free(resp);
235 return -1;
236 }
237 free(resp);
238 resp=pop3_stat(session->sock);
239 if((!resp) || pop3_error(resp)){
240 session->sync=0;
241 free(resp);
242 return -1;
243 }
244 ret = stat2bytes(resp);
245 if (ret < 0)
246 session->sync=0;
247
248 else
249 session->bytes=ret;
250 ret = stat2num(resp);
251 if (ret < 0)
252 session->sync=0;
253 else
254 session->num=ret;
255 free(resp);
256 ret=poplast(session); /* check actual last id */
257 if (ret < 0){
258 session->sync=0;
259 free(resp);
260 return -1;
261 }
262 session->last=ret;
263
264 /* no more message of this id*/
265 session->list[id]=0;
266 free(session->uidl[id]);
267 session->uidl[id]=NULL;
268 session->sync=1;
269 return 0;
270 }
271
272 DLLIMPORT int popcancel(popsession* session){
273 /* cancel all previous deletions on pop server */
274 /* returns -1 if server error, 0 else */
275 char* resp;
276 int ret;
277
278 if(!session){
279 return(-1);
280 }
281 resp=pop3_rset(session->sock);
282 if((!resp) || pop3_error(resp)){
283 free(resp);
284 return(-1);
285 }
286 free(resp);
287 resp=pop3_stat(session->sock);
288 if((!resp) || pop3_error(resp)){
289 session->sync=0;
290 free(resp);
291 return(-1);
292 }
293 /* sync number of bytes */
294 ret = stat2bytes(resp);
295 if (ret < 0)
296 session->sync=0;
297 else
298 session->bytes=ret;
299 /* sync number of messages */
300 ret = stat2num(resp);
301 if (ret < 0)
302 session->sync=0;
303 else
304 session->num=ret;
305 /* sync last mail id */
306 /* safe to use stat2num here since we cancel */
307 ret = stat2num(resp);
308 if (ret < 0)
309 session->sync=0;
310 else
311 session->last=ret;
312 free(resp);
313 resp=pop3_list(session->sock,0);
314 if((!resp) || pop3_error(resp)){
315 session->sync=0;
316 free(resp);
317 return -1;
318 }
319 freelistarray(session->list);
320 session->list=list2array(resp);
321 free(resp);
322 resp=pop3_uidl(session->sock,0);
323 if((!resp) || pop3_error(resp)){
324 session->sync=0;
325 free(resp);
326 return -1;
327 }
328 freeuidlarray(session->uidl);
329 session->uidl=uidl2array(resp);
330 free(resp);
331 session->sync=1;
332 return 0;
333 }
334
335 DLLIMPORT void popend(popsession* session){
336 /* quit and destroys pop session */
337 int i;
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 free(session->list);
348 for(i=0;i<=session->last;i++){
349 free(session->uidl[i]);
350 }
351 free(session->uidl);
352 free(session);
353 return;
354 }
355
356 DLLIMPORT int popnum(popsession* session){
357 /* returns the number of current (non-deleted) messages */
358 char* r=NULL;
359 int n;
360
361 if(!session)
362 return -1;
363 r=pop3_stat(session->sock);
364 if(pop3_error(r)) {
365 free(r);
366 return -1; /* error (timeout, etc..) */
367 }
368 n=stat2num(r);
369 free(r);
370 return(n);
371 }
372
373 DLLIMPORT int poplast(popsession* session){
374 /* return the id of the last downloadable (non-deleted) message */
375 /* thanks to Francesco Gennai <francesco.gennai@isti.cnr.it> */
376 int i=0;
377 char* lines=NULL;
378 char* p=NULL;
379
380 if(!session)
381 return -1;
382 lines=pop3_list(session->sock, 0); /* 0 means 'all' */
383 if(pop3_error(lines)) {
384 free(lines);
385 return -1; /* error (timeout, etc..) */
386 }
387 p=lines;
388 p=nextline(p); /* skip +OK */
389 while (p[0]!='.'){ /* dot means list terminated */
390 i = atoi(p); /* first number is the id */
391 p=nextline(p);
392 }
393 /* i is now the greatest id */
394 free(lines);
395 return(i);
396 }
397
398 DLLIMPORT int popchkmsg(popsession* session, int id) {
399 /* check if the message 'id' is accessible in the current session */
400 /* thanks to Francesco Gennai <francesco.gennai@isti.cnr.it> */
401 if (popmsguid(session, id)) return 1; /* anything but 0 */
402 return 0;
403 }
404
405 /* re-synchronize the session object from the server */
406 DLLIMPORT int popsync(popsession* session) {
407 char* resp;
408 int ret;
409
410 if(!session){
411 return(-1);
412 }
413 resp=pop3_stat(session->sock);
414 if((!resp) || pop3_error(resp)){
415 session->sync=0;
416 return(-1);
417 }
418 session->bytes=stat2bytes(resp);
419 session->num=stat2num(resp);
420 ret=poplast(session); /* check actual last id */
421 if (ret < 0){
422 session->sync=0;
423 free(resp);
424 return(-1);
425 }
426 session->last=ret;
427 free(resp);
428 resp=pop3_list(session->sock,0);
429 if((!resp) || pop3_error(resp)){
430 session->sync=0;
431 free(resp);
432 return(-1);
433 }
434 freelistarray(session->list);
435 session->list=list2array(resp);
436 free(resp);
437 resp=pop3_uidl(session->sock,0);
438 if((!resp) || pop3_error(resp)){
439 session->sync=0;
440 free(resp);
441 return(-1);
442 }
443 freeuidlarray(session->uidl);
444 session->uidl=uidl2array(resp);
445 free(resp);
446 session->sync=1;
447 return(0);
448 }
449

  ViewVC Help
Powered by ViewVC 1.1.26