aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/url.lua64
1 files changed, 43 insertions, 21 deletions
diff --git a/src/url.lua b/src/url.lua
index 110ea94..0a3a80a 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -77,6 +77,34 @@ function _M.unescape(s)
77end 77end
78 78
79----------------------------------------------------------------------------- 79-----------------------------------------------------------------------------
80-- Removes '..' and '.' components appropriately from a path.
81-- Input
82-- path
83-- Returns
84-- dot-normalized path
85local function remove_dot_components(path)
86 local marker = string.char(1)
87 repeat
88 local was = path
89 path = path:gsub('//', '/'..marker..'/', 1)
90 until path == was
91 repeat
92 local was = path
93 path = path:gsub('/%./', '/', 1)
94 until path == was
95 repeat
96 local was = path
97 path = path:gsub('[^/]+/%.%./([^/]+)', '%1', 1)
98 until path == was
99 path = path:gsub('[^/]+/%.%./*$', '')
100 path = path:gsub('/%.%.$', '/')
101 path = path:gsub('/%.$', '/')
102 path = path:gsub('^/%.%./', '/')
103 path = path:gsub(marker, '')
104 return path
105end
106
107-----------------------------------------------------------------------------
80-- Builds a path from a base path and a relative path 108-- Builds a path from a base path and a relative path
81-- Input 109-- Input
82-- base_path 110-- base_path
@@ -85,23 +113,12 @@ end
85-- corresponding absolute path 113-- corresponding absolute path
86----------------------------------------------------------------------------- 114-----------------------------------------------------------------------------
87local function absolute_path(base_path, relative_path) 115local function absolute_path(base_path, relative_path)
88 if string.sub(relative_path, 1, 1) == "/" then return relative_path end 116 if string.sub(relative_path, 1, 1) == "/" then
89 local path = string.gsub(base_path, "[^/]*$", "") 117 return remove_dot_components(relative_path) end
90 path = path .. relative_path 118 base_path = base_path:gsub("[^/]*$", "")
91 path = string.gsub(path, "([^/]*%./)", function (s) 119 if not base_path:find'/$' then base_path = base_path .. '/' end
92 if s ~= "./" then return s else return "" end 120 local path = base_path .. relative_path
93 end) 121 path = remove_dot_components(path)
94 path = string.gsub(path, "/%.$", "/")
95 local reduced
96 while reduced ~= path do
97 reduced = path
98 path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
99 if s ~= "../../" then return "" else return s end
100 end)
101 end
102 path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
103 if s ~= "../.." then return "" else return s end
104 end)
105 return path 122 return path
106end 123end
107 124
@@ -227,10 +244,14 @@ function _M.absolute(base_url, relative_url)
227 else 244 else
228 base_parsed = _M.parse(base_url) 245 base_parsed = _M.parse(base_url)
229 end 246 end
247 local result
230 local relative_parsed = _M.parse(relative_url) 248 local relative_parsed = _M.parse(relative_url)
231 if not base_parsed then return relative_url 249 if not base_parsed then
232 elseif not relative_parsed then return base_url 250 result = relative_url
233 elseif relative_parsed.scheme then return relative_url 251 elseif not relative_parsed then
252 result = base_url
253 elseif relative_parsed.scheme then
254 result = relative_url
234 else 255 else
235 relative_parsed.scheme = base_parsed.scheme 256 relative_parsed.scheme = base_parsed.scheme
236 if not relative_parsed.authority then 257 if not relative_parsed.authority then
@@ -248,8 +269,9 @@ function _M.absolute(base_url, relative_url)
248 relative_parsed.path) 269 relative_parsed.path)
249 end 270 end
250 end 271 end
251 return _M.build(relative_parsed) 272 result = _M.build(relative_parsed)
252 end 273 end
274 return remove_dot_components(result)
253end 275end
254 276
255----------------------------------------------------------------------------- 277-----------------------------------------------------------------------------