rev |
line source |
jbe/bsw@20
|
1 --[[--
|
jbe@320
|
2 url = -- normalized URL or nil
|
jbe/bsw@20
|
3 auth.openid._normalize_url(
|
jbe/bsw@20
|
4 url -- unnormalized URL
|
jbe/bsw@20
|
5 )
|
jbe/bsw@20
|
6
|
jbe/bsw@20
|
7 This function normalizes an URL, and returns nil if the given URL is not a
|
jbe/bsw@20
|
8 valid absolute URL. For security reasons only a restricted set of URLs is
|
jbe/bsw@20
|
9 valid.
|
jbe/bsw@20
|
10
|
jbe/bsw@20
|
11 --]]--
|
jbe/bsw@20
|
12
|
jbe/bsw@20
|
13 function auth.openid._normalize_url(url)
|
jbe/bsw@20
|
14 local url = string.match(url, "^(.-)??$") -- remove "?" at end
|
jbe/bsw@20
|
15 local proto, host, path = string.match(
|
jbe/bsw@20
|
16 url,
|
jbe/bsw@20
|
17 "([A-Za-z]+)://([0-9A-Za-z.:_-]+)/?([0-9A-Za-z%%/._~-]*)$"
|
jbe/bsw@20
|
18 )
|
jbe/bsw@20
|
19 if not proto then
|
jbe/bsw@20
|
20 return nil
|
jbe/bsw@20
|
21 end
|
jbe/bsw@20
|
22 proto = string.lower(proto)
|
jbe/bsw@20
|
23 host = string.lower(host)
|
jbe/bsw@20
|
24 local port = string.match(host, ":(.*)")
|
jbe/bsw@20
|
25 if port then
|
jbe/bsw@20
|
26 if string.find(port, "^[0-9]+$") then
|
jbe/bsw@20
|
27 port = tonumber(port)
|
jbe/bsw@20
|
28 host = string.match(host, "^(.-):")
|
jbe/bsw@20
|
29 if port < 1 or port > 65535 then
|
jbe/bsw@20
|
30 return nil
|
jbe/bsw@20
|
31 end
|
jbe/bsw@20
|
32 else
|
jbe/bsw@20
|
33 return nil
|
jbe/bsw@20
|
34 end
|
jbe/bsw@20
|
35 end
|
jbe/bsw@20
|
36 if proto == "http" then
|
jbe/bsw@20
|
37 if port == 80 then port = nil end
|
jbe/bsw@20
|
38 elseif proto == "https" then
|
jbe/bsw@20
|
39 if port == 443 then port = nil end
|
jbe/bsw@20
|
40 else
|
jbe/bsw@20
|
41 return nil
|
jbe/bsw@20
|
42 end
|
jbe/bsw@20
|
43 if
|
jbe/bsw@20
|
44 string.find(host, "^%.") or
|
jbe/bsw@20
|
45 string.find(host, "%.$") or
|
jbe/bsw@20
|
46 string.find(host, "%.%.")
|
jbe/bsw@20
|
47 then
|
jbe/bsw@20
|
48 return nil
|
jbe/bsw@20
|
49 end
|
jbe/bsw@20
|
50 for part in string.gmatch(host, "[^.]+") do
|
jbe/bsw@20
|
51 if not string.find(part, "[A-Za-z]") then
|
jbe/bsw@20
|
52 return nil
|
jbe/bsw@20
|
53 end
|
jbe/bsw@20
|
54 end
|
jbe/bsw@20
|
55 local path_parts = {}
|
jbe/bsw@20
|
56 for part in string.gmatch(path, "[^/]+") do
|
jbe/bsw@20
|
57 if part == "." then
|
jbe/bsw@20
|
58 -- do nothing
|
jbe/bsw@20
|
59 elseif part == ".." then
|
jbe/bsw@20
|
60 path_parts[#path_parts] = nil
|
jbe/bsw@20
|
61 else
|
jbe/bsw@20
|
62 local fail = false
|
jbe/bsw@20
|
63 local part = string.gsub(
|
jbe/bsw@20
|
64 part,
|
jbe/bsw@20
|
65 "%%([0-9A-Fa-f]?[0-9A-Fa-f]?)",
|
jbe/bsw@20
|
66 function (hex)
|
jbe/bsw@20
|
67 if #hex ~= 2 then
|
jbe/bsw@20
|
68 fail = true
|
jbe/bsw@20
|
69 return
|
jbe/bsw@20
|
70 end
|
jbe/bsw@20
|
71 local char = string.char(tonumber("0x" .. hex))
|
jbe/bsw@20
|
72 if string.find(char, "[0-9A-Za-z._~-]") then
|
jbe/bsw@20
|
73 return char
|
jbe/bsw@20
|
74 else
|
jbe/bsw@20
|
75 return "%" .. string.upper(hex)
|
jbe/bsw@20
|
76 end
|
jbe/bsw@20
|
77 end
|
jbe/bsw@20
|
78 )
|
jbe/bsw@20
|
79 if fail then
|
jbe/bsw@20
|
80 return nil
|
jbe/bsw@20
|
81 end
|
jbe/bsw@20
|
82 path_parts[#path_parts+1] = part
|
jbe/bsw@20
|
83 end
|
jbe/bsw@20
|
84 end
|
jbe/bsw@20
|
85 if string.find(path, "/$") then
|
jbe/bsw@20
|
86 path_parts[#path_parts+1] = ""
|
jbe/bsw@20
|
87 end
|
jbe/bsw@20
|
88 path = table.concat(path_parts, "/")
|
jbe/bsw@20
|
89 if port then
|
jbe/bsw@20
|
90 host = host .. ":" .. tostring(port)
|
jbe/bsw@20
|
91 end
|
jbe/bsw@20
|
92 return proto .. "://" .. host .. "/" .. path
|
jbe/bsw@20
|
93 end
|