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