kdechunk3.c

最終更新:2009/11/8

kdechunk3.c

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: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)