From c905b5d44f8cdfbc8110a9a7d1d62c08b5703ae3 Mon Sep 17 00:00:00 2001 From: "E. Westbrook" Date: Tue, 21 Aug 2018 08:03:51 -0600 Subject: [PATCH] url.lua: separate remove_dot_components() from absolute_path(); also use in _M.absolute() even when not merging --- src/url.lua | 55 +++++++++++++++++++++++++++++++----------------- test/urltest.lua | 8 +++---- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/url.lua b/src/url.lua index 29b6734..a354ab5 100644 --- a/src/url.lua +++ b/src/url.lua @@ -76,6 +76,28 @@ function _M.unescape(s) end)) end +----------------------------------------------------------------------------- +-- Removes '..' and '.' components appropriately from a path. +-- Input +-- path +-- Returns +-- dot-normalized path +local function remove_dot_components(path) + repeat + local was = path + path = path:gsub('/%./', '/') + until path == was + repeat + local was = path + path = path:gsub('[^/]+/%.%./([^/]+)', '%1') + until path == was + path = path:gsub('[^/]+/%.%./*$', '') + path = path:gsub('/%.%.$', '/') + path = path:gsub('/%.$', '/') + path = path:gsub('^/%.%.', '') + return path +end + ----------------------------------------------------------------------------- -- Builds a path from a base path and a relative path -- Input @@ -85,21 +107,11 @@ end -- corresponding absolute path ----------------------------------------------------------------------------- local function absolute_path(base_path, relative_path) - if string.sub(relative_path, 1, 1) == "/" then return relative_path end - local path = string.gsub(base_path, "[^/]*$", "") - path = path .. relative_path - repeat - local was = path - path = path:gsub('/%./', '/') - until path == was - repeat - local was = path - path = path:gsub('[^/]+/%.%./([^/]+)', '%1') - until path == was - path = path:gsub('[^/]+/%.%./*$', '') - path = path:gsub('/%.%.$', '/') - path = path:gsub('/%.$', '/') - path = path:gsub('^/%.%.', '') + if string.sub(relative_path, 1, 1) == "/" then + return remove_dot_components(relative_path) end + base_path = base_path:gsub("[^/]*$", "") + local path = base_path .. relative_path + path = remove_dot_components(path) return path end @@ -225,10 +237,14 @@ function _M.absolute(base_url, relative_url) else base_parsed = _M.parse(base_url) end + local result local relative_parsed = _M.parse(relative_url) - if not base_parsed then return relative_url - elseif not relative_parsed then return base_url - elseif relative_parsed.scheme then return relative_url + if not base_parsed then + result = relative_url + elseif not relative_parsed then + result = base_url + elseif relative_parsed.scheme then + result = relative_url else relative_parsed.scheme = base_parsed.scheme if not relative_parsed.authority then @@ -246,8 +262,9 @@ function _M.absolute(base_url, relative_url) relative_parsed.path) end end - return _M.build(relative_parsed) + result = _M.build(relative_parsed) end + return remove_dot_components(result) end ----------------------------------------------------------------------------- diff --git a/test/urltest.lua b/test/urltest.lua index 63a33ea..649be88 100644 --- a/test/urltest.lua +++ b/test/urltest.lua @@ -627,10 +627,10 @@ check_absolute_url("http://a/b/c/d;p?q#f", "/g", "http://a/g") check_absolute_url("http://a/b/c/d;p?q#f", "//g", "http://g") check_absolute_url("http://a/b/c/d;p?q#f", "?y", "http://a/b/c/d;p?y") check_absolute_url("http://a/b/c/d;p?q#f", "g?y", "http://a/b/c/g?y") -check_absolute_url("http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/./x") +check_absolute_url("http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/x") check_absolute_url("http://a/b/c/d;p?q#f", "#s", "http://a/b/c/d;p?q#s") check_absolute_url("http://a/b/c/d;p?q#f", "g#s", "http://a/b/c/g#s") -check_absolute_url("http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/./x") +check_absolute_url("http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/x") check_absolute_url("http://a/b/c/d;p?q#f", "g?y#s", "http://a/b/c/g?y#s") check_absolute_url("http://a/b/c/d;p?q#f", ";x", "http://a/b/c/d;x") check_absolute_url("http://a/b/c/d;p?q#f", "g;x", "http://a/b/c/g;x") @@ -655,8 +655,8 @@ check_absolute_url("http://a/b/c/d;p?q#f", "../..", "http://a/") check_absolute_url("http://a/b/c/d;p?q#f", "../../", "http://a/") check_absolute_url("http://a/b/c/d;p?q#f", "../../g", "http://a/g") check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") -check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/./g") -check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/../g") +check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/g") +check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/g") check_absolute_url("http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g.") check_absolute_url("http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g") check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..")