kdechunk3.c
最終更新:2009/11/8
001: /* kdechunk3.c 002: * チャンク形式データ用デコーダ 003: */ 004: 005: #define USAGE "Usage: kdechunk3 <chunk-encoded-filename> <out-filename>" 006: 007: #include "mystab.h" 008: 009: #include "myio_apr.h" 010: #include "myio_chunk.h" 011: 012: /* 013: * 文字列 s 中に最初ぶ文字 c が現れた位置へのポインタを返す関数 014: * (strchr 相当) 015: */ 016: char * mystrchr (const char *s, char c) { 017: const char *p = s; 018: if (p) 019: for (; *p; p++) 020: if (*p == c) 021: return (char*)p; 022: 023: return NULL; 024: } 025: 026: /* entity-header が "Transfer-Encoding" ヘッダの時に、 027: * ヘッダの値が "chunked" か調べるコールバック関数 028: */ 029: 030: void lookup_te_chunked ( 031: const char *line 032: , void *ctx 033: ) { 034: char *name = NULL; 035: char *value = NULL; 036: char *pos = NULL; 037: int *seen_chunked = (int*)ctx; 038: 039: if (!line || !ctx) 040: return; 041: 042: name = (char*)line; 043: 044: pos = mystrchr(line, ':'); 045: 046: if (!pos) 047: return; /* ':' が見つからなかった時は何もしない。 */ 048: 049: /* ':' の前の空白を検査していないが、本来はすべきだろう。 */ 050: 051: if (strncasecmp(name, "transfer-encoding", pos-name)) { 052: return; 053: } 054: 055: /* ':' の後の空白のスキップ */ 056: 057: pos++; 058: while(*pos && (*pos == ' ' || *pos == '\t')) 059: pos++; 060: 061: value = pos; 062: 063: if (!strcmp(value, "chunked")) { 064: *seen_chunked = 1; 065: if(0)printf("#T-E chunked found.\n"); 066: } 067: } 068: 069: 070: void *my_alloc(void *ctx, int size) { 071: apr_pool_t *pool = (apr_pool_t*)ctx; 072: apr_size_t s = (apr_size_t)size; 073: return apr_palloc(pool, s); 074: } 075: 076: int apr_my_main ( 077: int ac 078: , char **av 079: , apr_file_t * astdin 080: , apr_file_t * astdout 081: , apr_file_t * astderr 082: , apr_pool_t * pool 083: ) { 084: int error_flag = 0; 085: 086: MYIO *in = NULL; 087: MYIO *out = NULL; 088: 089: char *infilename = NULL; 090: char *outfilename = NULL; 091: 092: int chunked = 0; 093: 094: if (ac < 2) { 095: apr_file_printf(astderr, "%s\n", USAGE); 096: goto _FINALLY_; 097: } 098: 099: infilename = av[1]; 100: outfilename = av[2]; 101: 102: 103: in = MYIO_fp_open(infilename, APR_FOPEN_READ|APR_FOPEN_BINARY, APR_OS_DEFAULT, pool); 104: if (! in) { 105: apr_file_printf(astderr, "ERROR: MYIO_fp_open: %s ", infilename); 106: error_flag = 1; 107: goto _FINALLY_; 108: } 109: out = MYIO_fp_open(outfilename, 110: APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_BINARY, 111: APR_OS_DEFAULT, pool); 112: if (! out) { 113: apr_file_printf(astderr, "ERROR: MYIO_fp_open: %s ", outfilename); 114: error_flag = 1; 115: goto _FINALLY_; 116: } 117: 118: 119: /* ヘッダの読み出し。T-E が "chunked" かチェックする。 */ 120: 121: if (MYIO_read_entity_headers_CRLF_do(in, lookup_te_chunked, &chunked) == 0) { 122: apr_file_printf(astderr, "ERROR: MYIO_read_entity_headers_CRLF_do "); 123: error_flag = 1; 124: goto _FINALLY_; 125: } 126: 127: if (chunked) { 128: 129: /* チャンク形式のボディをデコード。デコード結果は標準出力とストリーム out へ */ 130: char buf[80]; 131: int nbytes=0; 132: MYIO *dc_in = NULL; 133: 134: dc_in = MYIO_dechunk_filter_new(in, my_alloc, pool); 135: 136: if (!dc_in) { 137: apr_file_printf(astderr, "ERROR: dechunk_filter "); 138: error_flag = 1; 139: goto _FINALLY_; 140: } 141: 142: while ((nbytes = MYIO_read(dc_in, buf, sizeof(buf))) > 0) { 143: apr_size_t len = nbytes; 144: apr_file_write(astdout, buf, &len); 145: MYIO_write(out, buf, nbytes); 146: } 147: 148: } 149: 150: _FINALLY_: 151: 152: if (in) { 153: MYIO_fp_close(in); 154: in = NULL; 155: } 156: 157: if (out) { 158: MYIO_fp_close(out); 159: out = NULL; 160: } 161: 162: if (error_flag) { 163: apr_file_printf(astderr, "failed.\n"); 164: return 1; /* 異常終了 */ 165: } 166: 167: apr_file_printf(astdout, "done.\n"); 168: return 0; /* 正常終了 */ 169: 170: }
KAKU PROJECT (2009) |