diff options
| author | Diego Nehab <diego.nehab@gmail.com> | 2018-08-22 14:18:43 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-22 14:18:43 -0300 |
| commit | 648d81281f177f43de3d7b66e5923bdbaaeb25d9 (patch) | |
| tree | cf5a837a349305ad10b54d1ce152e7cdc490edfc | |
| parent | 5813cd05054599b0409480d3214f1827c2360467 (diff) | |
| parent | 043e99771352aff47680b99f09b66a32f0cc3ef5 (diff) | |
| download | luasocket-648d81281f177f43de3d7b66e5923bdbaaeb25d9.tar.gz luasocket-648d81281f177f43de3d7b66e5923bdbaaeb25d9.tar.bz2 luasocket-648d81281f177f43de3d7b66e5923bdbaaeb25d9.zip | |
Merge pull request #256 from ewestbrook/luasocket254
url.lua:absolute_path(): fix issue #254
| -rw-r--r-- | src/url.lua | 64 | ||||
| -rw-r--r-- | test/urltest.lua | 44 |
2 files changed, 82 insertions, 26 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 | ----------------------------------------------------------------------------- |
diff --git a/test/urltest.lua b/test/urltest.lua index 1090a7e..ae8ba75 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 '", relative, "' expected '", | 64 | io.write("absolute: In test for base='", base, "', rel='", 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,25 +627,37 @@ 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/") | ||
| 640 | check_absolute_url("http://a/b/c/d;p?q#f", "..", "http://a/b/") | 651 | 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/") | 652 | check_absolute_url("http://a/b/c/d;p?q#f", "../", "http://a/b/") |
| 642 | check_absolute_url("http://a/b/c/d;p?q#f", "../g", "http://a/b/g") | 653 | check_absolute_url("http://a/b/c/d;p?q#f", "../g", "http://a/b/g") |
| 643 | check_absolute_url("http://a/b/c/d;p?q#f", "../..", "http://a/") | 654 | 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/") | 655 | check_absolute_url("http://a/b/c/d;p?q#f", "../../", "http://a/") |
| 645 | 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", "../../../g", "http://a/g") | ||
| 646 | 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", "", "http://a/b/c/d;p?q#f") |
| 647 | 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") |
| 648 | 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") |
| 649 | 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.") |
| 650 | 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") |
| 651 | 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..") |
| @@ -655,6 +667,17 @@ check_absolute_url("http://a/b/c/d;p?q#f", "./g/.", "http://a/b/c/g/") | |||
| 655 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h") | 667 | check_absolute_url("http://a/b/c/d;p?q#f", "g/./h", "http://a/b/c/g/h") |
| 656 | check_absolute_url("http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h") | 668 | check_absolute_url("http://a/b/c/d;p?q#f", "g/../h", "http://a/b/c/h") |
| 657 | 669 | ||
| 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 | |||
| 658 | -- extra tests | 681 | -- extra tests |
| 659 | check_absolute_url("//a/b/c/d;p?q#f", "d/e/f", "//a/b/c/d/e/f") | 682 | 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") | 683 | check_absolute_url("/a/b/c/d;p?q#f", "d/e/f", "/a/b/c/d/e/f") |
| @@ -662,6 +685,17 @@ 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") | 685 | check_absolute_url("a/b/c/d/../", "d/e/f", "a/b/c/d/e/f") |
| 663 | check_absolute_url("http://velox.telemar.com.br", "/dashboard/index.html", | 686 | check_absolute_url("http://velox.telemar.com.br", "/dashboard/index.html", |
| 664 | "http://velox.telemar.com.br/dashboard/index.html") | 687 | "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") | ||
| 665 | 699 | ||
| 666 | print("testing path parsing and composition") | 700 | print("testing path parsing and composition") |
| 667 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) | 701 | check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 }) |
