kmyio_htget2.c

最終更新:2009/12/19

kmyio_htget2.c

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 */
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)