webmcp
annotate libraries/rocketcgi/rocketcgi.lua @ 1:985024b16520
Version 1.0.1
New feature: JSON requests
Changes in ui.paginate: Current page setting is directly fetched from CGI params, instead of view params
Changed behavior of load methods of atom library to accept nil as input
Bugfixes in mondelefant_atom_connector timestamp(tz) loaders
Added global constant _WEBMCP_VERSION containing a version string
New feature: JSON requests
Changes in ui.paginate: Current page setting is directly fetched from CGI params, instead of view params
Changed behavior of load methods of atom library to accept nil as input
Bugfixes in mondelefant_atom_connector timestamp(tz) loaders
Added global constant _WEBMCP_VERSION containing a version string
author | jbe |
---|---|
date | Tue Nov 17 12:00:00 2009 +0100 (2009-11-17) |
parents | 9fdfb27f8e67 |
children | 72860d232f32 |
rev | line source |
---|---|
jbe/bsw@0 | 1 #!/usr/bin/env lua |
jbe/bsw@0 | 2 |
jbe/bsw@0 | 3 local assert = assert |
jbe/bsw@0 | 4 local error = error |
jbe/bsw@0 | 5 local getfenv = getfenv |
jbe/bsw@0 | 6 local getmetatable = getmetatable |
jbe/bsw@0 | 7 local ipairs = ipairs |
jbe/bsw@0 | 8 local next = next |
jbe/bsw@0 | 9 local pairs = pairs |
jbe/bsw@0 | 10 local pcall = pcall |
jbe/bsw@0 | 11 local print = print |
jbe/bsw@0 | 12 local rawequal = rawequal |
jbe/bsw@0 | 13 local rawget = rawget |
jbe/bsw@0 | 14 local rawset = rawset |
jbe/bsw@0 | 15 local select = select |
jbe/bsw@0 | 16 local setfenv = setfenv |
jbe/bsw@0 | 17 local setmetatable = setmetatable |
jbe/bsw@0 | 18 local tonumber = tonumber |
jbe/bsw@0 | 19 local tostring = tostring |
jbe/bsw@0 | 20 local type = type |
jbe/bsw@0 | 21 local unpack = unpack |
jbe/bsw@0 | 22 local xpcall = xpcall |
jbe/bsw@0 | 23 |
jbe/bsw@0 | 24 local io = io |
jbe/bsw@0 | 25 local math = math |
jbe/bsw@0 | 26 local os = os |
jbe/bsw@0 | 27 local string = string |
jbe/bsw@0 | 28 local table = table |
jbe/bsw@0 | 29 |
jbe/bsw@0 | 30 module(...) |
jbe/bsw@0 | 31 |
jbe/bsw@0 | 32 data_sent = false |
jbe/bsw@0 | 33 |
jbe/bsw@0 | 34 function add_header(...) |
jbe/bsw@0 | 35 if data_sent then |
jbe/bsw@0 | 36 error("Can not add header after data has been sent.", 2) |
jbe/bsw@0 | 37 end |
jbe/bsw@0 | 38 io.stdout:write(...) |
jbe/bsw@0 | 39 io.stdout:write("\r\n") |
jbe/bsw@0 | 40 end |
jbe/bsw@0 | 41 |
jbe/bsw@0 | 42 function send_data(...) |
jbe/bsw@0 | 43 if not data_sent then |
jbe/bsw@0 | 44 io.stdout:write("\r\n") |
jbe/bsw@0 | 45 data_sent = true |
jbe/bsw@0 | 46 end |
jbe/bsw@0 | 47 io.stdout:write(...) |
jbe/bsw@0 | 48 end |
jbe/bsw@0 | 49 |
jbe/bsw@0 | 50 function set_status(status) |
jbe/bsw@0 | 51 add_header("Status: ", status) |
jbe/bsw@0 | 52 end |
jbe/bsw@0 | 53 |
jbe/bsw@0 | 54 function redirect(location) |
jbe/bsw@0 | 55 set_status("303 See Other") |
jbe/bsw@0 | 56 add_header("Location: ", location) |
jbe/bsw@0 | 57 end |
jbe/bsw@0 | 58 |
jbe/bsw@0 | 59 function set_content_type(content_type) |
jbe/bsw@0 | 60 add_header("Content-Type: ", content_type) |
jbe/bsw@0 | 61 end |
jbe/bsw@0 | 62 |
jbe/bsw@0 | 63 method = os.getenv("REQUEST_METHOD") or false |
jbe/bsw@0 | 64 query = os.getenv("QUERY_STRING") or false |
jbe/bsw@0 | 65 cookie_data = os.getenv("HTTP_COOKIE") or false |
jbe/bsw@0 | 66 post_data = io.stdin:read("*a") or false |
jbe/bsw@0 | 67 post_contenttype = os.getenv("CONTENT_TYPE") or false |
jbe/bsw@0 | 68 params = {} |
jbe/bsw@0 | 69 get_params = {} |
jbe/bsw@0 | 70 cookies = {} |
jbe/bsw@0 | 71 post_params = {} |
jbe/bsw@0 | 72 post_filenames = {} |
jbe/bsw@0 | 73 post_types = {} |
jbe/bsw@0 | 74 |
jbe/bsw@0 | 75 local urldecode |
jbe/bsw@0 | 76 do |
jbe/bsw@0 | 77 local b0 = string.byte("0") |
jbe/bsw@0 | 78 local b9 = string.byte("9") |
jbe/bsw@0 | 79 local bA = string.byte("A") |
jbe/bsw@0 | 80 local bF = string.byte("F") |
jbe/bsw@0 | 81 local ba = string.byte("a") |
jbe/bsw@0 | 82 local bf = string.byte("f") |
jbe/bsw@0 | 83 function urldecode(str) |
jbe/bsw@0 | 84 return ( |
jbe/bsw@0 | 85 string.gsub( |
jbe/bsw@0 | 86 string.gsub(str, "%+", " "), |
jbe/bsw@0 | 87 "%%([0-9A-Fa-f][0-9A-Fa-f])", |
jbe/bsw@0 | 88 function(hex) |
jbe/bsw@0 | 89 local n1, n2 = string.byte(hex, 1, 2) |
jbe/bsw@0 | 90 if n1 >= b0 and n1 <= b9 then n1 = n1 - b0 |
jbe/bsw@0 | 91 elseif n1 >= bA and n1 <= bF then n1 = n1 - bA + 10 |
jbe/bsw@0 | 92 elseif n1 >= ba and n1 <= bf then n1 = n1 - ba + 10 |
jbe/bsw@0 | 93 else return end |
jbe/bsw@0 | 94 if n2 >= b0 and n2 <= b9 then n2 = n2 - b0 |
jbe/bsw@0 | 95 elseif n2 >= bA and n2 <= bF then n2 = n2 - bA + 10 |
jbe/bsw@0 | 96 elseif n2 >= ba and n2 <= bf then n2 = n2 - ba + 10 |
jbe/bsw@0 | 97 else return end |
jbe/bsw@0 | 98 return string.char(n1 * 16 + n2) |
jbe/bsw@0 | 99 end |
jbe/bsw@0 | 100 ) |
jbe/bsw@0 | 101 ) |
jbe/bsw@0 | 102 end |
jbe/bsw@0 | 103 end |
jbe/bsw@0 | 104 |
jbe/bsw@0 | 105 local function proc_param(tbl, key, value) |
jbe/bsw@0 | 106 if string.find(key, "%[%]$") then |
jbe/bsw@0 | 107 if tbl[key] then |
jbe/bsw@0 | 108 table.insert(tbl[key], value) |
jbe/bsw@0 | 109 else |
jbe/bsw@0 | 110 local list = { value } |
jbe/bsw@0 | 111 params[key] = list |
jbe/bsw@0 | 112 tbl[key] = list |
jbe/bsw@0 | 113 end |
jbe/bsw@0 | 114 else |
jbe/bsw@0 | 115 params[key] = value |
jbe/bsw@0 | 116 tbl[key] = value |
jbe/bsw@0 | 117 end |
jbe/bsw@0 | 118 end |
jbe/bsw@0 | 119 |
jbe/bsw@0 | 120 local function read_urlencoded_form(tbl, data) |
jbe/bsw@0 | 121 for rawkey, rawvalue in string.gmatch(data, "([^=&]*)=([^=&]*)") do |
jbe/bsw@0 | 122 proc_param(tbl, urldecode(rawkey), urldecode(rawvalue)) |
jbe/bsw@0 | 123 end |
jbe/bsw@0 | 124 end |
jbe/bsw@0 | 125 |
jbe/bsw@0 | 126 if query then |
jbe/bsw@0 | 127 read_urlencoded_form(get_params, query) |
jbe/bsw@0 | 128 end |
jbe/bsw@0 | 129 |
jbe/bsw@0 | 130 if cookie_data then |
jbe/bsw@0 | 131 for rawkey, rawvalue in string.gmatch(cookie_data, "([^=; ]*)=([^=; ]*)") do |
jbe/bsw@0 | 132 cookies[urldecode(rawkey)] = urldecode(rawvalue) |
jbe/bsw@0 | 133 end |
jbe/bsw@0 | 134 end |
jbe/bsw@0 | 135 |
jbe/bsw@0 | 136 if post_contenttype == "application/x-www-form-urlencoded" then |
jbe/bsw@0 | 137 read_urlencoded_form(post_params, post_data) |
jbe/bsw@0 | 138 elseif post_contenttype then |
jbe/bsw@0 | 139 local boundary = string.match( |
jbe/bsw@0 | 140 post_contenttype, |
jbe/bsw@0 | 141 '^multipart/form%-data[ \t]*;[ \t]*boundary="([^"]+)"' |
jbe/bsw@0 | 142 ) or string.match( |
jbe/bsw@0 | 143 post_contenttype, |
jbe/bsw@0 | 144 '^multipart/form%-data[ \t]*;[ \t]*boundary=([^"; \t]+)' |
jbe/bsw@0 | 145 ) |
jbe/bsw@0 | 146 if boundary then |
jbe/bsw@0 | 147 local parts = {} |
jbe/bsw@0 | 148 do |
jbe/bsw@0 | 149 local boundary = "\r\n--" .. boundary |
jbe/bsw@0 | 150 local post_data = "\r\n" .. post_data |
jbe/bsw@0 | 151 local pos1, pos2 = string.find(post_data, boundary, 1, true) |
jbe/bsw@0 | 152 while true do |
jbe/bsw@0 | 153 local ind = string.sub(post_data, pos2 + 1, pos2 + 2) |
jbe/bsw@0 | 154 if ind == "\r\n" then |
jbe/bsw@0 | 155 local pos3, pos4 = string.find(post_data, boundary, pos2 + 1, true) |
jbe/bsw@0 | 156 if pos3 then |
jbe/bsw@0 | 157 parts[#parts + 1] = string.sub(post_data, pos2 + 3, pos3 - 1) |
jbe/bsw@0 | 158 else |
jbe/bsw@0 | 159 error("Illegal POST data.") |
jbe/bsw@0 | 160 end |
jbe/bsw@0 | 161 pos1, pos2 = pos3, pos4 |
jbe/bsw@0 | 162 elseif ind == "--" then |
jbe/bsw@0 | 163 break |
jbe/bsw@0 | 164 else |
jbe/bsw@0 | 165 error("Illegal POST data.") |
jbe/bsw@0 | 166 end |
jbe/bsw@0 | 167 end |
jbe/bsw@0 | 168 end |
jbe/bsw@0 | 169 for i, part in ipairs(parts) do |
jbe/bsw@0 | 170 local pos = 1 |
jbe/bsw@0 | 171 local name, filename, contenttype |
jbe/bsw@0 | 172 while true do |
jbe/bsw@0 | 173 local header |
jbe/bsw@0 | 174 do |
jbe/bsw@0 | 175 local oldpos = pos |
jbe/bsw@0 | 176 pos = string.find(part, "\r\n", oldpos, true) |
jbe/bsw@0 | 177 if not pos then |
jbe/bsw@0 | 178 error("Illegal POST data.") |
jbe/bsw@0 | 179 end |
jbe/bsw@0 | 180 if pos == oldpos then break end |
jbe/bsw@0 | 181 header = string.sub(part, oldpos, pos - 1) |
jbe/bsw@0 | 182 pos = pos + 2 |
jbe/bsw@0 | 183 end |
jbe/bsw@0 | 184 if string.find( |
jbe/bsw@0 | 185 string.lower(header), |
jbe/bsw@0 | 186 "^content%-disposition:[ \t]*form%-data[ \t]*;" |
jbe/bsw@0 | 187 ) then |
jbe/bsw@0 | 188 -- TODO: handle all cases correctly |
jbe/bsw@0 | 189 name = string.match(header, ';[ \t]*name="([^"]*)"') or |
jbe/bsw@0 | 190 string.match(header, ';[ \t]*name=([^"; \t]+)') |
jbe/bsw@0 | 191 filename = string.match(header, ';[ \t]*filename="([^"]*)"') or |
jbe/bsw@0 | 192 string.match(header, ';[ \t]*filename=([^"; \t]+)') |
jbe/bsw@0 | 193 else |
jbe/bsw@0 | 194 local dummy, subpos = string.find( |
jbe/bsw@0 | 195 string.lower(header), |
jbe/bsw@0 | 196 "^content%-type:[ \t]*" |
jbe/bsw@0 | 197 ) |
jbe/bsw@0 | 198 if subpos then |
jbe/bsw@0 | 199 contenttype = string.sub(header, subpos + 1, #header) |
jbe/bsw@0 | 200 end |
jbe/bsw@0 | 201 end |
jbe/bsw@0 | 202 end |
jbe/bsw@0 | 203 local content = string.sub(part, pos + 2, #part) |
jbe/bsw@0 | 204 if not name then |
jbe/bsw@0 | 205 error("Illegal POST data.") |
jbe/bsw@0 | 206 end |
jbe/bsw@0 | 207 proc_param(post_params, name, content) |
jbe/bsw@0 | 208 post_filenames[name] = filename |
jbe/bsw@0 | 209 post_types[name] = contenttype |
jbe/bsw@0 | 210 end |
jbe/bsw@0 | 211 end |
jbe/bsw@0 | 212 end |
jbe/bsw@0 | 213 |
jbe/bsw@0 | 214 if post_data and #post_data > 262144 then |
jbe/bsw@0 | 215 post_data = nil |
jbe/bsw@0 | 216 collectgarbage("collect") |
jbe/bsw@0 | 217 else |
jbe/bsw@0 | 218 post_data = nil |
jbe/bsw@0 | 219 end |