util-soc-imp-url.lua /size: 6863 b    last modification: 2020-07-01 14:35
1
-- original file : url.lua
2
-- for more into : see util-soc.lua
3 4
local
tonumber
,
tostring
,
type
=
tonumber
,
tostring
,
type
5 6
local
gsub
,
sub
,
match
,
find
,
format
,
byte
,
char
=
string
.
gsub
,
string
.
sub
,
string
.
match
,
string
.
find
,
string
.
format
,
string
.
byte
,
string
.
char
7
local
insert
=
table
.
insert
8 9
local
socket
=
socket
or
require
(
"
socket
"
)
10 11
local
url
=
{
12
_VERSION
=
"
URL 1.0.3
"
,
13
}
14 15
socket
.
url
=
url
16 17
function
url
.
escape
(
s
)
18
return
(
gsub
(
s
,
"
([^A-Za-z0-9_])
"
,
function
(
c
)
19
return
format
(
"
%%%02x
"
,
byte
(
c
)
)
20
end
)
)
21
end
22 23
local
function
make_set
(
t
)
-- table.tohash
24
local
s
=
{
}
25
for
i
=
1
,
#
t
do
26
s
[
t
[
i
]
]
=
true
27
end
28
return
s
29
end
30 31
local
segment_set
=
make_set
{
32
"
-
"
,
"
_
"
,
"
.
"
,
"
!
"
,
"
~
"
,
"
*
"
,
"
'
"
,
"
(
"
,
33
"
)
"
,
"
:
"
,
"
@
"
,
"
&
"
,
"
=
"
,
"
+
"
,
"
$
"
,
"
,
"
,
34
}
35 36
local
function
protect_segment
(
s
)
37
return
gsub
(
s
,
"
([^A-Za-z0-9_])
"
,
function
(
c
)
38
if
segment_set
[
c
]
then
39
return
c
40
else
41
return
format
(
"
%%%02X
"
,
byte
(
c
)
)
42
end
43
end
)
44
end
45 46
function
url
.
unescape
(
s
)
47
return
(
gsub
(
s
,
"
%%(%x%x)
"
,
function
(
hex
)
48
return
char
(
tonumber
(
hex
,
16
)
)
49
end
)
)
50
end
51 52
local
function
absolute_path
(
base_path
,
relative_path
)
53
if
find
(
relative_path
,
"
^/
"
)
then
54
return
relative_path
55
end
56
local
path
=
gsub
(
base_path
,
"
[^/]*$
"
,
"
"
)
57
path
=
path
.
.
relative_path
58
path
=
gsub
(
path
,
"
([^/]*%./)
"
,
function
(
s
)
59
if
s
~
=
"
./
"
then
60
return
s
61
else
62
return
"
"
63
end
64
end
)
65
path
=
gsub
(
path
,
"
/%.$
"
,
"
/
"
)
66
local
reduced
67
while
reduced
~
=
path
do
68
reduced
=
path
69
path
=
gsub
(
reduced
,
"
([^/]*/%.%./)
"
,
function
(
s
)
70
if
s
~
=
"
../../
"
then
71
return
"
"
72
else
73
return
s
74
end
75
end
)
76
end
77
path
=
gsub
(
reduced
,
"
([^/]*/%.%.)$
"
,
function
(
s
)
78
if
s
~
=
"
../..
"
then
79
return
"
"
80
else
81
return
s
82
end
83
end
)
84
return
path
85
end
86 87
function
url
.
parse
(
url
,
default
)
88
local
parsed
=
{
}
89
for
k
,
v
in
next
,
default
or
parsed
do
90
parsed
[
k
]
=
v
91
end
92
if
not
url
or
url
=
=
"
"
then
93
return
nil
,
"
invalid url
"
94
end
95
url
=
gsub
(
url
,
"
#(.*)$
"
,
function
(
f
)
96
parsed
.
fragment
=
f
97
return
"
"
98
end
)
99
url
=
gsub
(
url
,
"
^([%w][%w%+%-%.]*)%:
"
,
function
(
s
)
100
parsed
.
scheme
=
s
101
return
"
"
102
end
)
103
url
=
gsub
(
url
,
"
^//([^/]*)
"
,
function
(
n
)
104
parsed
.
authority
=
n
105
return
"
"
106
end
)
107
url
=
gsub
(
url
,
"
%?(.*)
"
,
function
(
q
)
108
parsed
.
query
=
q
109
return
"
"
110
end
)
111
url
=
gsub
(
url
,
"
%;(.*)
"
,
function
(
p
)
112
parsed
.
params
=
p
113
return
"
"
114
end
)
115
if
url
~
=
"
"
then
116
parsed
.
path
=
url
117
end
118
local
authority
=
parsed
.
authority
119
if
not
authority
then
120
return
parsed
121
end
122
authority
=
gsub
(
authority
,
"
^([^@]*)@
"
,
function
(
u
)
123
parsed
.
userinfo
=
u
124
return
"
"
125
end
)
126
authority
=
gsub
(
authority
,
"
:([^:%]]*)$
"
,
function
(
p
)
127
parsed
.
port
=
p
128
return
"
"
129
end
)
130
if
authority
~
=
"
"
then
131
parsed
.
host
=
match
(
authority
,
"
^%[(.+)%]$
"
)
or
authority
132
end
133
local
userinfo
=
parsed
.
userinfo
134
if
not
userinfo
then
135
return
parsed
136
end
137
userinfo
=
gsub
(
userinfo
,
"
:([^:]*)$
"
,
function
(
p
)
138
parsed
.
password
=
p
139
return
"
"
140
end
)
141
parsed
.
user
=
userinfo
142
return
parsed
143
end
144 145
function
url
.
build
(
parsed
)
146
local
url
=
parsed
.
path
or
"
"
147
if
parsed
.
params
then
148
url
=
url
.
.
"
;
"
.
.
parsed
.
params
149
end
150
if
parsed
.
query
then
151
url
=
url
.
.
"
?
"
.
.
parsed
.
query
152
end
153
local
authority
=
parsed
.
authority
154
if
parsed
.
host
then
155
authority
=
parsed
.
host
156
if
find
(
authority
,
"
:
"
)
then
-- IPv6?
157
authority
=
"
[
"
.
.
authority
.
.
"
]
"
158
end
159
if
parsed
.
port
then
160
authority
=
authority
.
.
"
:
"
.
.
tostring
(
parsed
.
port
)
161
end
162
local
userinfo
=
parsed
.
userinfo
163
if
parsed
.
user
then
164
userinfo
=
parsed
.
user
165
if
parsed
.
password
then
166
userinfo
=
userinfo
.
.
"
:
"
.
.
parsed
.
password
167
end
168
end
169
if
userinfo
then
authority
=
userinfo
.
.
"
@
"
.
.
authority
end
170
end
171
if
authority
then
172
url
=
"
//
"
.
.
authority
.
.
url
173
end
174
if
parsed
.
scheme
then
175
url
=
parsed
.
scheme
.
.
"
:
"
.
.
url
176
end
177
if
parsed
.
fragment
then
178
url
=
url
.
.
"
#
"
.
.
parsed
.
fragment
179
end
180
return
url
181
end
182 183
function
url
.
absolute
(
base_url
,
relative_url
)
184
local
base_parsed
185
if
type
(
base_url
)
=
=
"
table
"
then
186
base_parsed
=
base_url
187
base_url
=
url
.
build
(
base_parsed
)
188
else
189
base_parsed
=
url
.
parse
(
base_url
)
190
end
191
local
relative_parsed
=
url
.
parse
(
relative_url
)
192
if
not
base_parsed
then
193
return
relative_url
194
elseif
not
relative_parsed
then
195
return
base_url
196
elseif
relative_parsed
.
scheme
then
197
return
relative_url
198
else
199
relative_parsed
.
scheme
=
base_parsed
.
scheme
200
if
not
relative_parsed
.
authority
then
201
relative_parsed
.
authority
=
base_parsed
.
authority
202
if
not
relative_parsed
.
path
then
203
relative_parsed
.
path
=
base_parsed
.
path
204
if
not
relative_parsed
.
params
then
205
relative_parsed
.
params
=
base_parsed
.
params
206
if
not
relative_parsed
.
query
then
207
relative_parsed
.
query
=
base_parsed
.
query
208
end
209
end
210
else
211
relative_parsed
.
path
=
absolute_path
(
base_parsed
.
path
or
"
"
,
relative_parsed
.
path
)
212
end
213
end
214
return
url
.
build
(
relative_parsed
)
215
end
216
end
217 218
function
url
.
parse_path
(
path
)
219
local
parsed
=
{
}
220
path
=
path
or
"
"
221
gsub
(
path
,
"
([^/]+)
"
,
function
(
s
)
222
insert
(
parsed
,
s
)
223
end
)
224
for
i
=
1
,
#
parsed
do
225
parsed
[
i
]
=
url
.
unescape
(
parsed
[
i
]
)
226
end
227
if
sub
(
path
,
1
,
1
)
=
=
"
/
"
then
228
parsed
.
is_absolute
=
1
229
end
230
if
sub
(
path
,
-1
,
-1
)
=
=
"
/
"
then
231
parsed
.
is_directory
=
1
232
end
233
return
parsed
234
end
235 236
function
url
.
build_path
(
parsed
,
unsafe
)
237
local
path
=
"
"
238
local
n
=
#
parsed
239
if
unsafe
then
240
for
i
=
1
,
n
-1
do
241
path
=
path
.
.
parsed
[
i
]
.
.
"
/
"
242
end
243
if
n
>
0
then
244
path
=
path
.
.
parsed
[
n
]
245
if
parsed
.
is_directory
then
246
path
=
path
.
.
"
/
"
247
end
248
end
249
else
250
for
i
=
1
,
n
-1
do
251
path
=
path
.
.
protect_segment
(
parsed
[
i
]
)
.
.
"
/
"
252
end
253
if
n
>
0
then
254
path
=
path
.
.
protect_segment
(
parsed
[
n
]
)
255
if
parsed
.
is_directory
then
256
path
=
path
.
.
"
/
"
257
end
258
end
259
end
260
if
parsed
.
is_absolute
then
261
path
=
"
/
"
.
.
path
262
end
263
return
path
264
end
265 266
package
.
loaded
[
"
socket.url
"
]
=
url
267 268
return
url
269