00001
00011 #ifdef CPLUSPLUS
00012 #undef CPLUSPLUS
00013 #endif
00014
00015
00016 #include "http_tool.h"
00017
00018
00020
00021
00022
00057 int send_http_header(int sofd, tList* pp, int mode)
00058 {
00059 int hs=0, sz=0;
00060 Buffer buf;
00061
00062 if (pp==NULL) return JBXL_ARGS_ERROR;
00063
00064 buf = restore_protocol_header(pp, (char*)": ", mode, &hs);
00065 if (buf.vldsz>0) {
00066 sz = tcp_send_Buffer(sofd, &buf);
00067 if (mode==ON) sz = sz - hs;
00068 }
00069
00070 free_Buffer(&buf);
00071 return sz;
00072 }
00073
00074
00075
00076 Buffer rebuild_http_Buffer(tList* pl, Buffer* buf)
00077 {
00078 Buffer rbd;
00079 int nobody = FALSE;
00080
00081 if (pl==NULL) {
00082 rbd = dup_Buffer(*buf);
00083 return rbd;
00084 }
00085 if (buf==NULL || buf->vldsz<0 || buf->buf==NULL) nobody = TRUE;
00086
00087 if (!nobody) {
00088
00089 tList* pp = pl;
00090 while(pp!=NULL) {
00091 if (!strcasecmp((const char*)(pp->ldat.key.buf), "Content-Length")) {
00092 copy_i2Buffer(buf->vldsz, &(pp->ldat.val));
00093 break;
00094 }
00095 pp = pp->next;
00096 }
00097 }
00098
00099 rbd = restore_protocol_header(pl, (char*)": ", OFF, NULL);
00100 if (!nobody) cat_Buffer(buf, &rbd);
00101
00102 return rbd;
00103 }
00104
00105
00106
00107
00120 int send_http_Buffer(int sofd, tList* pl, Buffer* buf)
00121 {
00122 int sz;
00123 Buffer snd;
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 snd = rebuild_http_Buffer(pl, buf);
00147 sz = tcp_send_Buffer(sofd, &snd);
00148 free_Buffer(&snd);
00149
00150 return sz;
00151 }
00152
00153
00154
00168 int send_http_file(int sofd, tList* pl, const char* fname)
00169 {
00170 int sz = 0;
00171 FILE* fp = NULL;
00172 char num[20];
00173 tList* pp;
00174 unsigned char* html;
00175 Buffer buf;
00176
00177 size_t rs;
00178 UNUSED(rs);
00179
00180 if (pl==NULL) return JBXL_ARGS_ERROR;
00181 if (fname!=NULL) sz = file_size((char*)fname);
00182 if (sz<=0) sz = 0;
00183 snprintf(num, 18, "%d", sz);
00184
00185
00186 pp = pl;
00187 while(pp!=NULL) {
00188 if (!strcasecmp((const char*)(pp->ldat.key.buf), "Content-Length")) {
00189 copy_s2Buffer(num, &(pp->ldat.val));
00190 break;
00191 }
00192 pp = pp->next;
00193 }
00194
00195 buf = restore_protocol_header(pl, (char*)": ", OFF, NULL);
00196
00197 if (fname!=NULL && sz!=0) fp = fopen(fname, "rb");
00198 if (fp!=NULL) {
00199 html = (unsigned char*)malloc(sz+1);
00200 if (html==NULL) {
00201 fclose(fp);
00202 free_Buffer(&buf);
00203 return JBXL_MALLOC_ERROR;
00204 }
00205
00206 memset(html, 0, sz+1);
00207 rs = fread(html, sz, 1, fp);
00208 fclose(fp);
00209
00210 cat_b2Buffer(html, &buf, sz);
00211 free(html);
00212 }
00213
00214 sz = tcp_send_Buffer(sofd, &buf);
00215 free_Buffer(&buf);
00216
00217 return sz;
00218 }
00219
00220
00221
00246 int recv_http_header(int sofd, tList** pl, int* len, int tm, FILE* fp, int* state)
00247 {
00248 int cc, sz, com;
00249 Buffer mbuf;
00250 tList* lp;
00251 int connect = TRUE;
00252
00253 if (sofd<=0) return JBXL_ARGS_ERROR;
00254 if (len==NULL) return JBXL_ARGS_ERROR;
00255 *len = HTTP_HEADER_UNKNOWN_LEN;
00256
00257 mbuf = make_Buffer(RECVBUFSZ);
00258
00259 sz = 0;
00260 lp = NULL;
00261 *pl = NULL;
00262
00263 cc = tcp_recv_Buffer_wait(sofd, &mbuf, tm);
00264 com = get_http_method((char*)mbuf.buf);
00265
00266 if (com>HTTP_UNKNOWN_METHOD) {
00267 Loop {
00268 if (cc>0) {
00269 if (fp!=NULL) fwrite(mbuf.buf, cc, 1, fp);
00270 lp = get_protocol_header_list_seq(lp, mbuf, ':', TRUE, TRUE);
00271 sz += cc;
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 }
00282 else {
00283 connect = FALSE;
00284 break;
00285 }
00286
00287 *pl = find_tList_top(lp);
00288 if (strncasecmp_tList(*pl, (char*)HDLIST_END_KEY, 0, 1)!=NULL) break;
00289
00290 cc = tcp_recv_Buffer_wait(sofd, &mbuf, tm);
00291 }
00292 }
00293 else {
00294 if (mbuf.vldsz>0) {
00295 Buffer key = make_Buffer_str(HDLIST_CONTENTS_KEY);
00296 *pl = add_tList_node_Buffer(NULL, key, mbuf);
00297 free_Buffer(&key);
00298 }
00299 *len = HTTP_HEADER_NOT_HTTP;
00300 connect = FALSE;
00301 }
00302
00303 free_Buffer(&mbuf);
00304 if (*pl!=NULL) (*pl)->ldat.id = com;
00305 if (state!=NULL) *state = connect;
00306
00307 if (sz==0 && cc==0) return 0;
00308 if (sz==0 && cc<0) return JBXL_NET_RECV_ERROR;
00309 if (*pl==NULL) return JBXL_NET_RECV_ERROR;
00310 if (*len==HTTP_HEADER_NOT_HTTP) return cc;
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 if (com==HTTP_GET_METHOD) *len = 0;
00323
00324 if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00325 if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00326 *len = HTTP_HEADER_CHUNKED;
00327 }
00328 }
00329
00330 if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00331 Buffer hbuf = search_protocol_header(*pl, (char*)"Content-Length", 1);
00332 if (hbuf.buf!=NULL) {
00333 *len = atoi((const char*)hbuf.buf);
00334 free_Buffer(&hbuf);
00335 }
00336 }
00337
00338 if (*len==HTTP_HEADER_UNKNOWN_LEN) {
00339 if (get_http_version_num(*pl)<=1.0 && get_http_status_num(*pl)>=200) {
00340 if (is_http_header_field(*pl, (char*)"Connection", (char*)"close", 1)) {
00341 *len = HTTP_HEADER_CLOSED_SESSION;
00342 }
00343 }
00344 }
00345
00346 return sz;
00347 }
00348
00349
00350
00368 int recv_http_content(int sofd, Buffer* buf, int len, int tm, FILE* fp, int* state)
00369 {
00370 int cc, sz;
00371 Buffer rcv;
00372
00373 if (state!=NULL) *state = TRUE;
00374
00375 sz = buf->vldsz;
00376 if (sz>0 && fp!=NULL) fwrite(buf->buf, sz, 1, fp);
00377
00378
00379 rcv = make_Buffer(RECVBUFSZ);
00380 while(sz<len) {
00381
00382 cc = tcp_recv_Buffer_wait(sofd, &rcv, tm);
00383 if (cc>0) {
00384 if (fp!=NULL) fwrite(rcv.buf, cc, 1, fp);
00385 cat_Buffer(&rcv, buf);
00386 sz += cc;
00387 }
00388 else {
00389 if (state!=NULL) *state = FALSE;
00390 sz = cc;
00391 break;
00392 }
00393
00394 }
00395 free_Buffer(&rcv);
00396
00397 return sz;
00398 }
00399
00400
00401
00418 int recv_http_chunked(int sofd, Buffer* buf, int tm, FILE* fp, int* state)
00419 {
00420 int cc, sz, i;
00421 int chnksz, hdsz, tlsz;
00422 if (state!=NULL) *state = TRUE;
00423
00424 Buffer tmp = make_Buffer(RECVBUFSZ);
00425
00426 sz = buf->vldsz;
00427 if (sz<=0) {
00428 cc = tcp_recv_Buffer_wait(sofd, &tmp, tm);
00429 if (cc<=0) {
00430 if (state!=NULL) *state = FALSE;
00431 free_Buffer(&tmp);
00432 return cc;
00433 }
00434 }
00435 else {
00436 cat_Buffer(buf, &tmp);
00437 clear_Buffer(buf);
00438 }
00439
00440
00441 chnksz = sz = get_chunked_size((char*)tmp.buf, &hdsz, &tlsz);
00442
00443 while (chnksz>0) {
00444
00445 if (chnksz+hdsz+tlsz > tmp.vldsz) {
00446 cc = recv_http_chunked_remain(sofd, &tmp, chnksz+hdsz+tlsz, tm);
00447 if (cc<=0) {
00448 sz = cc;
00449 break;
00450 }
00451 }
00452
00453 Buffer cat = tmp;
00454 cat.buf = tmp.buf + hdsz;
00455 cat.vldsz = chnksz;
00456 cat_Buffer(&cat, buf);
00457
00458
00459
00460 for (i=0; i<tmp.vldsz-chnksz-hdsz-tlsz; i++) {
00461 tmp.buf[i] = tmp.buf[chnksz + hdsz + tlsz + i];
00462 }
00463 tmp.vldsz = tmp.vldsz - chnksz - hdsz - tlsz;
00464
00465
00466 if (tmp.vldsz==0) {
00467 cc = tcp_recv_Buffer_wait(sofd, &tmp, tm);
00468 if (cc<=0) {
00469 sz = cc;
00470 break;
00471 }
00472 }
00473 chnksz = get_chunked_size((char*)tmp.buf, &hdsz, &tlsz);
00474 sz += chnksz;
00475 }
00476
00477 if (fp!=NULL) fwrite(buf->buf, buf->vldsz, 1, fp);
00478
00479 free_Buffer(&tmp);
00480 return sz;
00481 }
00482
00483
00484
00498 int recv_http_chunked_remain(int sofd, Buffer* buf, int chnksz, int tm)
00499 {
00500 int cc = 0;
00501 int sz = buf->vldsz;
00502 if (chnksz<=sz) return 0;
00503
00504 Buffer rcv = make_Buffer(RECVBUFSZ);
00505
00506 while (chnksz>sz) {
00507
00508 cc = tcp_recv_Buffer_wait(sofd, &rcv, tm);
00509 if (cc<=0) {
00510 sz = cc;
00511 break;
00512 }
00513 cat_Buffer(&rcv, buf);
00514 sz += cc;
00515 }
00516
00517 free_Buffer(&rcv);
00518 return sz;
00519 }
00520
00521
00522
00539 int recv_http_closed(int sofd, Buffer* buf, int tm, FILE* fp)
00540 {
00541 int cc, sz, tout;
00542 Buffer rcv;
00543
00544 sz = buf->vldsz;
00545
00546 rcv = make_Buffer(RECVBUFSZ);
00547 while ((tout=recv_wait(sofd, tm))){
00548 cc = tcp_recv_Buffer(sofd, &rcv);
00549 if (cc>0) {
00550 if (fp!=NULL) fwrite(rcv.buf, cc, 1, fp);
00551 cat_Buffer(&rcv, buf);
00552 sz += cc;
00553 }
00554 else {
00555 break;
00556 }
00557
00558 }
00559 free_Buffer(&rcv);
00560
00561 if (!tout) return JBXL_NET_RECV_TIMEOUT;
00562
00563 return sz;
00564 }
00565
00566
00567
00588 int recv_http_Buffer(int sofd, tList** pl, Buffer* buf, int tsecond, int* hdonly, int* state, int nochunk)
00589 {
00590 int cc=0, hs, len;
00591 int connect;
00592 Buffer cnt;
00593 tList* lp;
00594
00595 if (buf==NULL || buf->buf==NULL) return JBXL_ARGS_ERROR;
00596 if (hdonly!=NULL) *hdonly = FALSE;
00597
00598 clear_Buffer(buf);
00599
00600
00601 hs = recv_http_header(sofd, &lp, &len, tsecond, NULL, &connect);
00602 if (state!=NULL) *state = connect;
00603 if (hs<=0) return hs;
00604 if (len==0 || len==HTTP_HEADER_UNKNOWN_LEN) {
00605 if (hdonly!=NULL) *hdonly = TRUE;
00606 if (pl!=NULL) *pl = lp;
00607 else del_tList(&lp);
00608 return hs;
00609 }
00610
00611
00612 cnt = search_protocol_header(lp, (char*)HDLIST_CONTENTS_KEY, 1);
00613 if (cnt.buf!=NULL) {
00614 cc = cnt.vldsz;
00615 hs = hs - cc;
00616 copy_Buffer(&cnt, buf);
00617 free_Buffer(&cnt);
00618 }
00619
00620 if (lp!=NULL && lp->ldat.id==HTTP_UNKNOWN_METHOD) {
00621 *pl = lp;
00622 return cc;
00623 }
00624
00625
00626 if (connect) {
00627 if (len>0) {
00628 cc = recv_http_content(sofd, buf, len, tsecond, NULL, &connect);
00629 }
00630 else if (len==HTTP_HEADER_CHUNKED) {
00631 connect = HTTP_HEADER_CHUNKED;
00632 if (!nochunk) {
00633 cc = recv_http_chunked(sofd, buf, tsecond, NULL, &connect);
00634 }
00635 }
00636 else {
00637 cc = recv_http_closed(sofd, buf, tsecond, NULL);
00638 connect = FALSE;
00639 }
00640 }
00641
00642
00643 if (!nochunk && is_http_header_field(lp, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00644 delete_protocol_header(&lp, (char*)"Transfer-Encoding", 0);
00645 char* str = itostr_ts(cc);
00646 add_protocol_header(lp, (char*)"Content-Length", str);
00647 freeNull(str);
00648 }
00649
00650 if (pl!=NULL) *pl = lp;
00651 else del_tList(&lp);
00652 if (cc>0) cc = cc + hs;
00653
00654 if (state!=NULL) *state = connect;
00655 return cc;
00656 }
00657
00658
00659
00678 int recv_http_file(int sofd, tList** pl, const char* fname, const char* wdir, int tsecond, int* hdonly, int* state)
00679 {
00680 int cc=0, hs, len;
00681 Buffer buf, cnt;
00682 FILE* fp = NULL;
00683 const char tmpd[] = "/tmp";
00684 int connect;
00685
00686 if (hdonly!=NULL) *hdonly = FALSE;
00687
00688
00689 hs = recv_http_header(sofd, pl, &len, tsecond, NULL, &connect);
00690 if (state!=NULL) *state = connect;
00691 if (hs<=0) return hs;
00692 if (len==0 || len==HTTP_HEADER_UNKNOWN_LEN) {
00693 if (hdonly!=NULL) *hdonly = TRUE;
00694 return hs;
00695 }
00696
00697
00698 buf = make_Buffer(RECVBUFSZ);
00699 cnt = search_protocol_header(*pl, (char*)HDLIST_CONTENTS_KEY, 1);
00700 if (cnt.buf!=NULL) {
00701
00702
00703
00704
00705
00706
00707
00708
00709 cc = cnt.vldsz;
00710 hs = hs - cc;
00711 copy_Buffer(&cnt, &buf);
00712 free_Buffer(&cnt);
00713 }
00714
00715
00716 if (connect) {
00717 if (len>0) {
00718 cc = recv_http_content(sofd, &buf, len, tsecond, NULL, &connect);
00719 }
00720 else if (len==HTTP_HEADER_CHUNKED) {
00721 cc = recv_http_chunked(sofd, &buf, tsecond, NULL, &connect);
00722 }
00723 else {
00724 cc = recv_http_closed(sofd, &buf, tsecond, NULL);
00725 connect = FALSE;
00726 }
00727 }
00728
00729 if (cc>0) {
00730
00731 if (fname!=NULL) fp = fopen(fname, "wb");
00732 if (fp!=NULL) {
00733 fwrite(buf.buf, buf.vldsz, 1, fp);
00734 fclose(fp);
00735 }
00736 free_Buffer(&buf);
00737
00738
00739 if (fname!=NULL) {
00740 buf = search_protocol_header(*pl, (char*)"Content-Encoding", 1);
00741
00742
00743 if (buf.buf!=NULL) {
00744
00745 if (!strncasecmp((const char*)buf.buf, "gzip", 4) ||
00746 !strncasecmp((const char*)buf.buf, "deflate", 7)) {
00747 #ifdef DISABLE_ZLIB
00748 DEBUG_MODE PRINT_MESG("RECV_HTTP_FILE: WARNING: Content-Encoding is [%s]. But zlib is not installed!!\n", buf.buf);
00749 #else
00750 if (wdir==NULL) wdir = tmpd;
00751 cc = gz_decode_file_replace(fname, wdir);
00752 delete_protocol_header(pl, (char*)"Content-Encoding", 0);
00753
00754
00755 if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00756 delete_protocol_header(pl, (char*)"Transfer-Encoding", 0);
00757 char* str = itostr_ts(cc);
00758 add_protocol_header(*pl, (char*)"Content-Length", str);
00759 freeNull(str);
00760 }
00761 #endif
00762 }
00763
00764 else {
00765 DEBUG_MODE PRINT_MESG("RECV_HTTP_FILE: WARNING: unknown Content-Encoding [%s]\n", buf.buf);
00766 }
00767
00768 free_Buffer(&buf);
00769 }
00770
00771
00772 else {
00773
00774 if (is_http_header_field(*pl, (char*)"Transfer-Encoding", (char*)"chunked", 1)) {
00775 delete_protocol_header(pl, (char*)"Transfer-Encoding", 0);
00776 char* str = itostr_ts(cc);
00777 add_protocol_header(*pl, (char*)"Content-Length", str);
00778 freeNull(str);
00779 }
00780 }
00781 }
00782 cc = cc + hs;
00783 }
00784
00785 if (state!=NULL) *state = connect;
00786 return cc;
00787 }
00788
00789
00790
00809 int save_http_xml(int cofd, tList** pl, tXML** xml, char** recvfn, const char* wdir, int timeout, int* state)
00810 {
00811 int header;
00812
00813 if (pl==NULL || recvfn==NULL) return 0;
00814
00815 *pl = NULL;
00816 if (xml!=NULL) *xml = NULL;
00817 *recvfn = temp_filename(wdir, WORK_FILENAME_LEN);
00818
00819 int cc = recv_http_file(cofd, pl, *recvfn, wdir, timeout, &header, state);
00820 if (cc<=0 || *pl==NULL) {
00821 free(*recvfn);
00822 *recvfn = NULL;
00823 if (cc==0) return 0;
00824 return JBXL_NET_RECV_ERROR;
00825 }
00826
00827 if (header) {
00828 free(*recvfn);
00829 *recvfn = NULL;
00830 }
00831 else {
00832 if (xml!=NULL && *pl!=NULL && *recvfn!=NULL && cc>0) {
00833 Buffer buf = search_protocol_header(*pl, (char*)"Content-Type", 1);
00834 *xml = xml_parse_file(*recvfn);
00835 if (*xml!=NULL && (*xml)->state<0) del_xml(xml);
00836 free_Buffer(&buf);
00837 }
00838 }
00839
00840 return cc;
00841 }
00842
00843
00844
00845
00847
00848
00849
00850 int get_http_method(char* data)
00851 {
00852 if (ex_strcmp("GET ", data)) return HTTP_GET_METHOD;
00853 else if (ex_strcmp("PUT ", data)) return HTTP_PUT_METHOD;
00854 else if (ex_strcmp("POST ", data)) return HTTP_POST_METHOD;
00855 else if (ex_strcmp("DELETE ", data)) return HTTP_DELETE_METHOD;
00856 else if (ex_strcmp("OPTIONS ", data)) return HTTP_OPTIONS_METHOD;
00857 else if (ex_strcmp("HEAD ", data)) return HTTP_HEAD_METHOD;
00858 else if (ex_strcmp("TRACE ", data)) return HTTP_TRACE_METHOD;
00859 else if (ex_strcmp("CONNECT ", data)) return HTTP_CONNECT_METHOD;
00860 else if (ex_strcmp("PATCH ", data)) return HTTP_PATCH_METHOD;
00861 else if (ex_strcmp("LINK ", data)) return HTTP_LINK_METHOD;
00862 else if (ex_strcmp("UNLINK ", data)) return HTTP_UNLINK_METHOD;
00863 else if (ex_strcmp("HTTP/", data)) return HTTP_RESPONSE_METHOD;
00864
00865 else if (ex_strcmp("PROPFIND ", data)) return HTTP_PROPFIND_METHOD;
00866 else if (ex_strcmp("PROPPATCH ", data)) return HTTP_PROPPATCH_METHOD;
00867 else if (ex_strcmp("MKCOL ", data)) return HTTP_MKCOL_METHOD;
00868 else if (ex_strcmp("COPY ", data)) return HTTP_COPY_METHOD;
00869 else if (ex_strcmp("MOVE ", data)) return HTTP_MOVE_METHOD;
00870 else if (ex_strcmp("LOCK ", data)) return HTTP_LOCK_METHOD;
00871 else if (ex_strcmp("UNLOCK ", data)) return HTTP_UNLOCK_METHOD;
00872
00873 return HTTP_UNKNOWN_METHOD;
00874 }
00875
00876
00877
00891 int is_http_header_field(tList* pl, char* field, char* value, int n)
00892 {
00893 int ret = FALSE;
00894
00895 Buffer hbuf = search_protocol_header(pl, field, n);
00896 if (hbuf.buf!=NULL) {
00897 if (!strcasecmp((char*)hbuf.buf, value)) {
00898 ret = TRUE;
00899 }
00900 free_Buffer(&hbuf);
00901 }
00902
00903 return ret;
00904 }
00905
00906
00907
00913 int get_http_header_method(tList* pl)
00914 {
00915 int ret = HTTP_UNKNOWN_METHOD;
00916
00917 if (pl==NULL) return ret;
00918
00919 Buffer hbuf = search_protocol_header(pl, (char*)HDLIST_FIRST_LINE_KEY, 1);
00920 if (hbuf.buf!=NULL) ret = get_http_method((char*)hbuf.buf);
00921
00922 return ret;
00923 }
00924
00925
00926
00933 void set_http_host_header(tList* pl, char* hname, unsigned short hport)
00934 {
00935 Buffer buf;
00936 char num[LEN_INT];
00937
00938 if (pl==NULL) return;
00939
00940 buf = make_Buffer(LBUF);
00941 snprintf(num, LEN_INT-1, "%d", hport);
00942 copy_s2Buffer(hname, &buf);
00943 cat_s2Buffer (":", &buf);
00944 cat_s2Buffer (num, &buf);
00945
00946 set_protocol_header(pl, (char*)"Host", (char*)buf.buf, 1, ON);
00947
00948 free_Buffer(&buf);
00949 return;
00950 }
00951
00952
00953
00959 void dump_http_header(FILE* fp, tList* pp)
00960 {
00961 if (fp==NULL) fp = stderr;
00962
00963 if (pp!=NULL) {
00964 int image = FALSE;
00965 while(pp!=NULL) {
00966 tList_data ld = pp->ldat;
00967 if (!strcasecmp((const char*)ld.key.buf, "Content-Type")) {
00968 if (!strncasecmp((const char*)ld.val.buf, "image", 5)) image = TRUE;
00969
00970 }
00971
00972 if (!strcasecmp((const char*)ld.key.buf, HDLIST_CONTENTS_KEY) && image==TRUE) {
00973 fprintf(fp, "[%d] [%d] [%s] [%d]\n", ld.id, ld.lv, ld.key.buf, ld.val.vldsz);
00974 fdump(fp, (unsigned char*)ld.val.buf, ld.val.vldsz);
00975 }
00976 else {
00977 fprintf(fp, "[%d] [%d] [%s] [%s]\n", ld.id, ld.lv, ld.key.buf, ld.val.buf);
00978 }
00979 pp = pp->next;
00980 }
00981 }
00982 else {
00983 fprintf(fp, "(List is NULL)\n");
00984 }
00985 return;
00986 }
00987
00988
00989
00999 int get_chunked_size(char* ptr, int* hdsz, int* tlsz)
01000 {
01001 int ck = 0, hd = 0, tl = 0;
01002 char hex[L_32];
01003
01004 int i = 0;
01005 while (ptr[i]!=0x0d && i<L_32) {
01006 hex[i] = ptr[i];
01007 i++;
01008 }
01009 if (i==L_32) {
01010 if (hdsz!=NULL) *hdsz = 0;
01011 if (tlsz!=NULL) *tlsz = 0;
01012 return -1;
01013 }
01014
01015 if (ptr[i+1]==0x0a) hd = i + 2;
01016 else hd = i + 1;
01017 if (hdsz!=NULL) *hdsz = hd;
01018
01019 hex[i] = '\0';
01020 ck = hexstr2i(hex);
01021
01022 if (ptr[ck+hd]==0x0d) {
01023 tl++;
01024 if (ptr[ck+hd+tl]==0x0a) tl++;
01025 }
01026 if (tlsz!=NULL) *tlsz = tl;
01027
01028 return ck;
01029 }
01030
01031
01032
01033
01034 char* get_http_header_date(time_t date)
01035 {
01036 char* buf = get_gmt_timestamp(date, "%a, %d %b %Y %H:%M:%S %Z");
01037
01038 return buf;
01039 }
01040
01041
01042
01043
01045
01046
01047
01064 void simple_web_proxy(int bofd, char* myip, int tmout)
01065 {
01066 int wofd = 0;
01067 int len, nd, cc, state;
01068 int btm, wtm, keep;
01069 char* ipa;
01070 tList* pl;
01071
01072 unsigned short sport = 0;
01073 Buffer server, com;
01074
01075 fd_set mask;
01076 struct timeval timeout;
01077
01078
01079
01080
01081 if (tmout<0) tmout = HTTP_PROXY_TIMEOUT;
01082 btm = wtm = tmout;
01083 keep = TRUE;
01084
01085 do {
01086 timeout.tv_sec = btm*10;
01087 timeout.tv_usec = 0;
01088 FD_ZERO(&mask);
01089 FD_SET(bofd, &mask);
01090 nd = select(bofd+1, &mask, NULL, NULL, &timeout);
01091 } while (nd<0);
01092
01093 while (FD_ISSET(bofd, &mask) && keep) {
01094 cc = recv_http_header(bofd, &pl, &len, tmout, NULL, &state);
01095 if (cc<=0) break;
01096 if (pl==NULL) break;
01097
01098
01099
01100
01101
01102
01103
01104
01105 com = http_proxy_header_analyze(pl, &server, &sport, &btm, &keep);
01106 if (btm==0) btm = tmout;
01107 else btm = Min(btm, 60);
01108
01109 wofd = 0;
01110 if (server.buf!=NULL && sport!=0) {
01111 ipa = get_ipaddr_byname((char*)server.buf, AF_INET);
01112 if (ipa!=NULL && !strcmp(ipa, myip)) {
01113 free_Buffer(&server);
01114 server = make_Buffer_bystr("127.0.0.1");
01115 }
01116 freeNull(ipa);
01117
01118 wofd = tcp_client_socket((char*)server.buf, sport);
01119 free_Buffer(&server);
01120 }
01121
01122 if (wofd<=0) {
01123 free_Buffer(&com);
01124 del_tList(&pl);
01125 break;
01126 }
01127
01128
01129 if (com.buf!=NULL && !strcasecmp((char*)com.buf, "CONNECT")) {
01130 cc = tcp_send(bofd, (char*)"HTTP/1.1 200 Connection established.\r\nProxy-Connection: close\r\n\r\n", 0);
01131 cc = tcp_relay(bofd, wofd, 5);
01132
01133 del_tList(&pl);
01134 free_Buffer(&com);
01135 break;
01136 }
01137 free_Buffer(&com);
01138
01139 cc = send_http_header(wofd, pl, ON);
01140 if (cc<len && state) {
01141 Buffer buf = make_Buffer(RECVBUFSZ);
01142 cc = recv_http_content(bofd, &buf, len-cc, wtm, NULL, &state);
01143 if (cc<=0) {
01144 del_tList(&pl);
01145 break;
01146 }
01147
01148 tcp_send_Buffer(wofd, &buf);
01149 free_Buffer(&buf);
01150 }
01151 del_tList(&pl);
01152
01153 cc = www2browser_relay(bofd, wofd, btm, wtm, keep);
01154 if (cc<=0) break;
01155
01156 do {
01157 timeout.tv_sec = btm;
01158 timeout.tv_usec = 0;
01159 FD_ZERO(&mask);
01160 FD_SET(bofd, &mask);
01161 nd = select(bofd+1, &mask, NULL, NULL, &timeout);
01162 } while (nd<0);
01163 }
01164
01165 socket_close(wofd);
01166
01167 return;
01168 }
01169
01170
01171
01185 Buffer http_proxy_header_analyze(tList* pl, Buffer* server, unsigned short* sport, int* timeout, int* keep)
01186 {
01187 tList* frst;
01188 tList* lst;
01189 Buffer cmnd, url, ptcl;
01190 Buffer srvdir, bufport;
01191
01192 cmnd = init_Buffer();
01193 srvdir = init_Buffer();
01194 *server = init_Buffer();
01195 *sport = 0;
01196 *timeout = 0;
01197 *keep = FALSE;
01198
01199 frst = strncasecmp_tList(pl, (char*)HDLIST_FIRST_LINE_KEY, 0, 1);
01200 if (frst!=NULL) {
01201 cmnd = cawk_Buffer(frst->ldat.val, ' ', 1);
01202 url = cawk_Buffer(frst->ldat.val, ' ', 2);
01203 ptcl = cawk_Buffer(frst->ldat.val, ' ', 3);
01204 decomp_url(url, NULL, NULL, server, sport, &srvdir);
01205 }
01206 else return cmnd;
01207
01208 if (server->buf==NULL) {
01209 lst = strncasecmp_tList(pl, (char*)"Host", 0, 1);
01210 if (lst!=NULL) {
01211 *server = cawk_Buffer(lst->ldat.val, ':', 1);
01212 bufport = cawk_Buffer(lst->ldat.val, ':', 2);
01213 if (bufport.buf!=NULL) *sport = atoi((char*)bufport.buf);
01214 free_Buffer(&bufport);
01215 }
01216 }
01217 if (*sport==0) *sport = 80;
01218
01219 lst = strncasecmp_tList(pl, (char*)"Keep-Alive", 0, 1);
01220 if (lst!=NULL) {
01221 if (lst->ldat.val.buf!=NULL) *timeout = atoi((char*)(lst->ldat.val.buf));
01222 del_tList_node(&lst);
01223 }
01224
01225 lst = strncasecmp_tList(pl, (char*)"Proxy-Connection", 0, 1);
01226 if (lst!=NULL) {
01227 if (!strcasecmp((char*)(lst->ldat.val.buf), "keep-alive")) *keep = TRUE;
01228 del_tList_node(&lst);
01229 }
01230
01231 free_Buffer(&(frst->ldat.val));
01232 copy_Buffer (&cmnd, &(frst->ldat.val));
01233 cat_s2Buffer(" ", &(frst->ldat.val));
01234 cat_Buffer (&srvdir, &(frst->ldat.val));
01235 cat_s2Buffer(" ", &(frst->ldat.val));
01236 cat_Buffer (&ptcl, &(frst->ldat.val));
01237
01238 free_Buffer(&url);
01239 free_Buffer(&ptcl);
01240 free_Buffer(&srvdir);
01241
01242 return cmnd;
01243 }
01244
01245
01246
01262 int www2browser_relay(int bofd, int wofd, int btm, int wtm, int keep)
01263 {
01264 int len, cc, cx, sz, tout, state;
01265 Buffer buf;
01266 tList* pl;
01267 tList* lst;
01268
01269 if (!recv_wait(wofd, wtm*10)) return JBXL_NET_RECV_TIMEOUT;
01270 cc = recv_http_header(wofd, &pl, &len, wtm, NULL, &state);
01271 if (cc<=0) {
01272 if (pl!=NULL) del_tList(&pl);
01273 return cc;
01274 }
01275 if (pl==NULL) return JBXL_NET_RECV_ERROR;
01276
01277
01278
01279
01280
01281
01282
01283
01284 lst = strncasecmp_tList(pl, (char*)HDLIST_END_KEY, 0, 1);
01285 if (lst!=NULL && lst->prev!=NULL) {
01286 if (keep) {
01287 char pxcn[48];
01288 snprintf(pxcn, 46, "keep-alive, timeout=%d", btm);
01289 add_tList_node_str(lst->prev, "Proxy-Connection", pxcn);
01290 }
01291 else {
01292 add_tList_node_str(lst->prev, "Proxy-Connection", "close");
01293 }
01294 }
01295
01296 sz = cx = send_http_header(bofd, pl, ON);
01297 del_tList(&pl);
01298
01299 if (len>0) {
01300 buf = make_Buffer(RECVBUFSZ);
01301 while(sz<len) {
01302 if (!recv_wait(wofd, wtm)) {
01303 free_Buffer(&buf);
01304 return JBXL_NET_RECV_TIMEOUT;
01305 }
01306 cc = tcp_recv_Buffer(wofd, &buf);
01307 if (cc>0) {
01308 sz += cc;
01309 cx = tcp_send_Buffer(bofd, &buf);
01310 if (cx<=0) break;
01311 }
01312 else break;
01313 }
01314
01315 free_Buffer(&buf);
01316 if (cc<=0 || (cc>0&&cx<=0)) return 0;
01317 }
01318
01319 else if (len==HTTP_HEADER_CHUNKED || len==HTTP_HEADER_CLOSED_SESSION) {
01320 buf = make_Buffer(RECVBUFSZ);
01321 while ((tout=recv_wait(wofd, 1))){
01322 cc = tcp_recv_Buffer(wofd, &buf);
01323 if (cc>0) {
01324 sz += cc;
01325 cx = tcp_send_Buffer(bofd, &buf);
01326 if (cx<=0) break;
01327 }
01328 else break;
01329 }
01330
01331 free_Buffer(&buf);
01332 if (!tout) return JBXL_NET_RECV_TIMEOUT;
01333 return 0;
01334 }
01335
01336 return sz;
01337 }
01338
01339
01340
01341
01343
01344
01345
01359 int tcp_relay(int sofd, int cofd, int tm)
01360 {
01361 int num, nd, cx, cc = JBXL_NET_RECV_TIMEOUT;
01362 Buffer buf;
01363 fd_set mask;
01364 struct timeval timeout;
01365
01366 buf = make_Buffer(RECVBUFSZ);
01367 num = Max(sofd, cofd);
01368
01369 do {
01370 timeout.tv_sec = tm;
01371 timeout.tv_usec = 0;
01372 FD_ZERO(&mask);
01373 FD_SET(sofd, &mask);
01374 FD_SET(cofd, &mask);
01375 nd = select(num+1, &mask, NULL, NULL, &timeout);
01376 } while (nd<0);
01377
01378
01379 while (nd>0 && (FD_ISSET(cofd, &mask) || FD_ISSET(sofd, &mask))) {
01380
01381 if (FD_ISSET(cofd, &mask)) {
01382 cc = tcp_recv_Buffer(cofd, &buf);
01383 if (cc>0) {
01384 cx = tcp_send_Buffer(sofd, &buf);
01385 if (cx<=0) {
01386 cc = cx;
01387 break;
01388 }
01389 }
01390 else break;
01391
01392 }
01393
01394 if (FD_ISSET(sofd, &mask)) {
01395 cc = tcp_recv_Buffer(sofd, &buf);
01396 if (cc>0) {
01397 cx = tcp_send_Buffer(cofd, &buf);
01398 if (cx<=0) {
01399 cc = cx;
01400 break;
01401 }
01402 }
01403 else break;
01404
01405 }
01406
01407 do {
01408 timeout.tv_sec = tm;
01409 timeout.tv_usec = 0;
01410 FD_ZERO(&mask);
01411 FD_SET(sofd, &mask);
01412 FD_SET(cofd, &mask);
01413 nd = select(num+1, &mask, NULL, NULL, &timeout);
01414 } while (nd<0);
01415 }
01416
01417 free_Buffer(&buf);
01418
01419 if (!FD_ISSET(cofd, &mask) && !FD_ISSET(sofd, &mask)) return JBXL_NET_RECV_TIMEOUT;
01420 return cc;
01421 }
01422
01423
01424
01425 int get_http_status_num(tList* pl)
01426 {
01427 int pnum = 0;
01428
01429 Buffer dat = search_protocol_header(pl, (char*)HDLIST_FIRST_LINE_KEY, 1);
01430 if (dat.buf!=NULL) {
01431 if (!strncasecmp((const char*)dat.buf, "HTTP/", 5)) {
01432 Buffer num = cawk_Buffer(dat, ' ', 2);
01433 if (num.buf!=NULL) {
01434 pnum = atoi((const char*)num.buf);
01435 free_Buffer(&num);
01436 }
01437 }
01438 free_Buffer(&dat);
01439 }
01440
01441 return pnum;
01442 }
01443
01444
01445
01446 float get_http_version_num(tList* pl)
01447 {
01448 float ver = 0.0;
01449
01450 Buffer dat = search_protocol_header(pl, (char*)HDLIST_FIRST_LINE_KEY, 1);
01451 if (dat.buf!=NULL) {
01452 if (!strncasecmp((const char*)dat.buf, "HTTP/", 5)) {
01453 Buffer num = cawk_Buffer(dat, ' ', 1);
01454 if (num.buf!=NULL) {
01455 ver = (float)atof((char*)&num.buf[5]);
01456 free_Buffer(&num);
01457 }
01458 }
01459 else {
01460 Buffer buf = cawk_Buffer(dat, ' ', 3);
01461 if (!strncasecmp((const char*)buf.buf, "HTTP/", 5)) {
01462 Buffer num = cawk_Buffer(buf, ' ', 1);
01463 if (num.buf!=NULL) {
01464 ver = (float)atof((char*)&num.buf[5]);
01465 free_Buffer(&num);
01466 }
01467 }
01468 free_Buffer(&buf);
01469 }
01470 free_Buffer(&dat);
01471 }
01472
01473 return ver;
01474 }
01475
01476
01477
01478
01480
01481
01482
01483 int send_http_res_file(int sofd, char* fname, int mode)
01484 {
01485 int sz;
01486 FILE* fp;
01487 char buf[LBUF];
01488 char* html;
01489 size_t rs;
01490 UNUSED(rs);
01491
01492 sz = file_size(fname);
01493 if (sz<=0) {
01494 sz = 0;
01495 mode = HTTP_CONNECTION_CLOSE;
01496 }
01497
01498 tcp_send(sofd, (char*)"HTTP/1.1 200 OK\r\n", 0);
01499 tcp_send(sofd, (char*)"Accept-Ranges: bytes\r\n", 0);
01500 tcp_send(sofd, (char*)"Pragma: no-cache\r\n", 0);
01501 tcp_send(sofd, (char*)"Cache-Control: no-cache\r\n", 0);
01502 memset(buf, 0, LBUF);
01503 snprintf(buf, LBUF-2, "Content-Length: %d\r\n", sz);
01504 tcp_send(sofd, buf, 0);
01505 if (mode==HTTP_CONNECTION_CLOSE) tcp_send(sofd, (char*)"Connection: Close\r\n", 0);
01506 else {
01507 tcp_send(sofd, (char*)"Keep-Alive: timeout=1800, max=100\r\n", 0);
01508 tcp_send(sofd, (char*)"Connection: Keep-Alive\r\n", 0);
01509 }
01510 tcp_send(sofd, (char*)"\r\n", 0);
01511
01512 if (sz!=0) fp = fopen(fname, "rb");
01513 else fp = NULL;
01514 if (fp==NULL) return JBXL_FILE_OPEN_ERROR;
01515
01516 html = (char*)malloc(sz);
01517 if (html==NULL) {
01518 fclose(fp);
01519 return JBXL_MALLOC_ERROR;
01520 }
01521
01522 rs = fread(html, sz, 1, fp);
01523 tcp_send(sofd, html, sz);
01524 fclose(fp);
01525
01526 free(html);
01527 return sz;
01528 }
01529
01530
01531
01532 void send_http_passwd_req(int sofd)
01533 {
01534 tcp_send(sofd, (char*)"HTTP/1.1 401 Authorization Required\r\n", 0);
01535 tcp_send(sofd, (char*)"WWW-Authenticate: Basic realm=\"TTS\"\r\n", 0);
01536 tcp_send(sofd, (char*)"Pragma: no-cache\r\n", 0);
01537 tcp_send(sofd, (char*)"Cache-Control: no-cache\r\n", 0);
01538 tcp_send(sofd, (char*)"Connection: Close\r\n", 0);
01539 tcp_send(sofd, (char*)"Content-Length: 0\r\n", 0);
01540 tcp_send(sofd, (char*)"Content-Type: text/html\r\n\r\n", 0);
01541
01542 return;
01543 }
01544