RPC part #3
authorSteven Barth <steven@midlink.org>
Fri, 22 Aug 2008 20:04:49 +0000 (20:04 +0000)
committerSteven Barth <steven@midlink.org>
Fri, 22 Aug 2008 20:04:49 +0000 (20:04 +0000)
libs/json/Makefile [new file with mode: 0644]
libs/json/luasrc/json.lua [new file with mode: 0644]
libs/rpc/Makefile [deleted file]
libs/rpc/luasrc/Json.lua [deleted file]
libs/web/luasrc/http.lua

diff --git a/libs/json/Makefile b/libs/json/Makefile
new file mode 100644 (file)
index 0000000..f7fac77
--- /dev/null
@@ -0,0 +1,2 @@
+include ../../build/config.mk
+include ../../build/module.mk
diff --git a/libs/json/luasrc/json.lua b/libs/json/luasrc/json.lua
new file mode 100644 (file)
index 0000000..85b85e1
--- /dev/null
@@ -0,0 +1,519 @@
+--[[
+
+ JSON Encoder and Parser for Lua 5.1
+ Copyright � 2007 Shaun Brown (http://www.chipmunkav.com).
+ All Rights Reserved.
+ Permission is hereby granted, free of charge, to any person 
+ obtaining a copy of this software to deal in the Software without 
+ restriction, including without limitation the rights to use, 
+ copy, modify, merge, publish, distribute, sublicense, and/or 
+ sell copies of the Software, and to permit persons to whom the 
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be 
+ included in all copies or substantial portions of the Software.
+ If you find this software useful please give www.chipmunkav.com a mention.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Usage:
+
+ -- Lua script:
+ local t = { 
+       ["name1"] = "value1",
+       ["name2"] = {1, false, true, 23.54, "a \021 string"},
+       name3 = Json.Null() 
+ }
+
+ local json = Json.Encode (t)
+ print (json) 
+ --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
+
+ local t = Json.Decode(json)
+ print(t.name2[4])
+ --> 23.54
+ Notes:
+ 1) Encodable Lua types: string, number, boolean, table, nil
+ 2) Use Json.Null() to insert a null value into a Json object
+ 3) All control chars are encoded to \uXXXX format eg "\021" encodes to "\u0015"
+ 4) All Json \uXXXX chars are decoded to chars (0-255 byte range only)
+ 5) Json single line // and /* */ block comments are discarded during decoding
+ 6) Numerically indexed Lua arrays are encoded to Json Lists eg [1,2,3]
+ 7) Lua dictionary tables are converted to Json objects eg {"one":1,"two":2}
+ 8) Json nulls are decoded to Lua nil and treated by Lua in the normal way
+
+--]]
+
+local string = string
+local math = math
+local table = table
+local error = error
+local tonumber = tonumber
+local tostring = tostring
+local type = type
+local setmetatable = setmetatable
+local pairs = pairs
+local ipairs = ipairs
+local assert = assert
+local Chipmunk = Chipmunk
+
+module("luci.json")
+
+local StringBuilder = {
+       buffer = {}
+}
+
+function StringBuilder:New()
+       local o = {}
+       setmetatable(o, self)
+       self.__index = self
+       o.buffer = {}
+       return o
+end
+
+function StringBuilder:Append(s)
+       self.buffer[#self.buffer+1] = s
+end
+
+function StringBuilder:ToString()
+       return table.concat(self.buffer)
+end
+
+local JsonWriter = {
+       backslashes = {
+               ['\b'] = "\\b",
+               ['\t'] = "\\t", 
+               ['\n'] = "\\n", 
+               ['\f'] = "\\f",
+               ['\r'] = "\\r", 
+               ['"']  = "\\\"", 
+               ['\\'] = "\\\\", 
+               ['/']  = "\\/"
+       }
+}
+
+function JsonWriter:New()
+       local o = {}
+       o.writer = StringBuilder:New()
+       setmetatable(o, self)
+       self.__index = self
+       return o
+end
+
+function JsonWriter:Append(s)
+       self.writer:Append(s)
+end
+
+function JsonWriter:ToString()
+       return self.writer:ToString()
+end
+
+function JsonWriter:Write(o)
+       local t = type(o)
+       if t == "nil" then
+               self:WriteNil()
+       elseif t == "boolean" then
+               self:WriteString(o)
+       elseif t == "number" then
+               self:WriteString(o)
+       elseif t == "string" then
+               self:ParseString(o)
+       elseif t == "table" then
+               self:WriteTable(o)
+       elseif t == "function" then
+               self:WriteFunction(o)
+       elseif t == "thread" then
+               self:WriteError(o)
+       elseif t == "userdata" then
+               self:WriteError(o)
+       end
+end
+
+function JsonWriter:WriteNil()
+       self:Append("null")
+end
+
+function JsonWriter:WriteString(o)
+       self:Append(tostring(o))
+end
+
+function JsonWriter:ParseString(s)
+       self:Append('"')
+       self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
+               local c = self.backslashes[n]
+               if c then return c end
+               return string.format("\\u%.4X", string.byte(n))
+       end))
+       self:Append('"')
+end
+
+function JsonWriter:IsArray(t)
+       local count = 0
+       local isindex = function(k) 
+               if type(k) == "number" and k > 0 then
+                       if math.floor(k) == k then
+                               return true
+                       end
+               end
+               return false
+       end
+       for k,v in pairs(t) do
+               if not isindex(k) then
+                       return false, '{', '}'
+               else
+                       count = math.max(count, k)
+               end
+       end
+       return true, '[', ']', count
+end
+
+function JsonWriter:WriteTable(t)
+       local ba, st, et, n = self:IsArray(t)
+       self:Append(st) 
+       if ba then              
+               for i = 1, n do
+                       self:Write(t[i])
+                       if i < n then
+                               self:Append(',')
+                       end
+               end
+       else
+               local first = true;
+               for k, v in pairs(t) do
+                       if not first then
+                               self:Append(',')
+                       end
+                       first = false;                  
+                       self:ParseString(k)
+                       self:Append(':')
+                       self:Write(v)                   
+               end
+       end
+       self:Append(et)
+end
+
+function JsonWriter:WriteError(o)
+       error(string.format(
+               "Encoding of %s unsupported", 
+               tostring(o)))
+end
+
+function JsonWriter:WriteFunction(o)
+       if o == Null then 
+               self:WriteNil()
+       else
+               self:WriteError(o)
+       end
+end
+
+local StringReader = {
+       s = "",
+       i = 0
+}
+
+function StringReader:New(s)
+       local o = {}
+       setmetatable(o, self)
+       self.__index = self
+       o.s = s or o.s
+       return o        
+end
+
+function StringReader:Peek()
+       local i = self.i + 1
+       if i <= #self.s then
+               return string.sub(self.s, i, i)
+       end
+       return nil
+end
+
+function StringReader:Next()
+       self.i = self.i+1
+       if self.i <= #self.s then
+               return string.sub(self.s, self.i, self.i)
+       end
+       return nil
+end
+
+function StringReader:All()
+       return self.s
+end
+
+local JsonReader = {
+       escapes = {
+               ['t'] = '\t',
+               ['n'] = '\n',
+               ['f'] = '\f',
+               ['r'] = '\r',
+               ['b'] = '\b',
+       }
+}
+
+function JsonReader:New(s)
+       local o = {}
+       o.reader = StringReader:New(s)
+       setmetatable(o, self)
+       self.__index = self
+       return o;
+end
+
+function JsonReader:Read()
+       self:SkipWhiteSpace()
+       local peek = self:Peek()
+       if peek == nil then
+               error(string.format(
+                       "Nil string: '%s'", 
+                       self:All()))
+       elseif peek == '{' then
+               return self:ReadObject()
+       elseif peek == '[' then
+               return self:ReadArray()
+       elseif peek == '"' then
+               return self:ReadString()
+       elseif string.find(peek, "[%+%-%d]") then
+               return self:ReadNumber()
+       elseif peek == 't' then
+               return self:ReadTrue()
+       elseif peek == 'f' then
+               return self:ReadFalse()
+       elseif peek == 'n' then
+               return self:ReadNull()
+       elseif peek == '/' then
+               self:ReadComment()
+               return self:Read()
+       else
+               error(string.format(
+                       "Invalid input: '%s'", 
+                       self:All()))
+       end
+end
+               
+function JsonReader:ReadTrue()
+       self:TestReservedWord{'t','r','u','e'}
+       return true
+end
+
+function JsonReader:ReadFalse()
+       self:TestReservedWord{'f','a','l','s','e'}
+       return false
+end
+
+function JsonReader:ReadNull()
+       self:TestReservedWord{'n','u','l','l'}
+       return nil
+end
+
+function JsonReader:TestReservedWord(t)
+       for i, v in ipairs(t) do
+               if self:Next() ~= v then
+                        error(string.format(
+                               "Error reading '%s': %s", 
+                               table.concat(t), 
+                               self:All()))
+               end
+       end
+end
+
+function JsonReader:ReadNumber()
+        local result = self:Next()
+        local peek = self:Peek()
+        while peek ~= nil and string.find(
+               peek, 
+               "[%+%-%d%.eE]") do
+            result = result .. self:Next()
+            peek = self:Peek()
+       end
+       result = tonumber(result)
+       if result == nil then
+               error(string.format(
+                       "Invalid number: '%s'", 
+                       result))
+       else
+               return result
+       end
+end
+
+function JsonReader:ReadString()
+       local result = ""
+       assert(self:Next() == '"')
+        while self:Peek() ~= '"' do
+               local ch = self:Next()
+               if ch == '\\' then
+                       ch = self:Next()
+                       if self.escapes[ch] then
+                               ch = self.escapes[ch]
+                       end
+               end
+                result = result .. ch
+       end
+        assert(self:Next() == '"')
+       local fromunicode = function(m)
+               return string.char(tonumber(m, 16))
+       end
+       return string.gsub(
+               result, 
+               "u%x%x(%x%x)", 
+               fromunicode)
+end
+
+function JsonReader:ReadComment()
+        assert(self:Next() == '/')
+        local second = self:Next()
+        if second == '/' then
+            self:ReadSingleLineComment()
+        elseif second == '*' then
+            self:ReadBlockComment()
+        else
+            error(string.format(
+               "Invalid comment: %s", 
+               self:All()))
+       end
+end
+
+function JsonReader:ReadBlockComment()
+       local done = false
+       while not done do
+               local ch = self:Next()          
+               if ch == '*' and self:Peek() == '/' then
+                       done = true
+                end
+               if not done and 
+                       ch == '/' and 
+                       self:Peek() == "*" then
+                    error(string.format(
+                       "Invalid comment: %s, '/*' illegal.",  
+                       self:All()))
+               end
+       end
+       self:Next()
+end
+
+function JsonReader:ReadSingleLineComment()
+       local ch = self:Next()
+       while ch ~= '\r' and ch ~= '\n' do
+               ch = self:Next()
+       end
+end
+
+function JsonReader:ReadArray()
+       local result = {}
+       assert(self:Next() == '[')
+       self:SkipWhiteSpace()
+       local done = false
+       if self:Peek() == ']' then
+               done = true;
+       end
+       while not done do
+               local item = self:Read()
+               result[#result+1] = item
+               self:SkipWhiteSpace()
+               if self:Peek() == ']' then
+                       done = true
+               end
+               if not done then
+                       local ch = self:Next()
+                       if ch ~= ',' then
+                               error(string.format(
+                                       "Invalid array: '%s' due to: '%s'", 
+                                       self:All(), ch))
+                       end
+               end
+       end
+       assert(']' == self:Next())
+       return result
+end
+
+function JsonReader:ReadObject()
+       local result = {}
+       assert(self:Next() == '{')
+       self:SkipWhiteSpace()
+       local done = false
+       if self:Peek() == '}' then
+               done = true
+       end
+       while not done do
+               local key = self:Read()
+               if type(key) ~= "string" then
+                       error(string.format(
+                               "Invalid non-string object key: %s", 
+                               key))
+               end
+               self:SkipWhiteSpace()
+               local ch = self:Next()
+               if ch ~= ':' then
+                       error(string.format(
+                               "Invalid object: '%s' due to: '%s'", 
+                               self:All(), 
+                               ch))
+               end
+               self:SkipWhiteSpace()
+               local val = self:Read()
+               result[key] = val
+               self:SkipWhiteSpace()
+               if self:Peek() == '}' then
+                       done = true
+               end
+               if not done then
+                       ch = self:Next()
+                       if ch ~= ',' then
+                               error(string.format(
+                                       "Invalid array: '%s' near: '%s'", 
+                                       self:All(), 
+                                       ch))
+                       end
+               end
+       end
+       assert(self:Next() == "}")
+       return result
+end
+
+function JsonReader:SkipWhiteSpace()
+       local p = self:Peek()
+       while p ~= nil and string.find(p, "[%s/]") do
+               if p == '/' then
+                       self:ReadComment()
+               else
+                       self:Next()
+               end
+               p = self:Peek()
+       end
+end
+
+function JsonReader:Peek()
+       return self.reader:Peek()
+end
+
+function JsonReader:Next()
+       return self.reader:Next()
+end
+
+function JsonReader:All()
+       return self.reader:All()
+end
+
+function Encode(o)
+       local writer = JsonWriter:New()
+       writer:Write(o)
+       return writer:ToString()
+end
+
+function Decode(s)
+       local reader = JsonReader:New(s)
+       local object = reader:Read()
+       reader:SkipWhiteSpace()
+       assert(reader:Peek() == nil, "Invalid characters after JSON body")
+       return object
+end
+
+function Null()
+       return Null
+end
diff --git a/libs/rpc/Makefile b/libs/rpc/Makefile
deleted file mode 100644 (file)
index f7fac77..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-include ../../build/config.mk
-include ../../build/module.mk
diff --git a/libs/rpc/luasrc/Json.lua b/libs/rpc/luasrc/Json.lua
deleted file mode 100644 (file)
index 1dbc65c..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
---[[
-
- JSON Encoder and Parser for Lua 5.1
- Copyright © 2007 Shaun Brown (http://www.chipmunkav.com).
- All Rights Reserved.
- Permission is hereby granted, free of charge, to any person 
- obtaining a copy of this software to deal in the Software without 
- restriction, including without limitation the rights to use, 
- copy, modify, merge, publish, distribute, sublicense, and/or 
- sell copies of the Software, and to permit persons to whom the 
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be 
- included in all copies or substantial portions of the Software.
- If you find this software useful please give www.chipmunkav.com a mention.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
- ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
- Usage:
-
- -- Lua script:
- local t = { 
-       ["name1"] = "value1",
-       ["name2"] = {1, false, true, 23.54, "a \021 string"},
-       name3 = Json.Null() 
- }
-
- local json = Json.Encode (t)
- print (json) 
- --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}
-
- local t = Json.Decode(json)
- print(t.name2[4])
- --> 23.54
- Notes:
- 1) Encodable Lua types: string, number, boolean, table, nil
- 2) Use Json.Null() to insert a null value into a Json object
- 3) All control chars are encoded to \uXXXX format eg "\021" encodes to "\u0015"
- 4) All Json \uXXXX chars are decoded to chars (0-255 byte range only)
- 5) Json single line // and /* */ block comments are discarded during decoding
- 6) Numerically indexed Lua arrays are encoded to Json Lists eg [1,2,3]
- 7) Lua dictionary tables are converted to Json objects eg {"one":1,"two":2}
- 8) Json nulls are decoded to Lua nil and treated by Lua in the normal way
-
---]]
-
-local string = string
-local math = math
-local table = table
-local error = error
-local tonumber = tonumber
-local tostring = tostring
-local type = type
-local setmetatable = setmetatable
-local pairs = pairs
-local ipairs = ipairs
-local assert = assert
-local Chipmunk = Chipmunk
-
-module("Json")
-
-local StringBuilder = {
-       buffer = {}
-}
-
-function StringBuilder:New()
-       local o = {}
-       setmetatable(o, self)
-       self.__index = self
-       o.buffer = {}
-       return o
-end
-
-function StringBuilder:Append(s)
-       self.buffer[#self.buffer+1] = s
-end
-
-function StringBuilder:ToString()
-       return table.concat(self.buffer)
-end
-
-local JsonWriter = {
-       backslashes = {
-               ['\b'] = "\\b",
-               ['\t'] = "\\t", 
-               ['\n'] = "\\n", 
-               ['\f'] = "\\f",
-               ['\r'] = "\\r", 
-               ['"']  = "\\\"", 
-               ['\\'] = "\\\\", 
-               ['/']  = "\\/"
-       }
-}
-
-function JsonWriter:New()
-       local o = {}
-       o.writer = StringBuilder:New()
-       setmetatable(o, self)
-       self.__index = self
-       return o
-end
-
-function JsonWriter:Append(s)
-       self.writer:Append(s)
-end
-
-function JsonWriter:ToString()
-       return self.writer:ToString()
-end
-
-function JsonWriter:Write(o)
-       local t = type(o)
-       if t == "nil" then
-               self:WriteNil()
-       elseif t == "boolean" then
-               self:WriteString(o)
-       elseif t == "number" then
-               self:WriteString(o)
-       elseif t == "string" then
-               self:ParseString(o)
-       elseif t == "table" then
-               self:WriteTable(o)
-       elseif t == "function" then
-               self:WriteFunction(o)
-       elseif t == "thread" then
-               self:WriteError(o)
-       elseif t == "userdata" then
-               self:WriteError(o)
-       end
-end
-
-function JsonWriter:WriteNil()
-       self:Append("null")
-end
-
-function JsonWriter:WriteString(o)
-       self:Append(tostring(o))
-end
-
-function JsonWriter:ParseString(s)
-       self:Append('"')
-       self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
-               local c = self.backslashes[n]
-               if c then return c end
-               return string.format("\\u%.4X", string.byte(n))
-       end))
-       self:Append('"')
-end
-
-function JsonWriter:IsArray(t)
-       local count = 0
-       local isindex = function(k) 
-               if type(k) == "number" and k > 0 then
-                       if math.floor(k) == k then
-                               return true
-                       end
-               end
-               return false
-       end
-       for k,v in pairs(t) do
-               if not isindex(k) then
-                       return false, '{', '}'
-               else
-                       count = math.max(count, k)
-               end
-       end
-       return true, '[', ']', count
-end
-
-function JsonWriter:WriteTable(t)
-       local ba, st, et, n = self:IsArray(t)
-       self:Append(st) 
-       if ba then              
-               for i = 1, n do
-                       self:Write(t[i])
-                       if i < n then
-                               self:Append(',')
-                       end
-               end
-       else
-               local first = true;
-               for k, v in pairs(t) do
-                       if not first then
-                               self:Append(',')
-                       end
-                       first = false;                  
-                       self:ParseString(k)
-                       self:Append(':')
-                       self:Write(v)                   
-               end
-       end
-       self:Append(et)
-end
-
-function JsonWriter:WriteError(o)
-       error(string.format(
-               "Encoding of %s unsupported", 
-               tostring(o)))
-end
-
-function JsonWriter:WriteFunction(o)
-       if o == Null then 
-               self:WriteNil()
-       else
-               self:WriteError(o)
-       end
-end
-
-local StringReader = {
-       s = "",
-       i = 0
-}
-
-function StringReader:New(s)
-       local o = {}
-       setmetatable(o, self)
-       self.__index = self
-       o.s = s or o.s
-       return o        
-end
-
-function StringReader:Peek()
-       local i = self.i + 1
-       if i <= #self.s then
-               return string.sub(self.s, i, i)
-       end
-       return nil
-end
-
-function StringReader:Next()
-       self.i = self.i+1
-       if self.i <= #self.s then
-               return string.sub(self.s, self.i, self.i)
-       end
-       return nil
-end
-
-function StringReader:All()
-       return self.s
-end
-
-local JsonReader = {
-       escapes = {
-               ['t'] = '\t',
-               ['n'] = '\n',
-               ['f'] = '\f',
-               ['r'] = '\r',
-               ['b'] = '\b',
-       }
-}
-
-function JsonReader:New(s)
-       local o = {}
-       o.reader = StringReader:New(s)
-       setmetatable(o, self)
-       self.__index = self
-       return o;
-end
-
-function JsonReader:Read()
-       self:SkipWhiteSpace()
-       local peek = self:Peek()
-       if peek == nil then
-               error(string.format(
-                       "Nil string: '%s'", 
-                       self:All()))
-       elseif peek == '{' then
-               return self:ReadObject()
-       elseif peek == '[' then
-               return self:ReadArray()
-       elseif peek == '"' then
-               return self:ReadString()
-       elseif string.find(peek, "[%+%-%d]") then
-               return self:ReadNumber()
-       elseif peek == 't' then
-               return self:ReadTrue()
-       elseif peek == 'f' then
-               return self:ReadFalse()
-       elseif peek == 'n' then
-               return self:ReadNull()
-       elseif peek == '/' then
-               self:ReadComment()
-               return self:Read()
-       else
-               error(string.format(
-                       "Invalid input: '%s'", 
-                       self:All()))
-       end
-end
-               
-function JsonReader:ReadTrue()
-       self:TestReservedWord{'t','r','u','e'}
-       return true
-end
-
-function JsonReader:ReadFalse()
-       self:TestReservedWord{'f','a','l','s','e'}
-       return false
-end
-
-function JsonReader:ReadNull()
-       self:TestReservedWord{'n','u','l','l'}
-       return nil
-end
-
-function JsonReader:TestReservedWord(t)
-       for i, v in ipairs(t) do
-               if self:Next() ~= v then
-                        error(string.format(
-                               "Error reading '%s': %s", 
-                               table.concat(t), 
-                               self:All()))
-               end
-       end
-end
-
-function JsonReader:ReadNumber()
-        local result = self:Next()
-        local peek = self:Peek()
-        while peek ~= nil and string.find(
-               peek, 
-               "[%+%-%d%.eE]") do
-            result = result .. self:Next()
-            peek = self:Peek()
-       end
-       result = tonumber(result)
-       if result == nil then
-               error(string.format(
-                       "Invalid number: '%s'", 
-                       result))
-       else
-               return result
-       end
-end
-
-function JsonReader:ReadString()
-       local result = ""
-       assert(self:Next() == '"')
-        while self:Peek() ~= '"' do
-               local ch = self:Next()
-               if ch == '\\' then
-                       ch = self:Next()
-                       if self.escapes[ch] then
-                               ch = self.escapes[ch]
-                       end
-               end
-                result = result .. ch
-       end
-        assert(self:Next() == '"')
-       local fromunicode = function(m)
-               return string.char(tonumber(m, 16))
-       end
-       return string.gsub(
-               result, 
-               "u%x%x(%x%x)", 
-               fromunicode)
-end
-
-function JsonReader:ReadComment()
-        assert(self:Next() == '/')
-        local second = self:Next()
-        if second == '/' then
-            self:ReadSingleLineComment()
-        elseif second == '*' then
-            self:ReadBlockComment()
-        else
-            error(string.format(
-               "Invalid comment: %s", 
-               self:All()))
-       end
-end
-
-function JsonReader:ReadBlockComment()
-       local done = false
-       while not done do
-               local ch = self:Next()          
-               if ch == '*' and self:Peek() == '/' then
-                       done = true
-                end
-               if not done and 
-                       ch == '/' and 
-                       self:Peek() == "*" then
-                    error(string.format(
-                       "Invalid comment: %s, '/*' illegal.",  
-                       self:All()))
-               end
-       end
-       self:Next()
-end
-
-function JsonReader:ReadSingleLineComment()
-       local ch = self:Next()
-       while ch ~= '\r' and ch ~= '\n' do
-               ch = self:Next()
-       end
-end
-
-function JsonReader:ReadArray()
-       local result = {}
-       assert(self:Next() == '[')
-       self:SkipWhiteSpace()
-       local done = false
-       if self:Peek() == ']' then
-               done = true;
-       end
-       while not done do
-               local item = self:Read()
-               result[#result+1] = item
-               self:SkipWhiteSpace()
-               if self:Peek() == ']' then
-                       done = true
-               end
-               if not done then
-                       local ch = self:Next()
-                       if ch ~= ',' then
-                               error(string.format(
-                                       "Invalid array: '%s' due to: '%s'", 
-                                       self:All(), ch))
-                       end
-               end
-       end
-       assert(']' == self:Next())
-       return result
-end
-
-function JsonReader:ReadObject()
-       local result = {}
-       assert(self:Next() == '{')
-       self:SkipWhiteSpace()
-       local done = false
-       if self:Peek() == '}' then
-               done = true
-       end
-       while not done do
-               local key = self:Read()
-               if type(key) ~= "string" then
-                       error(string.format(
-                               "Invalid non-string object key: %s", 
-                               key))
-               end
-               self:SkipWhiteSpace()
-               local ch = self:Next()
-               if ch ~= ':' then
-                       error(string.format(
-                               "Invalid object: '%s' due to: '%s'", 
-                               self:All(), 
-                               ch))
-               end
-               self:SkipWhiteSpace()
-               local val = self:Read()
-               result[key] = val
-               self:SkipWhiteSpace()
-               if self:Peek() == '}' then
-                       done = true
-               end
-               if not done then
-                       ch = self:Next()
-                       if ch ~= ',' then
-                               error(string.format(
-                                       "Invalid array: '%s' near: '%s'", 
-                                       self:All(), 
-                                       ch))
-                       end
-               end
-       end
-       assert(self:Next() == "}")
-       return result
-end
-
-function JsonReader:SkipWhiteSpace()
-       local p = self:Peek()
-       while p ~= nil and string.find(p, "[%s/]") do
-               if p == '/' then
-                       self:ReadComment()
-               else
-                       self:Next()
-               end
-               p = self:Peek()
-       end
-end
-
-function JsonReader:Peek()
-       return self.reader:Peek()
-end
-
-function JsonReader:Next()
-       return self.reader:Next()
-end
-
-function JsonReader:All()
-       return self.reader:All()
-end
-
-function Encode(o)
-       local writer = JsonWriter:New()
-       writer:Write(o)
-       return writer:ToString()
-end
-
-function Decode(s)
-       local reader = JsonReader:New(s)
-       local object = reader:Read()
-       reader:SkipWhiteSpace()
-       assert(reader:Peek() == nil, "Invalid characters after JSON body")
-       return object
-end
-
-function Null()
-       return Null
-end
index 5b922d99438b14863b87b8b8901c8f6fc7e97cbe..17b27482e40c22e72471bf765b8f01dcdd6748e7 100644 (file)
@@ -81,6 +81,14 @@ function Request.formvaluetable(self, prefix)
        return vals
 end
 
        return vals
 end
 
+function Request.content(self)
+       if not self.parsed_input then
+               self:_parse_input()
+       end
+       
+       return self.message.content, self.message.content_length
+end
+
 function Request.getcookie(self, name)
   local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";")
   local p = ";" .. name .. "=(.-);"
 function Request.getcookie(self, name)
   local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";")
   local p = ";" .. name .. "=(.-);"
@@ -122,6 +130,13 @@ function close()
        end
 end
 
        end
 end
 
+--- Return the request content if the request was of unknown type.
+-- @return     HTTP request body
+-- @return     HTTP request body length
+function content()
+       return context.request:content()
+end
+
 --- Get a certain HTTP input value or a table of all input values.
 -- @param name         Name of the GET or POST variable to fetch
 -- @param noparse      Don't parse POST data before getting the value
 --- Get a certain HTTP input value or a table of all input values.
 -- @param name         Name of the GET or POST variable to fetch
 -- @param noparse      Don't parse POST data before getting the value