kmyio_htget.c

最終更新:2009/12/19

kmyio_htget.c

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