/[libspopc]/queries.c
ViewVC logotype

Contents of /queries.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show annotations)
Sun Apr 8 22:56:53 2012 UTC (8 years, 1 month ago) by ben
File MIME type: text/plain
File size: 9715 byte(s)
speedup dotline()

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

  ViewVC Help
Powered by ViewVC 1.1.26