queries.c

Go to the documentation of this file.
00001 /* this is queries.c file.
00002  * this is part of the libspopc library sources
00003  * copyright © 2002 Benoit Rouits <brouits@free.fr>
00004  * released under the terms of GNU LGPL
00005  * (GNU Lesser General Public Licence).
00006  * libspopc offers simple API for a pop3 client (MTA).
00007  * See RFC 1725 for pop3 specifications.
00008  * more information on http://brouits.free.fr/libspopc/
00009  */
00010 
00011 #include <sys/types.h>
00012 
00013 #ifdef _MSC_VER
00014 #include <winsock.h>
00015 #else
00016 #include <sys/socket.h>
00017 #endif
00018 
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include "libspopc.h"
00023 
00024 /* enable timeout sockets with 'select' */
00025 int timedrselect(fd_set *rfds, int max, int time){
00026 struct timeval timeout;
00027 timeout.tv_sec = time;
00028 timeout.tv_usec = 0;
00029 
00030    if(select(max, rfds, NULL, NULL, &timeout) <= 0){
00031       perror("timeout reached\n");
00032       return(1);
00033    }
00034    return(0);
00035 }
00036 /* prepare the socket ito be read */
00037 int timedrread(int sock, int time) {
00038 fd_set rfds;
00039 
00040    FD_ZERO(&rfds);
00041    FD_SET(sock, &rfds);
00042    timedrselect(&rfds, sock + 1, time);
00043    return FD_ISSET(sock, &rfds);
00044 }
00045 
00046 char* pop3_query(int sock, const char* query){
00047 /* performs a simple pop query and returns server's <512 bytes response */
00048 int r;
00049 char* buf;
00050 
00051 #ifdef EBUG
00052         fprintf(stderr,"<pop3_query>\n");
00053         fprintf(stderr,"send %s",query);
00054 #endif
00055         r=send(sock,query,strlen(query),0);
00056         if(r==-1){
00057                 perror("pop3_query.send");
00058                 return(NULL);
00059         }
00060         buf=(char*)malloc(512 +1); /* 512 chars + '\0' */
00061         if(!buf){
00062                 perror("pop3_query.malloc");
00063                 return(NULL);
00064         }
00065         /* memset(buf,0,512); SUGGEST: should not be an obligation */
00066         r=recv(sock,buf,512,0);
00067         buf[r]='\0';
00068 #ifdef EBUG
00069         fprintf(stderr,"recv %s",buf);
00070         fprintf(stderr,"</pop3_query>\n");
00071 #endif
00072         return(buf);
00073 }
00074 
00075 char* pop3_user(int sock, const char* name){
00076 /* performs "USER" pop query and returns server's <512 bytes response */
00077 char query[512]; /* total "USER ****your_name****\n" is < 512  */
00078 
00079         sprintf(query,"USER %s\r\n",name);
00080         return(pop3_query(sock,query));
00081 }
00082 
00083 char* pop3_pass(int sock, const char* pw){
00084 /* performs "PASS" pop query and return server's <512 bytes response */
00085 char query[512]; /* total "PASS ****your_pass****\n" is <512 */
00086 
00087         sprintf(query,"PASS %s\r\n",pw);
00088         return(pop3_query(sock,query));
00089 }
00090 
00091 char* pop3_quit(int sock){
00092 /* performs "QUIT" pop query and returns server's <512 bytes response */
00093 char query[]="QUIT\r\n";
00094 
00095         return(pop3_query(sock,query));
00096 }
00097 
00098 char* pop3_stat(int sock){
00099 /* performs "STAT" pop query and returns server's <512 bytes response */
00100 char query[]="STAT\r\n";
00101 
00102         return(pop3_query(sock,query));
00103 }
00104 
00105 char* recv_rest(int sock, char* buf, int cs, int bs){
00106 /* recv rest of data through sock, given a cs  pre-filled buffer sized of bs.
00107 * end of data is assumed when data has a "\n.\n" or "\n.\r" string
00108 * recv() is TCPBUFLEN  bytes stepped, SUGGEST any good value... */
00109 char* ret;
00110 char* cur; /* current position ready to receive */
00111 int tr;    /* total received */
00112 #ifdef EBUG
00113    fprintf(stderr,"<recv_rest>\n");
00114 #endif
00115    if(!buf){
00116 #ifdef EBUG
00117       fprintf(stderr,"was given NULL buf !\n");
00118 #endif
00119       return(NULL);
00120 }
00121    tr = cs;
00122    cur = buf;
00123    while(!dotline(cur)){
00124       if (tr >= (bs - TCPBUFLEN)){
00125 #ifdef EBUG
00126          fprintf(stderr,"realloc bs*2 + 1 == %d\n", bs*2 +1);
00127 #endif
00128          ret = (char*)realloc(buf, (bs *=2) +1);
00129       }
00130       if(!ret){
00131          perror("recv_rest.realloc");
00132          return(buf);
00133       }
00134       buf = ret;
00135       cur = buf + tr;
00136       if(timedrread(sock, SOCKET_TIMEOUT)){
00137          cs=recv(sock, cur, TCPBUFLEN, 0);
00138          if (cs < 0){ /* socket error */
00139             perror("Socket Error");
00140             free(cur);
00141             return(NULL);
00142          }
00143       }else{
00144          printf("timeout reached\n");
00145          return(buf);
00146       }
00147       if (cs > 0){
00148          tr+=cs;
00149          cur[cs] = '\0';
00150       }else{
00151          cs = 0;
00152       }
00153    }
00154    cur[cs] = '\0';
00155 #ifdef EBUG
00156    fprintf(stderr, "total recv %d bytes\n", tr);
00157    fprintf(stderr, "</recv_rest>\n");
00158 #endif
00159    return(buf);
00160 }
00161       
00162 char* pop3_list(int sock, int id){
00163 /* performs a "LIST" pop query and returns server's (long) response */
00164 int r;
00165 char query[512]; /* total query "LIST ID\n" string is < 512 */
00166 char* buf;
00167 
00168 #ifdef EBUG
00169         fprintf(stderr,"<pop3_list>\n");
00170 #endif
00171         if(id>0){
00172                 sprintf(query,"LIST %d\r\n",id);
00173         }else{
00174                 sprintf(query,"LIST\r\n");
00175         }
00176 #ifdef EBUG
00177         fprintf(stderr,"send %s",query);
00178 #endif
00179         r=send(sock,query,strlen(query),0);
00180         if(r==-1){
00181                 perror("pop3_list.send");
00182                 return(NULL);
00183         }
00184         /* now prepare a first short 512 bytes recv() */
00185         /* it might be now enough for recv() from "LIST X" */
00186         buf=(char*)malloc(512 +1); /* 512 chars + '\0' */
00187         if(!buf){
00188                 perror("pop3_list.malloc");
00189                 return(NULL);
00190         }
00191         r=recv(sock,buf,512,0);
00192    if(r < 0){ /* socket error */
00193       perror("Socket Error");
00194       free(buf);
00195       return(NULL);
00196    }
00197    buf[r]='\0';
00198         if(id>0){/* +OK id size */
00199                 return(buf); /* hope 512 bytes were enough */
00200         }
00201         /* else : +OK X messages (YYY octets)\n id size\n... */
00202         if(pop3_error(buf)){
00203 #ifdef EBUG
00204                 fprintf(stderr,"%s",buf);
00205 #endif
00206                 return(buf);
00207         }
00208 #ifdef EBUG
00209         fprintf(stderr,"</>\n");
00210 #endif
00211         return(recv_rest(sock,buf,r,512));
00212 }
00213 
00214 char* pop3_retr(int sock, int id){
00215 int r;
00216 char query[512];
00217 char *buf;
00218 
00219 #ifdef EBUG
00220    fprintf(stderr, "<pop3_retr>\n");
00221 #endif
00222    sprintf(query, "RETR %d\r\n", id);
00223    r=send(sock, query, strlen(query), 0);
00224    if(r == -1){
00225       perror("pop3_retr.send");
00226       return(NULL);
00227    }
00228    buf=(char*)malloc(512 +1);/* 512 chars + '\0' */
00229    if(!buf) {
00230       perror("pop3_retr.malloc");
00231       return(NULL);
00232    }
00233    if(timedrread(sock, SOCKET_TIMEOUT)){
00234       r=recv(sock, buf, 512, 0); 
00235       if(r < 0){ /* socket error */
00236          perror("Socket Error");
00237          free(buf);
00238          return(NULL);
00239       }
00240    }else{
00241       perror("timeout reached\n");
00242       return(NULL);
00243    }
00244    if(pop3_error(buf)){
00245       buf[r+1] = '\0';
00246       return(buf); /* hope 512 was enough */
00247    }
00248 #ifdef EBUG
00249    fprintf(stderr,"</>\n");
00250 #endif
00251    if (r > 0) {
00252       return(recv_rest(sock, buf, r, 512));
00253    }else{
00254       perror("nothing returned\n");
00255       return(NULL);
00256    }
00257 }
00258 
00259 char* pop3_dele(int sock, int id){
00260 /* performs a "DELE" pop query and returns server's <512 bytes response */
00261 char query[512]; /* total "DELE X\n" string < 512 */
00262 
00263         if(id<=0){
00264 #ifdef EBUG
00265                 fprintf(stderr,"pop3_dele : won't delete %d\n",id);
00266 #endif
00267                 return(NULL);
00268         }
00269         sprintf(query,"DELE %d\r\n",id);
00270         return(pop3_query(sock,query));
00271 }
00272 
00273 char* pop3_noop(int sock){
00274 /* performs a "NOOP" pop query and returns server's <512 bytes response */
00275 char query[]="NOOP\r\n";
00276         
00277         return(pop3_query(sock,query));
00278 }
00279 
00280 char* pop3_rset(int sock){
00281 /* performs a "RSET" pop query and returns server's <512 bytes response */
00282 char query[]="RSET\r\n";
00283 
00284         return(pop3_query(sock,query));
00285 }
00286 
00287 char* pop3_top(int sock, int id, int lines){
00288 /* performs a "TOP" pop query and returns server's (long) response */
00289 int r;
00290 char query[512]; /* total "TOP X Y\n" is < 512 */
00291 char* buf;
00292 
00293 #ifdef EBUG
00294         fprintf(stderr,"<pop3_top>\n");
00295 #endif
00296         sprintf(query,"TOP %d %d\r\n",id,lines);
00297 #ifdef EBUG
00298         fprintf(stderr,"send %s",query);
00299 #endif
00300         r=send(sock,query,strlen(query),0);
00301         if(r==-1){
00302                 perror("pop3_top.send");
00303                 return(NULL);
00304         }
00305         /* prepare first recv() of 512 bytes */
00306         buf=(char*)malloc(512 +1); /* 512 chars + '\0' */
00307         if(!buf){
00308                 perror("pop3_top.malloc");
00309                 return(NULL);
00310         }
00311 /*      memset(buf,0,512); SUGGEST: no obligation */
00312         r=recv(sock,buf,512,0);
00313    if(r < 0){ /* socket error */
00314       perror("Socket Error");
00315       free(buf);
00316       return(NULL);
00317    }
00318    buf[r]='\0';
00319    
00320         if(pop3_error(buf)){
00321 #ifdef EBUG
00322                 fprintf(stderr,"%s",buf);
00323 #endif
00324                 return(buf); /* hope 512 bytes were enough */
00325         }
00326 #ifdef EBUG
00327         fprintf(stderr,"</>\n");
00328 #endif
00329         return(recv_rest(sock,buf,r,512));
00330 }
00331 
00332 char* pop3_uidl(int sock, int id){
00333 /* performs a "UIDL" pop query and returns server's (long) response */
00334 int r;
00335 char query[512]; /* total "UIDL X\n" is < 512 */
00336 char* buf;
00337 
00338 #ifdef EBUG
00339         fprintf(stderr,"<pop3_uidl>\n");
00340 #endif
00341         if(id>0){
00342                 sprintf(query,"UIDL %d\r\n",id);
00343         }else{
00344                 sprintf(query,"UIDL\r\n");
00345         }
00346 #ifdef EBUG
00347         fprintf(stderr,"send %s",query);
00348 #endif
00349         r=send(sock,query,strlen(query),0);
00350         if(r==-1){
00351                 perror("pop3_uidl.send");
00352                 return(NULL);
00353         }
00354         /* prepare first 512 bytes for recv() */
00355         /* i hope this is also enough for the 'one line' short response */
00356         buf=(char*)malloc(512 +1); /* 512 chars + '\0' */
00357         if(!buf){
00358                 perror("pop3_uidl.malloc");
00359                 return(NULL);
00360         }
00361         memset(buf,0,512);
00362         r=recv(sock,buf,512,0);
00363    if (r < 0){ /* socket errorr */
00364       perror("Socket Error");
00365       free(buf);
00366       return(NULL);
00367    }
00368    buf[r]='\0';
00369    
00370         if(id>0){/* +OK id sig */
00371 #ifdef EBUG
00372                 if(pop3_error(buf)){
00373                         fprintf(stderr,"%s",buf);
00374                 }
00375 #endif
00376                 /* anyway, we return the short buf, error or not */
00377                 return(buf); /* hope 512 were enough */
00378         }
00379         /* else : +OK\n id sig\nid sig\nid sig\n... */
00380         if(pop3_error(buf)){
00381 #ifdef EBUG
00382                 fprintf(stderr,"%s",buf);
00383 #endif
00384                 return(buf); /* hope error msg were < 512 bytes */
00385         }
00386 #ifdef EBUG
00387         fprintf(stderr,"buf=%s</>\n",buf);
00388 #endif
00389         return(recv_rest(sock,buf,r,512));
00390 }
00391 
00392 char* pop3_apop(int sock, const char* name, const char* digest){
00393 /* performs a "APOP" secure query and returns server's <512 bytes response */
00394 char query[512]; /* total "APOP name digest\n" is < 512 */
00395 
00396         sprintf(query,"APOP %s %s\r\n",name,digest);
00397         return(pop3_query(sock,query));
00398 }
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3