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