diff options
-rw-r--r-- | src/url.lua | 51 | ||||
-rw-r--r-- | test/urltest.lua | 8 |
2 files changed, 38 insertions, 21 deletions
diff --git a/src/url.lua b/src/url.lua index 29b6734..a354ab5 100644 --- a/src/url.lua +++ b/src/url.lua | |||
@@ -77,24 +77,19 @@ function _M.unescape(s) | |||
77 | end | 77 | end |
78 | 78 | ||
79 | ----------------------------------------------------------------------------- | 79 | ----------------------------------------------------------------------------- |
80 | -- Builds a path from a base path and a relative path | 80 | -- Removes '..' and '.' components appropriately from a path. |
81 | -- Input | 81 | -- Input |
82 | -- base_path | 82 | -- path |
83 | -- relative_path | ||
84 | -- Returns | 83 | -- Returns |
85 | -- corresponding absolute path | 84 | -- dot-normalized path |
86 | ----------------------------------------------------------------------------- | 85 | local function remove_dot_components(path) |
87 | local function absolute_path(base_path, relative_path) | ||
88 | if string.sub(relative_path, 1, 1) == "/" then return relative_path end | ||
89 | local path = string.gsub(base_path, "[^/]*$", "") | ||
90 | path = path .. relative_path | ||
91 | repeat | 86 | repeat |
92 | local was = path | 87 | local was = path |
93 | path = path:gsub('/%./', '/') | 88 | path = path:gsub('/%./', '/') |
94 | until path == was | 89 | until path == was |
95 | repeat | 90 | repeat |
96 | local was = path | 91 | local was = path |
97 | path = path:gsub('[^/]+/%.%./([^/]+)', '%1') | 92 | path = path:gsub('[^/]+/%.%./([^/]+)', '%1') |
98 | until path == was | 93 | until path == was |
99 | path = path:gsub('[^/]+/%.%./*$', '') | 94 | path = path:gsub('[^/]+/%.%./*$', '') |
100 | path = path:gsub('/%.%.$', '/') | 95 | path = path:gsub('/%.%.$', '/') |
@@ -104,6 +99,23 @@ local function absolute_path(base_path, relative_path) | |||
104 | end | 99 | end |
105 | 100 | ||
106 | ----------------------------------------------------------------------------- | 101 | ----------------------------------------------------------------------------- |
102 | -- Builds a path from a base path and a relative path | ||
103 | -- Input | ||
104 | -- base_path | ||
105 | -- relative_path | ||
106 | -- Returns | ||
107 | -- corresponding absolute path | ||
108 | ----------------------------------------------------------------------------- | ||
109 | local function absolute_path(base_path, relative_path) | ||
110 | if string.sub(relative_path, 1, 1) == "/" then | ||
111 | return remove_dot_components(relative_path) end | ||
112 | base_path = base_path:gsub("[^/]*$", "") | ||
113 | local path = base_path .. relative_path | ||
114 | path = remove_dot_components(path) | ||
115 | return path | ||
116 | end | ||
117 | |||
118 | ----------------------------------------------------------------------------- | ||
107 | -- Parses a url and returns a table with all its parts according to RFC 2396 | 119 | -- Parses a url and returns a table with all its parts according to RFC 2396 |
108 | -- The following grammar describes the names given to the URL parts | 120 | -- The following grammar describes the names given to the URL parts |
109 | -- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment> | 121 | -- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment> |
@@ -225,10 +237,14 @@ function _M.absolute(base_url, relative_url) | |||
225 | else | 237 | else |
226 | base_parsed = _M.parse(base_url) | 238 | base_parsed = _M.parse(base_url) |
227 | end | 239 | end |
240 | local result | ||
228 | local relative_parsed = _M.parse(relative_url) | 241 | local relative_parsed = _M.parse(relative_url) |
229 | if not base_parsed then return relative_url | 242 | if not base_parsed then |
230 | elseif not relative_parsed then return base_url | 243 | result = relative_url |
231 | elseif relative_parsed.scheme then return relative_url | 244 | elseif not relative_parsed then |
245 | result = base_url | ||
246 | elseif relative_parsed.scheme then | ||
247 | result = relative_url | ||
232 | else | 248 | else |
233 | relative_parsed.scheme = base_parsed.scheme | 249 | relative_parsed.scheme = base_parsed.scheme |
234 | if not relative_parsed.authority then | 250 | if not relative_parsed.authority then |
@@ -246,8 +262,9 @@ function _M.absolute(base_url, relative_url) | |||
246 | relative_parsed.path) | 262 | relative_parsed.path) |
247 | end | 263 | end |
248 | end | 264 | end |
249 | return _M.build(relative_parsed) | 265 | result = _M.build(relative_parsed) |
250 | end | 266 | end |
267 | return remove_dot_components(result) | ||
251 | end | 268 | end |
252 | 269 | ||
253 | ----------------------------------------------------------------------------- | 270 | ----------------------------------------------------------------------------- |
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") | |||
627 | check_absolute_url("http://a/b/c/d;p?q#f", "//g", "http://g") | 627 | check_absolute_url("http://a/b/c/d;p?q#f", "//g", "http://g") |
628 | check_absolute_url("http://a/b/c/d;p?q#f", "?y", "http://a/b/c/d;p?y") | 628 | check_absolute_url("http://a/b/c/d;p?q#f", "?y", "http://a/b/c/d;p?y") |
629 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y", "http://a/b/c/g?y") | 629 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y", "http://a/b/c/g?y") |
630 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/./x") | 630 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y/./x", "http://a/b/c/g?y/x") |
631 | check_absolute_url("http://a/b/c/d;p?q#f", "#s", "http://a/b/c/d;p?q#s") | 631 | check_absolute_url("http://a/b/c/d;p?q#f", "#s", "http://a/b/c/d;p?q#s") |
632 | check_absolute_url("http://a/b/c/d;p?q#f", "g#s", "http://a/b/c/g#s") | 632 | check_absolute_url("http://a/b/c/d;p?q#f", "g#s", "http://a/b/c/g#s") |
633 | check_absolute_url("http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/./x") | 633 | check_absolute_url("http://a/b/c/d;p?q#f", "g#s/./x", "http://a/b/c/g#s/x") |
634 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y#s", "http://a/b/c/g?y#s") | 634 | check_absolute_url("http://a/b/c/d;p?q#f", "g?y#s", "http://a/b/c/g?y#s") |
635 | check_absolute_url("http://a/b/c/d;p?q#f", ";x", "http://a/b/c/d;x") | 635 | check_absolute_url("http://a/b/c/d;p?q#f", ";x", "http://a/b/c/d;x") |
636 | check_absolute_url("http://a/b/c/d;p?q#f", "g;x", "http://a/b/c/g;x") | 636 | 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/") | |||
655 | check_absolute_url("http://a/b/c/d;p?q#f", "../../", "http://a/") | 655 | check_absolute_url("http://a/b/c/d;p?q#f", "../../", "http://a/") |
656 | check_absolute_url("http://a/b/c/d;p?q#f", "../../g", "http://a/g") | 656 | check_absolute_url("http://a/b/c/d;p?q#f", "../../g", "http://a/g") |
657 | check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") | 657 | check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") |
658 | check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/./g") | 658 | check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/g") |
659 | check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/../g") | 659 | check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/g") |
660 | check_absolute_url("http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g.") | 660 | check_absolute_url("http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g.") |
661 | check_absolute_url("http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g") | 661 | check_absolute_url("http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g") |
662 | check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..") | 662 | check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..") |