/[libspopc]/queries.c
ViewVC logotype

Contents of /queries.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (show annotations)
Wed Apr 11 14:06:48 2012 UTC (7 years, 1 month ago) by ben
File MIME type: text/plain
File size: 9654 byte(s)
Removed old homepage reference in docs and headers

1 /* this is queries.c file, 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 #ifdef WIN32
24 #include <winsock.h>
25 #else
26 #include <sys/socket.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #ifndef WIN32
36 #include <unistd.h>
37 #endif
38
39 #include "libspopc.h"
40
41 #ifdef USE_SSL
42
43 DLLIMPORT int pop3_recv (pop3sock_t sock, char* buf, int len){
44 return sock->ssl?SSL_read(sock->ssl,buf,len):recv(sock->sock,buf,len,0);
45 }
46
47 DLLIMPORT int pop3_send (pop3sock_t sock, char* buf, int len){
48 return sock->ssl?SSL_write(sock->ssl,buf,len):send(sock->sock,buf,len,0);
49 }
50
51 #else
52
53 DLLIMPORT int pop3_recv (pop3sock_t sock, char* buf, int len){
54 return recv(sock,buf,len,0);
55 }
56
57 DLLIMPORT int pop3_send (pop3sock_t sock, char* buf, int len){
58 return send(sock,buf,len,0);
59 }
60
61 #endif
62
63 DLLIMPORT char* pop3_query(pop3sock_t sock, const char* query){
64 /* performs a simple pop query and returns server's <=512 bytes resp */
65 int r=0;
66 int bytes=0;
67 char* buf=NULL;
68
69 r=pop3_send(sock,(char *)query,strlen(query));
70 if(r==-1){ /* send timeout reached */
71 perror("pop3_query.pop3_send");
72 return(NULL);
73 }
74 buf=(char*)malloc(POPBUF); /* 512B + EOS */
75 if(!buf){
76 perror("pop3_query.malloc");
77 return(NULL);
78 }
79 do {
80 r=pop3_recv(sock, buf+bytes, POPBUF-bytes-1);
81 if (r>0)
82 bytes+=r;
83 else { /* closed (0) or timeout reached (-1) */
84 free(buf);
85 return NULL;
86 }
87 } while (bytes < 2 || (buf[bytes-2] != '\r' && buf[bytes-1] != '\n'));
88 buf[bytes]='\0';
89 return(buf);
90 }
91
92 DLLIMPORT char* pop3_user(pop3sock_t sock, const char* name){
93 /* performs "USER" pop query and returns server's <512 bytes response */
94 char query[POPBUF]; /* total "USER ****your_name****\n" is <= 512 */
95
96 snprintf(query,POPBUF,"USER %s\r\n",name);
97 return(pop3_query(sock,query));
98 }
99
100 DLLIMPORT char* pop3_pass(pop3sock_t sock, const char* pw){
101 /* performs "PASS" pop query and return server's <=512 bytes response */
102 char query[POPBUF]; /* total "PASS ****your_pass****\n" is <=512 */
103
104 snprintf(query,POPBUF,"PASS %s\r\n",pw);
105 return(pop3_query(sock,query));
106 }
107
108 DLLIMPORT char* pop3_quit(pop3sock_t sock){
109 /* performs "QUIT" pop query and returns server's <=512 bytes response */
110 char query[]="QUIT\r\n";
111
112 return(pop3_query(sock,query));
113 }
114
115 DLLIMPORT char* pop3_stat(pop3sock_t sock){
116 /* performs "STAT" pop query and returns server's <=512 bytes response */
117 char query[]="STAT\r\n";
118
119 return(pop3_query(sock,query));
120 }
121
122 char* recv_rest(pop3sock_t sock, char* buf, int cursize, int bufsize){
123 /* recv rest of data through sock, given a cs pre-filled buffer sized of bs.
124 * end of data is assumed when data has a "\r\n.\r\n" string
125 * recv() is TCPBUFLEN bytes stepped, Warning: after calling this function,
126 * buf must never be used again -not even for a free(buf)- since it may be
127 * reallocated. Use the return value instead:
128 * usage example: buf=recv_rest(sock,buf,cs,bs); free(buf);
129 */
130 char* ret = NULL;
131 char* cur = NULL; /* current position ready to receive */
132 int total; /* total received */
133 if(!buf){
134 return(NULL);
135 }
136 total = cursize;
137 cur = buf;
138 if(cursize == bufsize){
139 ret=(char*)realloc(buf,bufsize+1);
140 if(!ret){
141 perror("recv_rest.realloc");
142 free(buf);
143 return NULL;
144 }
145 cur = buf = ret;
146 }
147 cur[total]='\0';
148 while(!dotline(buf, total)){ /* recv until "\r\n.\r\n" */
149 if (total >= (bufsize - TCPBUFLEN)){
150 ret = (char*)realloc(buf, (bufsize *=2) +1);
151 }
152 if(!ret){
153 perror("recv_rest.realloc");
154 free(buf);
155 return NULL;
156 }
157 buf = ret;
158 cur = buf + total;
159 /* we use blocking sockets WITH TIMEOUT: no need for select() */
160 cursize=pop3_recv(sock, cur, TCPBUFLEN);
161 if (cursize <= 0){ /* timeout (-1) or closed (0) */
162 perror("recv_rest.pop3_recv");
163 free(buf);
164 return(NULL);
165 } /* else, we got some bytes */
166 total+=cursize;
167 cur[cursize] = '\0';
168 /* SUGGEST: we can strdup to a callback here */
169 }
170 return(buf);
171 }
172
173 DLLIMPORT char* pop3_list(pop3sock_t sock, int id){
174 /* performs a "LIST" pop query and returns server's (long) response */
175 int r;
176 char query[POPBUF]; /* total query "LIST ID\n" string is <=512 */
177 char* buf;
178
179 if(id>0){
180 snprintf(query,POPBUF,"LIST %d\r\n",id);
181 }else{
182 snprintf(query,POPBUF,"LIST\r\n");
183 }
184 r=pop3_send(sock,query,strlen(query));
185 if(r==-1){
186 perror("pop3_list.pop3_send");
187 return(NULL);
188 }
189 /* now prepare a first short 512 bytes recv() */
190 /* it might be now enough for recv() from "LIST X" */
191 buf=(char*)malloc(POPBUF); /* 512 chars + '\0' */
192 if(!buf){
193 perror("pop3_list.malloc");
194 return(NULL);
195 }
196 r=pop3_recv(sock,buf,POPBUF-1);
197 if(r <= 0){ /* close (0) or timeout (-1) */
198 perror("pop3_list.pop3_recv");
199 free(buf);
200 return(NULL);
201 } /* else, got some bytes */
202 buf[r]='\0';
203 if(id>0){/* +OK id size */
204 return(buf); /* 512 bytes are enough as say RFC 1939 */
205 }
206 /* else : +OK X messages (YYY octets)\n id size\n... */
207 if(pop3_error(buf)){
208 return(buf);
209 }
210 return(recv_rest(sock,buf,r,POPBUF-1));
211 }
212
213 DLLIMPORT char* pop3_retr(pop3sock_t sock, int id){
214 /* performs a "RETR" pop query and returns server's (long) response */
215 int r;
216 char query[POPBUF];
217 char *buf;
218
219 snprintf(query, POPBUF, "RETR %d\r\n", id);
220 r=pop3_send(sock, query, strlen(query));
221 if(r==-1){
222 perror("pop3_retr.pop3_send");
223 return(NULL);
224 }
225 buf=(char*)malloc(POPBUF);/* 512 chars + '\0' */
226 if(!buf) {
227 perror("pop3_retr.malloc");
228 return(NULL);
229 }
230 /* using blocking sockets WITH TIMEOUT: no need for select() */
231 r=pop3_recv(sock, buf, POPBUF-1);
232 if(r <= 0){ /* timeout (-1) or close (0) */
233 perror("pop3_retr.pop3_recv");
234 free(buf);
235 return(NULL);
236 } /* else, got some bytes */
237 if(pop3_error(buf)){
238 buf[r] = '\0';
239 return(buf); /* 512 are enough as say RFC 1939 */
240 }
241 return(recv_rest(sock, buf, r, POPBUF-1));
242 }
243
244 DLLIMPORT char* pop3_dele(pop3sock_t sock, int id){
245 /* performs a "DELE" pop query and returns server's <=512 bytes response */
246 char query[POPBUF]; /* total "DELE X\n" string <=512 */
247
248 if(id<=0){
249 return(NULL);
250 }
251 snprintf(query,POPBUF,"DELE %d\r\n",id);
252 return(pop3_query(sock,query));
253 }
254
255 DLLIMPORT char* pop3_noop(pop3sock_t sock){
256 /* performs a "NOOP" pop query and returns server's <=512 bytes response */
257 char query[]="NOOP\r\n";
258
259 return(pop3_query(sock,query));
260 }
261
262 DLLIMPORT char* pop3_rset(pop3sock_t sock){
263 /* performs a "RSET" pop query and returns server's <=512 bytes response */
264 char query[]="RSET\r\n";
265
266 return(pop3_query(sock,query));
267 }
268
269 DLLIMPORT char* pop3_top(pop3sock_t sock, int id, int lines){
270 /* performs a "TOP" pop query and returns server's (long) response */
271 int r;
272 char query[POPBUF]; /* total "TOP X Y\n" is <=512 */
273 char* buf;
274
275 snprintf(query,POPBUF,"TOP %d %d\r\n",id,lines);
276 r=pop3_send(sock,query,strlen(query));
277 if(r==-1){
278 perror("pop3_top.pop3_send");
279 return(NULL);
280 }
281 /* prepare first recv() of 512 bytes */
282 buf=(char*)malloc(POPBUF); /* 512 chars + '\0' */
283 if(!buf){
284 perror("pop3_top.malloc");
285 return(NULL);
286 }
287 r=pop3_recv(sock,buf,POPBUF-1);
288 if(r <= 0){ /* timeout (-1) or close (0) */
289 perror("pop3_top.pop3_recv");
290 free(buf);
291 return(NULL);
292 } /* else, got some bytes */
293 buf[r]='\0';
294 if(pop3_error(buf)){
295 return(buf); /* 512 bytes are enough as say RFC 1939 */
296 }
297 return(recv_rest(sock,buf,r,POPBUF-1));
298 }
299
300 DLLIMPORT char* pop3_uidl(pop3sock_t sock, int id){
301 /* performs a "UIDL" pop query and returns server's (long) response */
302 int r;
303 char query[POPBUF]; /* total "UIDL X\n" is <=512 */
304 char* buf;
305
306 if(id>0){
307 snprintf(query,POPBUF,"UIDL %d\r\n",id);
308 }else{
309 snprintf(query,POPBUF,"UIDL\r\n");
310 }
311 r=pop3_send(sock,query,strlen(query));
312 if(r==-1){
313 perror("pop3_uidl.pop3_send");
314 return(NULL);
315 }
316 /* prepare first 512 bytes for recv() */
317 /* i hope this is also enough for the 'one line' short response */
318 buf=(char*)malloc(POPBUF); /* 512 chars + '\0' */
319 if(!buf){
320 perror("pop3_uidl.malloc");
321 return(NULL);
322 }
323 memset(buf,0,POPBUF);
324 r=pop3_recv(sock,buf,POPBUF-1);
325 if (r <= 0){ /* timeout (-1) or close (0) */
326 perror("pop3_uidl.pop3_recv");
327 free(buf);
328 return(NULL);
329 } /* else, got some bytes */
330 buf[r]='\0';
331 if(id>0){/* +OK id sig */
332 /* return the short buf, error or not */
333 return(buf); /* 512 are enough as say RFC 1939 */
334 }
335 /* else : +OK\n id sig\nid sig\nid sig\n... */
336 if(pop3_error(buf)){
337 return(buf); /* hope error msg were <=512 bytes */
338 }
339 return(recv_rest(sock,buf,r,POPBUF-1));
340 }
341
342 DLLIMPORT char* pop3_apop(pop3sock_t sock, const char* name, const char* digest){
343 /* performs a "APOP" secure query and returns server's <=512 bytes response */
344 char query[POPBUF]; /* total "APOP name digest\r\n" is <=512 */
345
346 snprintf(query,POPBUF,"APOP %s %s\r\n",name,digest);
347 return(pop3_query(sock,query));
348 }
349

  ViewVC Help
Powered by ViewVC 1.1.26