de106aae42f6eedd174e722e8fb515adacd75577
[project/luci.git] / libs / http / luasrc / http / protocol / filter.lua
1 --[[
2
3 HTTP protocol implementation for LuCI - filter implementation
4 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 ]]--
15
16 module("luci.http.protocol.filter", package.seeall)
17
18 local ltn12 = require("luci.ltn12")
19
20
21 -- Factory that produces a filter which normalizes chunked transfer encoding
22 function decode_chunked()
23
24         local length = 0
25         local read   = 0
26
27         return ltn12.filter.cycle(
28                 function( chunk, ctx )
29
30                         if chunk ~= nil then
31
32                                 -- EOF
33                                 if ctx == nil then
34                                         if ( length - read ) > 0 then
35                                                 return nil, "Unexpected EOF"
36                                         else
37                                                 return ""
38                                         end
39                                 end
40
41                                 chunk = ctx .. chunk
42
43                                 local buf = ""
44                                 while true do
45
46                                         if read == length then
47
48                                                 -- Find chunk length indicator
49                                                 local spos, epos = chunk:find("^\r?\n?[a-fA-F0-9]+ *\r\n")
50                                                 if spos and spos == 1 then
51                                                         read   = 0
52                                                         length = tonumber(
53                                                                 chunk:sub( 1, epos ):gsub( "[^a-fA-F0-9]", "" ), 16
54                                                         )
55
56                                                         -- Check for end of chunk
57                                                         if length > 0 then
58                                                                 chunk = chunk:sub( epos + 1, #chunk )
59                                                         else
60                                                                 return buf, ""
61                                                         end
62                                                 else
63                                                         return "", nil
64                                                 end
65                                         else
66                                                 if ( read + #chunk ) <= length then
67                                                         read = read + #chunk
68                                                         return buf .. chunk, ""
69                                                 else
70                                                         local rest = length - read
71                                                         read  = read + rest
72                                                         buf   = buf .. chunk:sub( 1, rest )
73                                                         chunk = chunk:sub( rest + 1, #chunk )
74                                                 end
75                                         end
76                                 end
77                         end
78                 end,
79                 ""
80         )
81 end