| rev | line source | 
| jbe/bsw@20 | 1 --[[-- | 
| jbe/bsw@20 | 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 |