diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/url.lua | 64 |
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) | |||
77 | end | 77 | end |
78 | 78 | ||
79 | ----------------------------------------------------------------------------- | 79 | ----------------------------------------------------------------------------- |
80 | -- Removes '..' and '.' components appropriately from a path. | ||
81 | -- Input | ||
82 | -- path | ||
83 | -- Returns | ||
84 | -- dot-normalized path | ||
85 | local 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 | ||
105 | end | ||
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 | ----------------------------------------------------------------------------- |
87 | local function absolute_path(base_path, relative_path) | 115 | local 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 |
106 | end | 123 | end |
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) | ||
253 | end | 275 | end |
254 | 276 | ||
255 | ----------------------------------------------------------------------------- | 277 | ----------------------------------------------------------------------------- |