2013-04-04 10:18:08 +02:00
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- Utility functions for encoding/decoding of URLs.
|
|
|
|
--
|
|
|
|
-- @release $Id: urlcode.lua,v 1.10 2008/01/21 16:11:32 carregal Exp $
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
local ipairs, next, pairs, tonumber, type = ipairs, next, pairs, tonumber, type
|
|
|
|
local string = require"string"
|
|
|
|
local gsub = string.gsub
|
|
|
|
local strbyte, strchar, strformat, strsub = string.byte, string.char, string.format, string.sub
|
|
|
|
local tinsert = require"table".insert
|
|
|
|
|
|
|
|
--module ("cgilua.urlcode")
|
|
|
|
local _M = {}
|
|
|
|
|
|
|
|
-- Converts an hexadecimal code in the form %XX to a character
|
|
|
|
local function hexcode2char (h)
|
2013-09-20 23:38:20 +02:00
|
|
|
return strchar(tonumber(h,16))
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- Decode an URL-encoded string (see RFC 2396)
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.unescape (str)
|
2013-09-20 23:38:20 +02:00
|
|
|
str = gsub (str, "+", " ")
|
|
|
|
str = gsub (str, "%%(%x%x)", hexcode2char)
|
|
|
|
str = gsub (str, "\r\n", "\n")
|
|
|
|
return str
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Converts a character to an hexadecimal code in the form %XX
|
|
|
|
local function char2hexcode (c)
|
2013-09-20 23:38:20 +02:00
|
|
|
return strformat ("%%%02X", strbyte(c))
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- URL-encode a string (see RFC 2396)
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.escape (str)
|
2013-09-20 23:38:20 +02:00
|
|
|
str = gsub (str, "\n", "\r\n")
|
|
|
|
str = gsub (str, "([^0-9a-zA-Z ])", char2hexcode) -- locale independent
|
|
|
|
str = gsub (str, " ", "+")
|
|
|
|
return str
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- Insert a (name=value) pair into table [[args]]
|
|
|
|
-- @param args Table to receive the result.
|
|
|
|
-- @param name Key for the table.
|
|
|
|
-- @param value Value for the key.
|
|
|
|
-- Multi-valued names will be represented as tables with numerical indexes
|
|
|
|
-- (in the order they came).
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.insertfield (args, name, value)
|
2013-09-20 23:38:20 +02:00
|
|
|
if not args[name] then
|
|
|
|
args[name] = value
|
|
|
|
else
|
|
|
|
local t = type (args[name])
|
|
|
|
if t == "string" then
|
|
|
|
args[name] = {
|
|
|
|
args[name],
|
|
|
|
value,
|
|
|
|
}
|
|
|
|
elseif t == "table" then
|
|
|
|
tinsert (args[name], value)
|
|
|
|
else
|
|
|
|
error ("CGILua fatal error (invalid args table)!")
|
|
|
|
end
|
|
|
|
end
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- Parse url-encoded request data
|
|
|
|
-- (the query part of the script URL or url-encoded post data)
|
|
|
|
--
|
|
|
|
-- Each decoded (name=value) pair is inserted into table [[args]]
|
|
|
|
-- @param query String to be parsed.
|
|
|
|
-- @param args Table where to store the pairs.
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.parsequery (query, args)
|
2013-09-20 23:38:20 +02:00
|
|
|
if type(query) == "string" then
|
|
|
|
local insertfield, unescape = _M.insertfield, _M.unescape
|
|
|
|
gsub (query, "([^&=]+)=([^&=]*)&?",
|
|
|
|
function (key, val)
|
|
|
|
_M.insertfield (args, unescape(key), unescape(val))
|
|
|
|
end)
|
|
|
|
end
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
2013-09-20 23:38:20 +02:00
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- Parse url-encoded request data without using regular expressions
|
|
|
|
-- (the query part of the script URL or url-encoded post data)
|
|
|
|
--
|
|
|
|
-- Each decoded (name=value) pair is inserted into table [[args]]
|
|
|
|
-- @param query String to be parsed.
|
|
|
|
-- @param args Table where to store the pairs.
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.parsequeryNoRegex (query, args)
|
|
|
|
if type(query) == "string" then
|
|
|
|
local insertfield, unescape = _M.insertfield, _M.unescape
|
|
|
|
|
|
|
|
local k = 1
|
|
|
|
while true do
|
|
|
|
local v = query:find('=', k+1, true) -- look for '=', assuming a key of at least 1 character and do not perform pattern matching
|
|
|
|
if not v then break end -- no k/v pairs left
|
|
|
|
|
2013-09-23 18:42:00 +02:00
|
|
|
local key = query:sub(k, v-1)
|
2013-09-20 23:38:20 +02:00
|
|
|
v = v + 1
|
2013-10-08 16:55:50 +02:00
|
|
|
|
2013-09-20 23:38:20 +02:00
|
|
|
local ampersand = query:find('&', v, true)
|
|
|
|
if not ampersand then ampersand = 0 end -- 0 will become -1 in the substring call below...meaning end of string
|
|
|
|
|
2013-10-08 16:55:50 +02:00
|
|
|
|
2013-09-20 23:38:20 +02:00
|
|
|
local value = query:sub(v, ampersand - 1)
|
2013-10-08 16:55:50 +02:00
|
|
|
|
2013-09-20 23:38:20 +02:00
|
|
|
insertfield (args, unescape(key), unescape(value))
|
|
|
|
|
|
|
|
if ampersand == 0 then break end -- we couldn't find any ampersands anymore so this was the last k/v
|
|
|
|
|
|
|
|
k = ampersand + 1
|
|
|
|
end
|
|
|
|
end
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
-- URL-encode the elements of a table creating a string to be used in a
|
|
|
|
-- URL for passing data/parameters to another script
|
|
|
|
-- @param args Table where to extract the pairs (name=value).
|
|
|
|
-- @return String with the resulting encoding.
|
|
|
|
----------------------------------------------------------------------------
|
|
|
|
function _M.encodetable (args)
|
2013-09-20 23:38:20 +02:00
|
|
|
if args == nil or next(args) == nil then -- no args or empty args?
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
local escape = _M.escape
|
|
|
|
local strp = ""
|
|
|
|
for key, vals in pairs(args) do
|
|
|
|
if type(vals) ~= "table" then
|
|
|
|
vals = {vals}
|
|
|
|
end
|
|
|
|
for i,val in ipairs(vals) do
|
|
|
|
strp = strp.."&"..escape(key).."="..escape(val)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- remove first &
|
|
|
|
return strsub(strp,2)
|
2013-04-04 10:18:08 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return _M
|