~ubuntu-branches/ubuntu/quantal/nginx/quantal-updates

« back to all changes in this revision

Viewing changes to debian/modules/chunkin-nginx-module/src/chunked_parser.rl

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry, Kartik Mistry
  • Date: 2011-09-26 10:17:04 UTC
  • mfrom: (4.2.38 sid)
  • Revision ID: package-import@ubuntu.com-20110926101704-x8pxngiujrmkxnn3
Tags: 1.1.4-2
[Kartik Mistry]
* debian/modules:
  + Updated nginx-upload-progress module, Thanks to upstream for fixing issue
    that FTBFS nginx on kFreeBSD-* archs.
  + Updated nginx-lua module to latest upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) agentzh */
 
2
 
 
3
#define EXTENDED_DEBUG 1
 
4
#define DDEBUG 0
 
5
 
 
6
#include "ddebug.h"
 
7
 
 
8
#include "chunked_parser.h"
 
9
#include "ngx_http_chunkin_util.h"
 
10
 
 
11
#define ngx_chunkin_min(x, y) ((x) < (y) ? (x) : (y))
 
12
 
 
13
enum {
 
14
    PRE_TEXT_LEN = 25,
 
15
    POST_TEXT_LEN = 25
 
16
};
 
17
 
 
18
%% machine chunked;
 
19
%% write data;
 
20
 
 
21
 
 
22
ngx_int_t
 
23
ngx_http_chunkin_init_chunked_parser(ngx_http_request_t *r,
 
24
        ngx_http_chunkin_ctx_t *ctx)
 
25
{
 
26
    int cs;
 
27
 
 
28
    %% write init;
 
29
 
 
30
    ctx->chunks = NULL;
 
31
    ctx->next_chunk = NULL;
 
32
    ctx->chunk = NULL;
 
33
    ctx->chunk_size = 0;
 
34
    ctx->chunk_size_order = 0;
 
35
    ctx->chunk_bytes_read = 0;
 
36
 
 
37
    ctx->chunks_total_size = 0;
 
38
 
 
39
    ctx->parser_state = cs;
 
40
 
 
41
    return NGX_OK;
 
42
}
 
43
 
 
44
 
 
45
ngx_int_t
 
46
ngx_http_chunkin_run_chunked_parser(ngx_http_request_t *r,
 
47
        ngx_http_chunkin_ctx_t *ctx, u_char **pos_addr, u_char *last, char *caller_info)
 
48
{
 
49
    int                 cs   = ctx->parser_state;
 
50
    ngx_connection_t    *c   = r->connection;
 
51
    char                *pos = (char *) *pos_addr;
 
52
    char                *p   = (char *) *pos_addr;
 
53
    char                *pe  = (char *) last;
 
54
    char                *eof = NULL;
 
55
    ngx_buf_t           *b;
 
56
    ngx_flag_t          done = 0;
 
57
    ngx_str_t           pre, post;
 
58
    char*               err_ctx = "";
 
59
    ngx_str_t           user_agent = ngx_null_string;
 
60
    ssize_t             rest;
 
61
 
 
62
    %%{
 
63
        #alphtype unsigned char;
 
64
 
 
65
        action finalize {
 
66
            done = 1;
 
67
        }
 
68
 
 
69
        action test_len {
 
70
            ctx->chunk_bytes_read < ctx->chunk_size
 
71
        }
 
72
 
 
73
        action read_data_byte {
 
74
            /* optimization for buffered chunk data */
 
75
 
 
76
            rest = ngx_chunkin_min(
 
77
                (ssize_t)ctx->chunk_size - (ssize_t)ctx->chunk_bytes_read,
 
78
                (ssize_t)(pe - p));
 
79
 
 
80
            dd("moving %d, chunk size %d, read %d, rest %d",
 
81
                (int)rest,
 
82
                (int)ctx->chunk_size,
 
83
                (int)ctx->chunk_bytes_read,
 
84
                (int)rest);
 
85
 
 
86
            ctx->chunk_bytes_read += rest;
 
87
            p += rest - 1;
 
88
            ctx->chunk->buf->last = (u_char *)p + 1;
 
89
            ctx->chunks_total_size += rest;
 
90
 
 
91
            /* dd("bytes read: %d (char '%c', bytes read %d, chunk size %d)", ctx->chunk->buf->last - ctx->chunk->buf->pos, *p, ctx->chunk_bytes_read, ctx->chunk_size); */
 
92
            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
93
                    "chunkin: data bytes read: %uz (char: \"%c\")\n",
 
94
                    ctx->chunk_bytes_read, *p);
 
95
        }
 
96
 
 
97
        action start_reading_size {
 
98
            ctx->chunk_bytes_read = 0;
 
99
            ctx->chunk_size = 0;
 
100
            ctx->chunk_size_order = 0;
 
101
        }
 
102
 
 
103
        action read_size {
 
104
            ctx->chunk_size <<= 4;
 
105
            ctx->chunk_size_order++;
 
106
            if (*p >= 'A' && *p <= 'F') {
 
107
                ctx->chunk_size |= 10 + *p - 'A';
 
108
            } else if (*p >= 'a' && *p <= 'f') {
 
109
                ctx->chunk_size |= 10 + *p - 'a';
 
110
            } else {
 
111
                ctx->chunk_size |= *p - '0';
 
112
            }
 
113
 
 
114
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
115
                    "chunkin: chunk size: %uz\n", ctx->chunk_size);
 
116
        }
 
117
 
 
118
        action start_reading_data {
 
119
            ctx->chunk = ngx_http_chunkin_get_buf(r->pool, ctx);
 
120
 
 
121
            ctx->chunks_count++;
 
122
 
 
123
            if (ctx->chunks) {
 
124
                *ctx->next_chunk = ctx->chunk;
 
125
            } else {
 
126
                ctx->chunks = ctx->chunk;
 
127
            }
 
128
 
 
129
            ctx->next_chunk = &ctx->chunk->next;
 
130
 
 
131
            b = ctx->chunk->buf;
 
132
 
 
133
            b->last = b->pos = (u_char *) p;
 
134
            b->memory = 1;
 
135
        }
 
136
 
 
137
        action verify_data {
 
138
            if (ctx->chunk_bytes_read != ctx->chunk_size) {
 
139
                ngx_log_error(NGX_LOG_ERR, c->log, 0,
 
140
                        "ERROR: chunk size not met: "
 
141
                        "%uz != %uz\n", ctx->chunk_bytes_read,
 
142
                        ctx->chunk_size);
 
143
                *pos_addr = (u_char*) p;
 
144
                ctx->parser_state = chunked_error;
 
145
                return NGX_ERROR;
 
146
            }
 
147
 
 
148
            if (ctx->chunk_size == 0) {
 
149
                /* remove the current chunk */
 
150
                ctx->chunk->next = ctx->free_bufs;
 
151
                ctx->free_bufs = ctx->chunk;
 
152
                ctx->chunk = ctx->last_complete_chunk;
 
153
                if (ctx->last_complete_chunk) {
 
154
                    ctx->last_complete_chunk->next = NULL;
 
155
                } else {
 
156
                    ctx->chunks = NULL;
 
157
                }
 
158
            } else {
 
159
                ctx->last_complete_chunk = ctx->chunk;
 
160
            }
 
161
        }
 
162
 
 
163
        CR = "\r";
 
164
 
 
165
        LF = "\n";
 
166
 
 
167
        CRLF = CR LF $err{ err_ctx = "CRLF"; };
 
168
 
 
169
        chunk_size = (xdigit+ - "0"+) >start_reading_size $read_size;
 
170
 
 
171
        chunk_data_octet = any when test_len;
 
172
 
 
173
        chunk_data = (chunk_data_octet+)
 
174
                     >start_reading_data
 
175
                     $read_data_byte
 
176
                     $err{ err_ctx = "chunk_data"; }
 
177
                   ;
 
178
 
 
179
        chunk_data_terminator = CR when ! test_len LF
 
180
                                $err{ err_ctx = "chunk_data_terminator"; }
 
181
                              ;
 
182
 
 
183
        SP = ' ';
 
184
        HT = '\t';
 
185
 
 
186
        LWS = CRLF ? ( SP | HT )+;
 
187
 
 
188
        separator = "(" | ")" | "<" | ">" | "@"
 
189
                  | "," | ";" | ":" | "\\" | ["]
 
190
                  | "/" | "[" | "]" | "?" | "="
 
191
                  | "{" | "}" | SP | HT
 
192
                  ;
 
193
 
 
194
        CTL = 0..31 | 127;
 
195
 
 
196
        token = (any -- (CTL | separator))+;
 
197
 
 
198
        chunk_ext_name = token;
 
199
 
 
200
        TEXT = (any -- CTL) | LWS;
 
201
 
 
202
        qdtext = TEXT -- ["];
 
203
 
 
204
        CHAR = 0..127;
 
205
 
 
206
        quoted_pair = "\\" CHAR;
 
207
 
 
208
        quoted_string = ["] ( qdtext | quoted_pair )* ["];
 
209
 
 
210
        chunk_ext_val = token | quoted_string;
 
211
 
 
212
        chunk_extension = ( ";" LWS* chunk_ext_name LWS*
 
213
                            ("=" LWS* chunk_ext_val LWS*) ? )*
 
214
                        ;
 
215
 
 
216
        chunk = chunk_size (LWS* -- CRLF)
 
217
                    $err{ err_ctx = "chunk_size"; }
 
218
                    (chunk_extension -- CRLF) ?
 
219
                    CRLF
 
220
                    $err{ err_ctx = "chunk_ext"; }
 
221
                        chunk_data chunk_data_terminator
 
222
                        @verify_data;
 
223
 
 
224
        last_chunk = "0"+ (LWS* -- CRLF)
 
225
                      (chunk_extension -- CRLF) ?
 
226
                      CRLF $err{ err_ctx = "last_chunk"; }
 
227
                   ;
 
228
 
 
229
        parser = chunk* last_chunk CRLF
 
230
                 $err{ err_ctx = "parser"; }
 
231
               ;
 
232
 
 
233
        main := parser @finalize;
 
234
 
 
235
    }%%
 
236
 
 
237
    %% write exec;
 
238
 
 
239
    ctx->parser_state = cs;
 
240
 
 
241
    *pos_addr = (u_char *) p;
 
242
 
 
243
    if (p != pe) {
 
244
        dd("ASSERTION FAILED: p != pe");
 
245
    }
 
246
 
 
247
    if (done) {
 
248
        return NGX_OK;
 
249
    }
 
250
 
 
251
    if (cs == chunked_error) {
 
252
 
 
253
#if EXTENDED_DEBUG
 
254
 
 
255
        ngx_str_t           headers_buf, preread_buf;
 
256
 
 
257
#endif
 
258
 
 
259
        for (post.data = (u_char *) p, post.len = 0;
 
260
                post.data + post.len != (u_char *) pe; post.len++)
 
261
        {
 
262
            if (post.len >= POST_TEXT_LEN) {
 
263
                break;
 
264
            }
 
265
        }
 
266
 
 
267
        for (pre.data = (u_char *) p, pre.len = 0;
 
268
                pre.data != (u_char *) pos; pre.data--, pre.len++)
 
269
        {
 
270
            if (pre.len >= PRE_TEXT_LEN) {
 
271
                break;
 
272
            }
 
273
        }
 
274
 
 
275
        if (r->headers_in.user_agent) {
 
276
            user_agent = r->headers_in.user_agent->value;
 
277
        }
 
278
 
 
279
#if EXTENDED_DEBUG
 
280
 
 
281
        headers_buf.data = r->header_in->start;
 
282
        headers_buf.len = ctx->saved_header_in_pos - r->header_in->start;
 
283
 
 
284
        if (strcmp(caller_info, "preread") == 0) {
 
285
            preread_buf.data = (u_char *) pos;
 
286
            preread_buf.len = pe - pos;
 
287
 
 
288
        } else {
 
289
            preread_buf.data = ctx->saved_header_in_pos;
 
290
            preread_buf.len = r->header_in->pos - ctx->saved_header_in_pos;
 
291
        }
 
292
 
 
293
#endif
 
294
 
 
295
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
 
296
                "bad chunked body (buf size %O, buf offset %O, "
 
297
                "total decoded %uz, chunks count %d, "
 
298
                "chunk size %uz, chunk data read %uz, "
 
299
                "total to disk %uz, "
 
300
                "raw body size %O, caller \"%s\", "
 
301
                "plain_http %d, "
 
302
 
 
303
#if (NGX_HTTP_SSL)
 
304
 
 
305
                "ssl %d, "
 
306
#endif
 
307
 
 
308
                "keepalive %d, err ctx \"%s\", "
 
309
                "ctx ref count %ud, user agent \"%V\", "
 
310
 
 
311
#if EXTENDED_DEBUG
 
312
 
 
313
                "headers \"%V\", preread \"%V\", "
 
314
 
 
315
#endif
 
316
 
 
317
                "at char '%c' (%d), "
 
318
                "near \"%V <-- HERE %V\", marked by \" <-- HERE \").\n",
 
319
                (off_t) (pe - pos), (off_t) (p - pos),
 
320
                ctx->chunks_total_size, ctx->chunks_count,
 
321
                ctx->chunk_size, ctx->chunk_bytes_read,
 
322
                ctx->chunks_written_size,
 
323
                (off_t) ctx->raw_body_size, caller_info,
 
324
                (int) r->plain_http,
 
325
 
 
326
#if (NGX_HTTP_SSL)
 
327
 
 
328
                r->connection->ssl ? 1 : 0,
 
329
 
 
330
#endif
 
331
 
 
332
                (int) r->keepalive, err_ctx,
 
333
                ctx->count, &user_agent,
 
334
 
 
335
#if EXTENDED_DEBUG
 
336
 
 
337
                &headers_buf, &preread_buf,
 
338
 
 
339
#endif
 
340
 
 
341
                *p, *p,
 
342
                &pre, &post);
 
343
 
 
344
        return NGX_ERROR;
 
345
    }
 
346
 
 
347
    return NGX_AGAIN;
 
348
}
 
349