/* * kmyio_htget.c * HTTP/1.0 でWebサイトに接続してファイルに保存する。 */ #define USAGE "Usage: kmtio_htget " #include "apr_general.h" #include "apr_lib.h" #include "apr_errno.h" #include "apr_strings.h" #include "apr_uri.h" #include "apr_tables.h" #include "mystab.h" #include "myio_chunk.h" #include "myio_apr.h" #include "myht_util.h" void * my_alloc(void *alloc_func_ctx, int alloc_size) { apr_pool_t *pool = (apr_pool_t*)alloc_func_ctx; return apr_palloc(pool, alloc_size); } int apr_my_main ( int ac , char **av , apr_file_t * astdin , apr_file_t * astdout , apr_file_t * astderr , apr_pool_t * pool ) { int error_flag = 0; apr_status_t rv = APR_SUCCESS; char *uri_str = NULL; char *out_filename = NULL; apr_uri_t uri; char *hostname = NULL; int port = 0; MYIO *io = NULL; MYIO *out = NULL; MYIO *in = NULL; apr_table_t * rsp_headers = NULL; if (ac < 3) { apr_file_printf(astderr, "%s\n", USAGE); error_flag = 1; goto _FINALLY_; } uri_str = av[1]; out_filename = av[2]; if (! my_uri_parse(pool, uri_str, &uri)) { apr_file_printf(astderr, "ERROR: uri [%s] ", uri_str); error_flag = 1; goto _FINALLY_; } hostname = uri.hostname; port = uri.port; /* サーバへの接続 */ io = MYIO_sock_connect(hostname, port, pool); if (!io) { apr_file_printf(astderr, "ERROR: connect [%s:%d] ", hostname, port); error_flag = 1; goto _FINALLY_; } /* 出力ファイルのオープン */ out = MYIO_fp_open(out_filename, APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, APR_OS_DEFAULT, pool); if (!out) { apr_file_printf(astderr, "ERROR: file open [%s] ", out_filename); error_flag = 1; goto _FINALLY_; } /* リクエストの送信 */ { int nbytes = 0; char *req = apr_pstrcat(pool, "GET ", uri.path, " HTTP/1.0\r\n", NULL); if (uri.port == 80) { req = apr_pstrcat(pool, req, "Host: ", uri.hostname, "\r\n", NULL); } else { req = apr_pstrcat(pool, req, "Host: ", uri.hostname, ":", uri.port_str, "\r\n", NULL); } req = apr_pstrcat(pool, req, "Accept: */*\r\n", NULL); /* req = apr_pstrcat(pool, req, "Accept-Encoding: gzip, compress, deflate, identity\r\n", NULL); req = apr_pstrcat(pool, req, "Connection: close\r\n", NULL); */ req = apr_pstrcat(pool, req, "User-Agent: kmyio_htget/0.1\r\n\r\n", NULL); nbytes = MYIO_write(io, req, strlen(req)); if (nbytes <= 0) { error_flag = 1; goto _FINALLY_; } } /* バッファリングフィルタ */ { in = MYIO_buf_filter_new(io, 2048, my_alloc, pool); if (!in) { apr_file_printf(astderr, "ERROR: MYIO_buf_filter_new "); error_flag = 1; goto _FINALLY_; } } /* レスポンスラインの受信 */ { char rsp_line[1024]; char *rsp_version=NULL; char *status_str=NULL; char *reason_phrase=NULL; int ret = 0; if (MYIO_gets(in, rsp_line, sizeof(rsp_line)) < 0) { error_flag = 1; goto _FINALLY_; } ret = read_rsp_line(rsp_line, &rsp_version, &status_str, &reason_phrase, ' '); if (ret < 3) { apr_file_printf(astderr, "ERROR: read_rsp_line "); error_flag = 1; goto _FINALLY_; } apr_file_printf(astdout, "[%s] [%s] [%s]\n", rsp_version, status_str, reason_phrase); } /* レスポンスヘッダの受信 */ rsp_headers = apr_table_make(pool, 10); { int ret = MYIO_read_entity_headers_CRLF_do(in, set_entity_header_to_tab, rsp_headers); if (! ret) { apr_file_printf(astderr, "ERROR: bio_read_entity_headers_CRLF_do "); error_flag = 1; goto _FINALLY_; } } /* レスポンスヘッダの表示 */ apr_table_do(disp_tab, astdout, rsp_headers, NULL); /* レスポンスの受信〜ファイル出力 */ { char buf[1024]; while (1) { int nbytes = MYIO_read(in, buf, sizeof(buf)); if (nbytes <= 0) { break; } nbytes = MYIO_write(out, buf, nbytes); if (nbytes < 0) { break; } } } _FINALLY_: if (out) { MYIO_fp_close(out); out = NULL; } if (io) { MYIO_sock_close(io); io = NULL; } if (in) { MYIO_buf_free(in, NULL, NULL); in = NULL; } if (rv != APR_SUCCESS) { char error_buf[80]; apr_file_printf(astderr, "ERROR: %s\n", apr_strerror(rv, error_buf, sizeof(error_buf))); } if (error_flag) { apr_file_printf(astderr, "failed!\n"); return 1; /* 異常終了 */ } apr_file_printf(astdout, "\ndone.\n"); return 0; /* 正常終了 */ } /* end of main */