00001 
00009 #ifdef CPLUSPLUS
00010     #undef CPLUSPLUS
00011 #endif
00012 
00013 
00014 #include "https_tool.h"
00015 
00016 
00017 #ifdef ENABLE_SSL
00018 
00036 int  send_https_header(int sofd, SSL* ssl, tList* pp, int mode)
00037 {
00038     int    hs=0, sz=0;
00039     Buffer buf;
00040 
00041     if (pp==NULL) return JBXL_ARGS_ERROR;
00042 
00043     buf = restore_protocol_header(pp, (char*)": ", mode, &hs);
00044     if (buf.vldsz>0) {
00045         sz  = ssl_tcp_send_Buffer(sofd, ssl, &buf);
00046         if (mode==ON) sz = sz - hs;
00047     }
00048 
00049     free_Buffer(&buf);
00050     return sz;
00051 }
00052 
00053 
00054 
00068 int  send_https_Buffer(int sofd, SSL* ssl, tList* pl, Buffer* buf)
00069 {
00070     int sz;
00071     Buffer snd;
00072 
00073  
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095     snd = rebuild_http_Buffer(pl, buf);
00096     sz  = ssl_tcp_send_Buffer(sofd, ssl, &snd);
00097     free_Buffer(&snd);
00098 
00099     return sz;
00100 }
00101 
00102 
00103 
00118 int  send_https_file(int sofd, SSL* ssl, tList* pl, const char* fname)
00119 {
00120     int   sz = 0;
00121     FILE* fp = NULL;
00122     char num[20];
00123     tList* pp;
00124     unsigned char* html;
00125     Buffer  buf;
00126 
00127     size_t rs;
00128     UNUSED(rs);
00129 
00130     if (pl==NULL) return JBXL_ARGS_ERROR;
00131     if (fname!=NULL) sz = file_size((char*)fname);
00132     if (sz<=0) sz = 0;
00133     snprintf(num, 18, "%d", sz);
00134 
00135     
00136     pp = pl;
00137     while(pp!=NULL) {
00138         if (!strcasecmp((const char*)(pp->ldat.key.buf), "Content-Length")) {
00139             copy_s2Buffer(num, &(pp->ldat.val));
00140             break;
00141         }
00142         pp = pp->next;
00143     }
00144 
00145     buf = restore_protocol_header(pl, (char*)": ", OFF, NULL);
00146 
00147     if (fname!=NULL && sz!=0) fp = fopen(fname, "rb");
00148     if (fp!=NULL) {
00149         html = (unsigned char*)malloc(sz+1);
00150         if (html==NULL) {
00151             fclose(fp);
00152             free_Buffer(&buf);
00153             return JBXL_MALLOC_ERROR;
00154         }
00155 
00156         memset(html, 0, sz+1);
00157         rs = fread(html, sz, 1, fp); 
00158         fclose(fp);
00159 
00160         cat_b2Buffer(html, &buf, sz);
00161         free(html);
00162     }
00163 
00164     sz = ssl_tcp_send_Buffer(sofd, ssl, &buf);
00165     free_Buffer(&buf);
00166 
00167     return sz;
00168 }
00169 
00170 
00171 
00196 int  recv_https_header(int sofd, SSL* ssl, tList** pl, int* len, int tm, FILE* fp, int* state)
00197 {
00198     int  cc, sz, com;
00199     Buffer mbuf;
00200     tList* lp;
00201     int  connect = TRUE;
00202 
00203     if (sofd<=0)   return JBXL_ARGS_ERROR;
00204     if (len==NULL) return JBXL_ARGS_ERROR;
00205     *len = HTTP_HEADER_UNKNOWN_LEN;
00206 
00207     mbuf = make_Buffer(RECVBUFSZ);
00208 
00209     sz  = 0;
00210     lp  = NULL;
00211     *pl = NULL;
00212 
00213     cc  = ssl_tcp_recv_Buffer_wait(sofd, ssl, &mbuf, tm);
00214     com = get_http_method((char*)mbuf.buf);
00215 
00216     if (com>HTTP_UNKNOWN_METHOD) {
00217         Loop {
00218             if (cc>0) {
00219                 if (fp!=NULL) fwrite(mbuf.buf, cc, 1, fp);
00220                 lp = get_protocol_header_list_seq(lp, mbuf, ':', TRUE, TRUE);
00221                 sz += cc;
00222                 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231             }
00232             else {
00233                 connect = FALSE;
00234                 break;
00235             }
00236 
00237             *pl = find_tList_top(lp);
00238             if (strncasecmp_tList(*pl, (char*)HDLIST_END_KEY, 0, 1)!=NULL) break;
00239             
00240             cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &mbuf, tm);
00241         }
00242     }
00243     else {
00244         if (mbuf.vldsz>0) {
00245             Buffer key = make_Buffer_str(HDLIST_CONTENTS_KEY);
00246             *pl = add_tList_node_Buffer(NULL, key, mbuf);
00247             free_Buffer(&key);
00248         }
00249         *len = HTTP_HEADER_NOT_HTTP;
00250         connect = FALSE;
00251     }
00252 
00253     free_Buffer(&mbuf);
00254     if (*pl!=NULL) (*pl)->ldat.id = com;
00255     if (state!=NULL) *state = connect;
00256     
00257     if (sz==0 && cc==0) return 0;      
00258     if (sz==0 && cc<0)  return JBXL_SSL_RECV_ERROR;
00259     if (*pl==NULL)      return JBXL_SSL_RECV_ERROR;
00260     if (*len==HTTP_HEADER_NOT_HTTP) return cc;
00261 
00262     
00263     
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272     if (com==HTTP_GET_METHOD) *len = 0;
00273 
00274     if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00275         if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00276             *len = HTTP_HEADER_CHUNKED;
00277         }
00278     }
00279 
00280     if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00281         Buffer hbuf = search_protocol_header(*pl, (char*)"Content-Length", 1);
00282         if (hbuf.buf!=NULL) {
00283             *len = atoi((const char*)hbuf.buf);
00284             free_Buffer(&hbuf);
00285         }
00286     }
00287 
00288     if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00289         if (get_http_version_num(*pl)<=1.0 && get_http_status_num(*pl)>=200) {
00290             if (is_http_header_field(*pl, (char*)"Connection", (char*)"close", 1)) {
00291                 *len = HTTP_HEADER_CLOSED_SESSION;
00292             }
00293         }
00294     }
00295 
00296     return sz;
00297 }
00298 
00299 
00300 
00319 int  recv_https_content(int sofd, SSL* ssl, Buffer* buf, int len, int tm, FILE* fp, int* state)
00320 {
00321     int cc, sz;
00322     Buffer rcv;
00323 
00324     if (state!=NULL) *state = TRUE;
00325     sz = buf->vldsz;
00326     if (sz>0 && fp!=NULL) fwrite(buf->buf, sz, 1, fp);
00327 
00328     
00329     rcv = make_Buffer(RECVBUFSZ);
00330     while(sz<len) {
00331         
00332         cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &rcv, tm);
00333         if (cc>0) {
00334             if (fp!=NULL) fwrite(rcv.buf, cc, 1, fp);
00335             cat_Buffer(&rcv, buf);
00336             sz += cc;
00337         }
00338         else {
00339             if (state!=NULL) *state = FALSE;
00340             sz = cc;
00341             break;
00342         }
00343         
00344     }
00345 
00346     free_Buffer(&rcv);
00347     return sz;
00348 }
00349 
00350 
00351 
00369 int  recv_https_chunked(int sofd, SSL* ssl, Buffer* buf, int tm, FILE* fp, int* state)
00370 {
00371     int cc, sz, i;
00372     int chnksz, hdsz, tlsz;
00373     if (state!=NULL) *state = TRUE;
00374 
00375     Buffer tmp = make_Buffer(RECVBUFSZ);
00376 
00377     sz = buf->vldsz;
00378     if (sz<=0) {    
00379         cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &tmp, tm);
00380         if (cc<=0) {
00381             if (state!=NULL) *state = FALSE;
00382             free_Buffer(&tmp);
00383             return cc;
00384         }
00385     }
00386     else {          
00387         cat_Buffer(buf, &tmp);
00388         clear_Buffer(buf);
00389     }
00390 
00391     
00392     chnksz = sz = get_chunked_size((char*)tmp.buf, &hdsz, &tlsz);
00393 
00394     while (chnksz>0) {
00395         
00396         if (chnksz+hdsz+tlsz > tmp.vldsz) {
00397             cc = recv_https_chunked_remain(sofd, ssl, &tmp, chnksz+hdsz+tlsz, tm);
00398             if (cc<=0) {
00399                 sz = cc;
00400                 break;
00401             }
00402         }
00403     
00404         Buffer cat = tmp;
00405         cat.buf = tmp.buf + hdsz;
00406         cat.vldsz = chnksz;
00407         cat_Buffer(&cat, buf);
00408         
00409 
00410         
00411         for (i=0; i<tmp.vldsz-chnksz-hdsz-tlsz; i++) {
00412             tmp.buf[i] = tmp.buf[chnksz + hdsz + tlsz + i];
00413         }
00414         tmp.vldsz = tmp.vldsz - chnksz - hdsz - tlsz;
00415         
00416 
00417         if (tmp.vldsz==0) {
00418             cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &tmp, tm);
00419             if (cc<=0) {
00420                 sz = cc;
00421                 break;
00422             }
00423         }
00424         chnksz = get_chunked_size((char*)tmp.buf, &hdsz, &tlsz);
00425         sz += chnksz;
00426     }
00427 
00428     if (fp!=NULL) fwrite(buf->buf, buf->vldsz, 1, fp);
00429 
00430     free_Buffer(&tmp);
00431     return sz;
00432 }
00433 
00434 
00435 
00450 int  recv_https_chunked_remain(int sofd, SSL* ssl, Buffer* buf, int chnksz, int tm)
00451 {
00452     int cc = 0;
00453     int sz = buf->vldsz;
00454     if (chnksz<=sz) return 0;
00455 
00456     Buffer rcv = make_Buffer(RECVBUFSZ);
00457 
00458     while (chnksz>sz) {
00459         
00460         cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &rcv, tm);
00461         if (cc<=0) {
00462             sz = cc;
00463             break;
00464         }
00465         cat_Buffer(&rcv, buf);
00466         sz += cc;
00467     }
00468 
00469     free_Buffer(&rcv);
00470     return sz;
00471 }
00472 
00473 
00474 
00492 int  recv_https_closed(int sofd, SSL* ssl, Buffer* buf, int tm, FILE* fp)
00493 {
00494     int cc, sz, tout;
00495     Buffer rcv;
00496 
00497     sz = buf->vldsz;
00498 
00499     rcv = make_Buffer(RECVBUFSZ);
00500     while ((tout=recv_wait(sofd, tm))) {
00501         cc = ssl_tcp_recv_Buffer_wait(sofd, ssl, &rcv, tm);
00502         if (cc>0) {
00503             if (fp!=NULL) fwrite(rcv.buf, cc, 1, fp);
00504             cat_Buffer(&rcv, buf);
00505             sz += cc;
00506         }
00507         else {
00508             break;
00509         }
00510         
00511     }
00512     free_Buffer(&rcv);
00513 
00514     if (!tout) return JBXL_NET_RECV_TIMEOUT;
00515 
00516     return sz;
00517 }
00518 
00519 
00520 
00541 int  recv_https_Buffer(int sofd, SSL* ssl, tList** pl, Buffer* buf, int tsecond, int* hdonly, int* state, int nochunk)
00542 {
00543     int    cc=0, hs, len;
00544     int    connect;
00545     Buffer cnt;
00546     tList* lp;
00547     
00548     if (buf==NULL || buf->buf==NULL) return JBXL_ARGS_ERROR;
00549     if (hdonly!=NULL) *hdonly = FALSE;
00550 
00551     clear_Buffer(buf);
00552 
00553     
00554     hs = recv_https_header(sofd, ssl, &lp, &len, tsecond, NULL, &connect);
00555     if (state!=NULL) *state = connect;
00556     if (hs<=0) return hs;                                           
00557     if (len==0 || len==HTTP_HEADER_UNKNOWN_LEN) {                   
00558         if (hdonly!=NULL) *hdonly = TRUE;
00559         if (pl!=NULL) *pl = lp;
00560         else del_tList(&lp);
00561         return hs;
00562     }
00563 
00564     
00565     cnt = search_protocol_header(lp, (char*)HDLIST_CONTENTS_KEY, 1);
00566     if (cnt.buf!=NULL) {
00567         cc = cnt.vldsz;
00568         hs = hs - cc;
00569         copy_Buffer(&cnt, buf);
00570         free_Buffer(&cnt);
00571     }
00572 
00573     if (lp!=NULL && lp->ldat.id==HTTP_UNKNOWN_METHOD) {             
00574         *pl = lp;
00575         return cc;
00576     }
00577 
00578     
00579     if (connect) {
00580         if (len>0) {
00581             cc = recv_https_content(sofd, ssl, buf, len, tsecond, NULL, &connect);
00582         }
00583         else if (len==HTTP_HEADER_CHUNKED) {
00584             connect = HTTP_HEADER_CHUNKED;
00585             if (!nochunk) {
00586                 cc = recv_https_chunked(sofd, ssl, buf, tsecond, NULL, &connect);
00587             }
00588         }
00589         else {  
00590             cc = recv_https_closed(sofd, ssl, buf, tsecond, NULL);
00591             connect = FALSE;
00592         }
00593     }
00594 
00595     
00596     if (!nochunk && is_http_header_field(lp, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00597         delete_protocol_header(&lp, (char*)"Transfer-Encoding", 0); 
00598         char* str = itostr_ts(cc);
00599         add_protocol_header(lp, (char*)"Content-Length", str);   
00600         freeNull(str);
00601     }
00602 
00603     if (pl!=NULL) *pl = lp;
00604     else del_tList(&lp);
00605 
00606     if (cc>0) cc = cc + hs;
00607 
00608     if (state!=NULL) *state = connect;
00609     return cc;
00610 }
00611 
00612 
00632 int  recv_https_file(int sofd, SSL* ssl, tList** pl, const char* fname, const char* wdir, int tsecond, int* hdonly, int* state)
00633 {
00634     int    cc=0, hs, len;
00635     Buffer buf, cnt;
00636     FILE*  fp = NULL;
00637     const char tmpd[] = "/tmp";
00638     int   connect;
00639 
00640     if (hdonly!=NULL) *hdonly = FALSE;
00641 
00642     
00643     hs = recv_https_header(sofd, ssl, pl, &len, tsecond, NULL, &connect);
00644     if (state!=NULL) *state = connect;
00645     if (hs<=0) return hs;                                           
00646     if (len==0 || len==HTTP_HEADER_UNKNOWN_LEN) {                   
00647         if (hdonly!=NULL) *hdonly = TRUE;
00648         return hs;
00649     }
00650 
00651     
00652     
00653     
00654 
00655     
00656     buf = make_Buffer(RECVBUFSZ);
00657     cnt = search_protocol_header(*pl, (char*)HDLIST_CONTENTS_KEY, 1);
00658     if (cnt.buf!=NULL) {
00659         
00660 
00661 
00662 
00663 
00664 
00665 
00666 
00667         cc = cnt.vldsz;
00668         hs = hs - cc;
00669         copy_Buffer(&cnt, &buf);
00670         free_Buffer(&cnt);
00671     }
00672 
00673     
00674     if (connect) {
00675         if (len>0) {
00676             cc = recv_https_content(sofd, ssl, &buf, len, tsecond, NULL, &connect);
00677         }
00678         else if (len==HTTP_HEADER_CHUNKED) {
00679             cc = recv_https_chunked(sofd, ssl, &buf, tsecond, NULL, &connect);
00680             
00681         }
00682         else { 
00683             cc = recv_https_closed(sofd, ssl, &buf, tsecond, NULL);
00684             connect = FALSE;
00685         }
00686     }
00687 
00688     if (cc>0) {
00689         
00690         if (fname!=NULL) fp = fopen(fname, "wb");
00691         if (fp!=NULL) {
00692             fwrite(buf.buf, buf.vldsz, 1, fp);
00693             fclose(fp);
00694         }
00695         free_Buffer(&buf);
00696 
00697         
00698         if (fname!=NULL) {
00699             buf = search_protocol_header(*pl, (char*)"Content-Encoding", 1);
00700 
00701             
00702             if (buf.buf!=NULL) {
00703                 
00704                 if (!strncasecmp((const char*)buf.buf, "gzip",    4) ||
00705                     !strncasecmp((const char*)buf.buf, "deflate", 7)) {
00706                     #ifdef DISABLE_ZLIB
00707                         DEBUG_MODE PRINT_MESG("RECV_HTTPS_FILE: WARNING: Content-Encoding is [%s]. But zlib is not installed!!\n", buf.buf);
00708                     #else
00709                         if (wdir==NULL) wdir = tmpd;
00710                         cc = gz_decode_file_replace(fname, wdir);
00711                         delete_protocol_header(pl, (char*)"Content-Encoding",  0);
00712 
00713                         
00714                         if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00715                             delete_protocol_header(pl, (char*)"Transfer-Encoding", 0);  
00716                             char* str = itostr_ts(cc);
00717                             add_protocol_header(*pl, (char*)"Content-Length", str);  
00718                             freeNull(str);
00719                         }
00720                     #endif
00721                 }
00722 
00723                 else { 
00724                     DEBUG_MODE PRINT_MESG("RECV_HTTPS_FILE: WARNING: unknown Content-Encoding [%s]\n", buf.buf);
00725                 }
00726                 free_Buffer(&buf);
00727             }
00728             
00729             
00730             else {
00731                 
00732                 if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00733                     delete_protocol_header(pl, (char*)"Transfer-Encoding", 0);  
00734                     char* str = itostr_ts(cc);
00735                     add_protocol_header(*pl, (char*)"Content-Length", str);  
00736                     freeNull(str);
00737                 }
00738             }
00739         }
00740         cc = cc + hs;
00741     }
00742 
00743     if (state!=NULL) *state = connect;
00744     return cc;
00745 }
00746 
00747 
00748 
00768 int   save_https_xml(int cofd, SSL* ssl, tList** pl, tXML** xml, char** recvfn, const char* wdir, int timeout, int* state)
00769 {
00770     int header;
00771 
00772     if (pl==NULL || recvfn==NULL) return 0;
00773 
00774     *pl = NULL;
00775     if (xml!=NULL) *xml = NULL;
00776     *recvfn = temp_filename(wdir, WORK_FILENAME_LEN);
00777    
00778     int cc = recv_https_file(cofd, ssl, pl, *recvfn, wdir, timeout, &header, state);
00779     if (cc<=0 || *pl==NULL) {
00780         free(*recvfn);
00781         *recvfn = NULL;
00782         if (cc==0) return 0;
00783         return JBXL_SSL_RECV_ERROR;
00784     }
00785 
00786     if (header) {
00787         free(*recvfn);
00788         *recvfn = NULL;
00789     }
00790     else {
00791 
00792         if (xml!=NULL && *pl!=NULL && *recvfn!=NULL && cc>0) {
00793             Buffer buf = search_protocol_header(*pl, (char*)"Content-Type", 1);
00794             *xml = xml_parse_file(*recvfn);
00795             if (*xml!=NULL && (*xml)->state<0) del_xml(xml);
00796             free_Buffer(&buf);
00797         }
00798     }
00799 
00800     return  cc;
00801 }
00802 
00803 
00804 #endif  //  ENABLE_SSL