1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
-- filename : l-url.lua
-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
-- copyright: PRAGMA ADE / ConTeXt Development Team
-- license : see context related readme files
if not versions then versions = { } end versions['l-url'] = 1.001
if not url then url = { } end
-- from the spec (on the web):
--
-- foo://example.com:8042/over/there?name=ferret#nose
-- \_/ \______________/\_________/ \_________/ \__/
-- | | | | |
-- scheme authority path query fragment
-- | _____________________|__
-- / \ / \
-- urn:example:animal:ferret:nose
do
local function tochar(s)
return string.char(tonumber(s,16))
end
local colon, qmark, hash, slash, percent, endofstring = lpeg.P(":"), lpeg.P("?"), lpeg.P("#"), lpeg.P("/"), lpeg.P("%"), lpeg.P(-1)
local hexdigit = lpeg.R("09","AF","af")
local escaped = percent * lpeg.C(hexdigit * hexdigit) / tochar
local scheme = lpeg.Cs((escaped+(1-colon-slash-qmark-hash))^0) * colon + lpeg.Cc("")
local authority = slash * slash * lpeg.Cs((escaped+(1- slash-qmark-hash))^0) + lpeg.Cc("")
local path = slash * lpeg.Cs((escaped+(1- qmark-hash))^0) + lpeg.Cc("")
local query = qmark * lpeg.Cs((escaped+(1- hash))^0) + lpeg.Cc("")
local fragment = hash * lpeg.Cs((escaped+(1- endofstring))^0) + lpeg.Cc("")
local parser = lpeg.Ct(scheme * authority * path * query * fragment)
function url.split(str)
return (type(str) == "string" and parser:match(str)) or str
end
end
function url.hashed(str)
local s = url.split(str)
return {
scheme = (s[1] ~= "" and s[1]) or "file",
authority = s[2],
path = s[3],
query = s[4],
fragment = s[5],
original = str
}
end
function url.filename(filename)
local t = url.hashed(filename)
return (t.scheme == "file" and t.path:gsub("^/([a-zA-Z])([:|])/)","%1:")) or filename
end
function url.query(str)
if type(str) == "string" then
local t = { }
for k, v in str:gmatch("([^&=]*)=([^&=]*)") do
t[k] = v
end
return t
else
return str
end
end
--~ print(url.filename("file:///c:/oeps.txt"))
--~ print(url.filename("c:/oeps.txt"))
--~ print(url.filename("file:///oeps.txt"))
--~ print(url.filename("file:///etc/test.txt"))
--~ print(url.filename("/oeps.txt"))
-- from the spec on the web (sort of):
--~
--~ function test(str)
--~ print(table.serialize(url.hashed(str)))
--~ end
---~
--~ test("%56pass%20words")
--~ test("file:///c:/oeps.txt")
--~ test("file:///c|/oeps.txt")
--~ test("file:///etc/oeps.txt")
--~ test("file://./etc/oeps.txt")
--~ test("file:////etc/oeps.txt")
--~ test("ftp://ftp.is.co.za/rfc/rfc1808.txt")
--~ test("http://www.ietf.org/rfc/rfc2396.txt")
--~ test("ldap://[2001:db8::7]/c=GB?objectClass?one#what")
--~ test("mailto:John.Doe@example.com")
--~ test("news:comp.infosystems.www.servers.unix")
--~ test("tel:+1-816-555-1212")
--~ test("telnet://192.0.2.16:80/")
--~ test("urn:oasis:names:specification:docbook:dtd:xml:4.1.2")
--~ test("/etc/passwords")
--~ test("http://www.pragma-ade.com/spaced%20name")
--~ test("zip:///oeps/oeps.zip#bla/bla.tex")
--~ test("zip:///oeps/oeps.zip?bla/bla.tex")
|