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