kmyio_htget2.c
最終更新:2009/12/19
001: /* 002: * kmyio_htget2.c 003: * HTTP/1.1 でWebサイトに接続してファイルに保存する。 004: */ 005: 006: #define USAGE "Usage: kmtio_htget2 <uri> <out_filename>" 007: 008: #include <stdlib.h> 009: 010: #include "apr_general.h" 011: #include "apr_lib.h" 012: 013: #include "apr_errno.h" 014: #include "apr_strings.h" 015: #include "apr_uri.h" 016: #include "apr_tables.h" 017: 018: #include "mystab.h" 019: #include "myio_chunk.h" 020: #include "myio_apr.h" 021: #include "myht_util.h" 022: 023: int apr_my_main ( 024: int ac 025: , char **av 026: , apr_file_t * astdin 027: , apr_file_t * astdout 028: , apr_file_t * astderr 029: , apr_pool_t * pool 030: ) { 031: 032: int error_flag = 0; 033: apr_status_t rv = APR_SUCCESS; 034: 035: char *uri_str = NULL; 036: char *out_filename = NULL; 037: 038: apr_uri_t uri; 039: 040: char *hostname = NULL; 041: int port = 0; 042: 043: MYIO *io = NULL; 044: MYIO *out = NULL; 045: 046: apr_table_t * rsp_headers = NULL; 047: int rsp_clen = -1; 048: int chunked = 0; 049: 050: if (ac < 3) { 051: apr_file_printf(astderr, "%s\n", USAGE); 052: error_flag = 1; 053: goto _FINALLY_; 054: } 055: 056: uri_str = av[1]; 057: out_filename = av[2]; 058: 059: if (! my_uri_parse(pool, uri_str, &uri)) { 060: apr_file_printf(astderr, "ERROR: uri [%s] ", uri_str); 061: error_flag = 1; 062: goto _FINALLY_; 063: } 064: 065: hostname = uri.hostname; 066: port = uri.port; 067: 068: /* サーバへの接続 */ 069: 070: io = MYIO_sock_connect(hostname, port, pool); 071: if (!io) { 072: apr_file_printf(astderr, "ERROR: connect [%s:%d] ", hostname, port); 073: error_flag = 1; 074: goto _FINALLY_; 075: } 076: 077: /* 出力ファイルのオープン */ 078: 079: out = MYIO_fp_open(out_filename, 080: APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, 081: APR_OS_DEFAULT, pool); 082: if (!out) { 083: apr_file_printf(astderr, "ERROR: file open [%s] ", out_filename); 084: error_flag = 1; 085: goto _FINALLY_; 086: } 087: 088: /* リクエストの送信 */ 089: 090: { 091: int nbytes = 0; 092: char *req = apr_pstrcat(pool, "GET ", uri.path, " HTTP/1.1\r\n", NULL); 093: if (uri.port == 80) { 094: req = apr_pstrcat(pool, req, "Host: ", uri.hostname, "\r\n", NULL); 095: } else { 096: req = apr_pstrcat(pool, req, "Host: ", uri.hostname, ":", uri.port_str, 097: "\r\n", NULL); 098: } 099: req = apr_pstrcat(pool, req, "Accept: */*\r\n", NULL); 100: /* 101: req = apr_pstrcat(pool, req, 102: "Accept-Encoding: gzip, compress, deflate, identity\r\n", NULL); 103: req = apr_pstrcat(pool, req, "Connection: close\r\n", NULL); 104: */ 105: req = apr_pstrcat(pool, req, "User-Agent: khtget/0.1\r\n\r\n", NULL); 106: 107: nbytes = MYIO_write(io, req, strlen(req)); 108: if (nbytes <= 0) { 109: error_flag = 1; 110: goto _FINALLY_; 111: } 112: } 113: 114: /* レスポンスラインの受信 */ 115: 116: { 117: char rsp_line[1024]; 118: char *rsp_version=NULL; 119: char *status_str=NULL; 120: char *reason_phrase=NULL; 121: int ret = 0; 122: 123: if (MYIO_gets(io, rsp_line, sizeof(rsp_line)) < 0) { 124: error_flag = 1; 125: goto _FINALLY_; 126: } 127: ret = read_rsp_line(rsp_line, 128: &rsp_version, &status_str, &reason_phrase, ' '); 129: if (ret < 3) { 130: apr_file_printf(astderr, "ERROR: read_rsp_line "); 131: error_flag = 1; 132: goto _FINALLY_; 133: } 134: apr_file_printf(astdout, "[%s] [%s] [%s]\n", 135: rsp_version, status_str, reason_phrase); 136: } 137: 138: /* レスポンスヘッダの受信 */ 139: 140: rsp_headers = apr_table_make(pool, 10); 141: { 142: int ret = MYIO_read_entity_headers_CRLF_do(io, set_entity_header_to_tab, 143: rsp_headers); 144: if (! ret) { 145: apr_file_printf(astderr, "ERROR: bio_read_entity_headers_CRLF_do "); 146: error_flag = 1; 147: goto _FINALLY_; 148: } 149: } 150: 151: /* レスポンスヘッダの表示 */ 152: 153: apr_table_do(disp_tab, astdout, rsp_headers, NULL); 154: 155: /* コンテンツレングス、転送エンコーディングのチェック */ 156: { 157: char *tmp = (char*)apr_table_get(rsp_headers, "Content-Length"); 158: if (!tmp) { 159: rsp_clen = -1; 160: } else { 161: rsp_clen = atoi(tmp); 162: } 163: tmp = (char*)apr_table_get(rsp_headers, "Transfer-Encoding"); 164: if (tmp && !strcmp(tmp, "chunked")) { 165: chunked = 1; 166: } 167: } 168: 169: /* レスポンスの受信〜ファイル出力 */ 170: 171: if (chunked) { 172: int nbytes = MYIO_decode_chunked_body(io, out); 173: if (nbytes < 0) { 174: apr_file_printf(astderr, "ERROR: bio_decode_chunked_body "); 175: error_flag = 1; 176: goto _FINALLY_; 177: } 178: apr_table_set(rsp_headers, "Content-Length", apr_itoa(pool, nbytes)); 179: rsp_clen = nbytes; 180: 181: apr_table_unset(rsp_headers, "Transfer-Encoding"); 182: chunked = 0; 183: } else { 184: if (rsp_clen > 0) { 185: int nbytes = MYIO_move(io, rsp_clen, out); 186: if (nbytes != rsp_clen) { 187: apr_file_printf(astderr, "ERROR: MYIO_move "); 188: error_flag = 1; 189: goto _FINALLY_; 190: } 191: } 192: } 193: 194: _FINALLY_: 195: 196: if (out) { 197: MYIO_fp_close(out); 198: out = NULL; 199: } 200: 201: if (io) { 202: MYIO_sock_close(io); 203: io = NULL; 204: } 205: 206: if (rv != APR_SUCCESS) { 207: char error_buf[80]; 208: apr_file_printf(astderr, "ERROR: %s\n", 209: apr_strerror(rv, error_buf, sizeof(error_buf))); 210: } 211: 212: if (error_flag) { 213: apr_file_printf(astderr, "failed!\n"); 214: return 1; /* 異常終了 */ 215: } 216: 217: apr_file_printf(astdout, "\ndone.\n"); 218: 219: return 0; /* 正常終了 */ 220: 221: } /* end of main */
KAKU PROJECT (2009) |