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) |