kdechunk2.c

最終更新:2009/11/7

kdechunk2.c

001: /* kdechunk2.c
002:  * チャンク形式データ用デコーダ
003:  */
004: 
005: #define USAGE "Usage: kdechunk2 <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: int apr_my_main (
071:   int ac
072:   , char **av
073:   , apr_file_t * astdin
074:   , apr_file_t * astdout
075:   , apr_file_t * astderr
076:   , apr_pool_t * pool
077: ) {
078:   int error_flag = 0;
079: 
080:   MYIO *in = NULL;
081:   MYIO *out = NULL;
082:   
083:   char *infilename = NULL;
084:   char *outfilename = NULL;
085: 
086:   int chunked = 0;
087: 
088:   if (ac < 2) {
089:     apr_file_printf(astderr, "%s\n", USAGE);
090:     goto _FINALLY_;
091:   }
092: 
093:   infilename = av[1];
094:   outfilename = av[2];
095: 
096: 
097:   in = MYIO_fp_open(infilename, APR_FOPEN_READ|APR_FOPEN_BINARY, APR_OS_DEFAULT, pool);
098:   if (! in) {
099:     apr_file_printf(astderr, "ERROR: MYIO_fp_open: %s ", infilename);
100:     error_flag = 1;
101:     goto _FINALLY_;
102:   }
103:   out = MYIO_fp_open(outfilename, 
104:         APR_FOPEN_WRITE|APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_BINARY,
105:           APR_OS_DEFAULT, pool);
106:   if (! out) {
107:     apr_file_printf(astderr, "ERROR: MYIO_fp_open: %s ", outfilename);
108:     error_flag = 1;
109:     goto _FINALLY_;
110:   }
111: 
112: 
113:   /* ヘッダの読み出し。T-E が "chunked" かチェックする。 */
114: 
115:   if (MYIO_read_entity_headers_CRLF_do(in, lookup_te_chunked, &chunked) == 0) {
116:     apr_file_printf(astderr, "ERROR: MYIO_read_entity_headers_CRLF_do ");
117:     error_flag = 1;
118:     goto _FINALLY_;
119:   }
120:   
121:   if (chunked) {
122: 
123:     /* チャンク形式のボディをデコード。デコード結果はストリーム out へ */
124: 
125:     if (MYIO_decode_chunked_body (in, out) < 0) {
126:       apr_file_printf(astderr, "ERROR: MYIO_decode_chunked_body ");
127:       error_flag = 1;
128:       goto _FINALLY_;
129:     }
130: 
131:   }
132: 
133:   _FINALLY_:
134: 
135:   if (in) {
136:     MYIO_fp_close(in);
137:     in = NULL;
138:   }
139: 
140:   if (out) {
141:     MYIO_fp_close(out);
142:     out = NULL;
143:   }
144: 
145:   if (error_flag) {
146:     apr_file_printf(astderr, "failed.\n");
147:     return 1; /* 異常終了 */
148:   }
149:   
150:   apr_file_printf(astdout, "done.\n");
151:   return 0; /* 正常終了 */
152:   
153: }
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)