diff options
| -rw-r--r-- | src/url.lua | 64 | ||||
| -rw-r--r-- | test/urltest.lua | 44 |
2 files changed, 26 insertions, 82 deletions
diff --git a/src/url.lua b/src/url.lua index 0a3a80a..110ea94 100644 --- a/src/url.lua +++ b/src/url.lua | |||
| @@ -77,34 +77,6 @@ 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 | ----------------------------------------------------------------------------- | ||
| 108 | -- Builds a path from a base path and a relative path | 80 | -- Builds a path from a base path and a relative path |
| 109 | -- Input | 81 | -- Input |
| 110 | -- base_path | 82 | -- base_path |
| @@ -113,12 +85,23 @@ end | |||
| 113 | -- corresponding absolute path | 85 | -- corresponding absolute path |
| 114 | ----------------------------------------------------------------------------- | 86 | ----------------------------------------------------------------------------- |
| 115 | local function absolute_path(base_path, relative_path) | 87 | local function absolute_path(base_path, relative_path) |
| 116 | if string.sub(relative_path, 1, 1) == "/" then | 88 | if string.sub(relative_path, 1, 1) == "/" then return relative_path end |
| 117 | return remove_dot_components(relative_path) end | 89 | local path = string.gsub(base_path, "[^/]*$", "") |
| 118 | base_path = base_path:gsub("[^/]*$", "") | 90 | path = path .. relative_path |
| 119 | if not base_path:find'/$' then base_path = base_path .. '/' end | 91 | path = string.gsub(path, "([^/]*%./)", function (s) |
| 120 | local path = base_path .. relative_path | 92 | if s ~= "./" then return s else return "" end |
| 121 | path = remove_dot_components(path) | 93 | end) |
| 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) | ||
| 122 | return path | 105 | return path |
| 123 | end | 106 | end |
| 124 | 107 | ||
| @@ -244,14 +227,10 @@ function _M.absolute(base_url, relative_url) | |||
| 244 | else | 227 | else |
| 245 | base_parsed = _M.parse(base_url) | 228 | base_parsed = _M.parse(base_url) |
| 246 | end | 229 | end |
| 247 | local result | ||
| 248 | local relative_parsed = _M.parse(relative_url) | 230 | local relative_parsed = _M.parse(relative_url) |
| 249 | if not base_parsed then | 231 | if not base_parsed then return relative_url |
| 250 | result = relative_url | 232 | elseif not relative_parsed then return base_url |
| 251 | elseif not relative_parsed then | 233 | elseif relative_parsed.scheme then return relative_url |
| 252 | result = base_url | ||
| 253 | elseif relative_parsed.scheme then | ||
| 254 | result = relative_url | ||
| 255 | else | 234 | else |
| 256 | relative_parsed.scheme = base_parsed.scheme | 235 | relative_parsed.scheme = base_parsed.scheme |
| 257 | if not relative_parsed.authority then | 236 | if not relative_parsed.authority then |
| @@ -269,9 +248,8 @@ function _M.absolute(base_url, relative_url) | |||
| 269 | relative_parsed.path) | 248 | relative_parsed.path) |
| 270 | end | 249 | end |
| 271 | end | 250 | end |
| 272 | result = _M.build(relative_parsed) | 251 | return _M.build(relative_parsed) |
| 273 | end | 252 | end |
| 274 | return remove_dot_components(result) | ||
| 275 | end | 253 | end |
| 276 | 254 | ||
| 277 | ----------------------------------------------------------------------------- | 255 | ----------------------------------------------------------------------------- |
diff --git a/test/urltest.lua b/test/urltest.lua index ae8ba75..1090a7e 100644 --- a/test/urltest.lua +++ b/test/urltest.lua | |||
| @@ -61,7 +61,7 @@ end | |||
| 61 | local check_absolute_url = function(base, relative, absolute) | 61 | local check_absolute_url = function(base, relative, absolute) |
| 62 | local res = socket.url.absolute(base, relative) | 62 | local res = socket.url.absolute(base, relative) |
| 63 | if res ~= absolute then | 63 | if res ~= absolute then |
| 64 | io.write("absolute: In test for base='", base, "', rel='", relative, "' expected '", | 64 | io.write("absolute: In test for '", relative, "' expected '", |
| 65 | absolute, "' but got '", res, "'\n") | 65 | absolute, "' but got '", res, "'\n") |
| 66 | os.exit() | 66 | os.exit() |
| 67 | end | 67 | end |
| @@ -627,37 +627,25 @@ 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") |
| 637 | check_absolute_url("http://a/b/c/d;p?q#f", "g;x?y#s", "http://a/b/c/g;x?y#s") | 637 | check_absolute_url("http://a/b/c/d;p?q#f", "g;x?y#s", "http://a/b/c/g;x?y#s") |
| 638 | check_absolute_url("http://a/b/c/d;p?q#f", ".", "http://a/b/c/") | 638 | check_absolute_url("http://a/b/c/d;p?q#f", ".", "http://a/b/c/") |
| 639 | check_absolute_url("http://a/b/c/d;p?q#f", "./", "http://a/b/c/") | 639 | check_absolute_url("http://a/b/c/d;p?q#f", "./", "http://a/b/c/") |
| 640 | check_absolute_url("http://a/b/c/d;p?q#f", "./g", "http://a/b/c/g") | ||
| 641 | check_absolute_url("http://a/b/c/d;p?q#f", "./g/", "http://a/b/c/g/") | ||
| 642 | check_absolute_url("http://a/b/c/d;p?q#f", "././g", "http://a/b/c/g") | ||
| 643 | check_absolute_url("http://a/b/c/d;p?q#f", "././g/", "http://a/b/c/g/") | ||
| 644 | check_absolute_url("http://a/b/c/d;p?q#f", "g/.", "http://a/b/c/g/") | ||
| 645 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./", "http://a/b/c/g/") | ||
| 646 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./.", "http://a/b/c/g/") | ||
| 647 | check_absolute_url("http://a/b/c/d;p?q#f", "g/././", "http://a/b/c/g/") | ||
| 648 | check_absolute_url("http://a/b/c/d;p?q#f", "./.", "http://a/b/c/") | ||
| 649 | check_absolute_url("http://a/b/c/d;p?q#f", "././.", "http://a/b/c/") | ||
| 650 | check_absolute_url("http://a/b/c/d;p?q#f", "././g/./.", "http://a/b/c/g/") | ||
| 651 | check_absolute_url("http://a/b/c/d;p?q#f", "..", "http://a/b/") | 640 | check_absolute_url("http://a/b/c/d;p?q#f", "..", "http://a/b/") |
| 652 | check_absolute_url("http://a/b/c/d;p?q#f", "../", "http://a/b/") | 641 | check_absolute_url("http://a/b/c/d;p?q#f", "../", "http://a/b/") |
| 653 | check_absolute_url("http://a/b/c/d;p?q#f", "../g", "http://a/b/g") | 642 | check_absolute_url("http://a/b/c/d;p?q#f", "../g", "http://a/b/g") |
| 654 | check_absolute_url("http://a/b/c/d;p?q#f", "../..", "http://a/") | 643 | 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/") | 644 | 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") | 645 | 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", "../../../g", "http://a/g") | ||
| 658 | check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") | 646 | check_absolute_url("http://a/b/c/d;p?q#f", "", "http://a/b/c/d;p?q#f") |
| 659 | check_absolute_url("http://a/b/c/d;p?q#f", "/./g", "http://a/g") | 647 | 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/g") | 648 | check_absolute_url("http://a/b/c/d;p?q#f", "/../g", "http://a/../g") |
| 661 | check_absolute_url("http://a/b/c/d;p?q#f", "g.", "http://a/b/c/g.") | 649 | 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") | 650 | check_absolute_url("http://a/b/c/d;p?q#f", ".g", "http://a/b/c/.g") |
| 663 | check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..") | 651 | check_absolute_url("http://a/b/c/d;p?q#f", "g..", "http://a/b/c/g..") |
| @@ -667,17 +655,6 @@ check_absolute_url("http://a/b/c/d;p?q#f", "./g/.", "http://a/b/c/g/") | |||
| 667 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h") | 655 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h") |
| 668 | check_absolute_url("http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h") | 656 | check_absolute_url("http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h") |
| 669 | 657 | ||
| 670 | check_absolute_url("http://a/b/c/d:p?q#f/", "../g/", "http://a/b/g/") | ||
| 671 | check_absolute_url("http://a/b/c/d:p?q#f/", "../g", "http://a/b/g") | ||
| 672 | check_absolute_url("http://a/b/c/d:p?q#f/", "../.g/", "http://a/b/.g/") | ||
| 673 | check_absolute_url("http://a/b/c/d:p?q#f/", "../.g", "http://a/b/.g") | ||
| 674 | check_absolute_url("http://a/b/c/d:p?q#f/", "../.g.h/", "http://a/b/.g.h/") | ||
| 675 | check_absolute_url("http://a/b/c/d:p?q#f/", "../.g.h", "http://a/b/.g.h") | ||
| 676 | |||
| 677 | check_absolute_url("http://a/b/c/d:p?q#f/", "g.h/", "http://a/b/c/g.h/") | ||
| 678 | check_absolute_url("http://a/b/c/d:p?q#f/", "../g.h/", "http://a/b/g.h/") | ||
| 679 | check_absolute_url("http://a/", "../g.h/", "http://a/g.h/") | ||
| 680 | |||
| 681 | -- extra tests | 658 | -- extra tests |
| 682 | check_absolute_url("//a/b/c/d;p?q#f", "d/e/f", "//a/b/c/d/e/f") | 659 | check_absolute_url("//a/b/c/d;p?q#f", "d/e/f", "//a/b/c/d/e/f") |
| 683 | check_absolute_url("/a/b/c/d;p?q#f", "d/e/f", "/a/b/c/d/e/f") | 660 | check_absolute_url("/a/b/c/d;p?q#f", "d/e/f", "/a/b/c/d/e/f") |
| @@ -685,17 +662,6 @@ check_absolute_url("a/b/c/d", "d/e/f", "a/b/c/d/e/f") | |||
| 685 | check_absolute_url("a/b/c/d/../", "d/e/f", "a/b/c/d/e/f") | 662 | check_absolute_url("a/b/c/d/../", "d/e/f", "a/b/c/d/e/f") |
| 686 | check_absolute_url("http://velox.telemar.com.br", "/dashboard/index.html", | 663 | check_absolute_url("http://velox.telemar.com.br", "/dashboard/index.html", |
| 687 | "http://velox.telemar.com.br/dashboard/index.html") | 664 | "http://velox.telemar.com.br/dashboard/index.html") |
| 688 | check_absolute_url("http://example.com/", "../.badhost.com/", "http://example.com/.badhost.com/") | ||
| 689 | check_absolute_url("http://example.com/", "...badhost.com/", "http://example.com/...badhost.com/") | ||
| 690 | check_absolute_url("http://example.com/a/b/c/d/", "../q", "http://example.com/a/b/c/q") | ||
| 691 | check_absolute_url("http://example.com/a/b/c/d/", "../../q", "http://example.com/a/b/q") | ||
| 692 | check_absolute_url("http://example.com/a/b/c/d/", "../../../q", "http://example.com/a/q") | ||
| 693 | check_absolute_url("http://example.com", ".badhost.com", "http://example.com/.badhost.com") | ||
| 694 | check_absolute_url("http://example.com/a/b/c/d/", "..//../../../q", "http://example.com/a/q") | ||
| 695 | check_absolute_url("http://example.com/a/b/c/d/", "..//a/../../../../q", "http://example.com/a/q") | ||
| 696 | check_absolute_url("http://example.com/a/b/c/d/", "..//a/..//../../../q", "http://example.com/a/b/q") | ||
| 697 | check_absolute_url("http://example.com/a/b/c/d/", "..//a/..///../../../../q", "http://example.com/a/b/q") | ||
| 698 | check_absolute_url("http://example.com/a/b/c/d/", "../x/a/../y/z/../../../../q", "http://example.com/a/b/q") | ||
| 699 | 665 | ||
| 700 | print("testing path parsing and composition") | 666 | print("testing path parsing and composition") |
| 701 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) | 667 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) |
