@@ -62,9 +62,19 @@ local REASON_UPDATE = "update"
62
62
local REASON_DEPENDENCY = " dependency"
63
63
64
64
65
+ -- encodes for use as URL parameter or path component
66
+ local function urlencode (str )
67
+ return str :gsub (" [^%a%d()._~-]" , function (char )
68
+ return string.format (" %%%02X" , string.byte (char ))
69
+ end )
70
+ end
71
+ assert (urlencode (" sample text?" ) == " sample%20text%3F" )
72
+
73
+
65
74
local function get_download_url (package , reason )
66
75
local base_url = core .settings :get (" contentdb_url" )
67
- local ret = base_url .. (" /packages/%s/%s/releases/%d/download/" ):format (package .author , package .name , package .release )
76
+ local ret = base_url .. (" /packages/%s/releases/%d/download/" ):format (
77
+ package .url_part , package .release )
68
78
if reason then
69
79
ret = ret .. " ?reason=" .. reason
70
80
end
@@ -199,7 +209,7 @@ local function get_raw_dependencies(package)
199
209
local url_fmt = " /api/packages/%s/dependencies/?only_hard=1&protocol_version=%s&engine_version=%s"
200
210
local version = core .get_version ()
201
211
local base_url = core .settings :get (" contentdb_url" )
202
- local url = base_url .. url_fmt :format (package .id , core .get_max_supp_proto (), version .string )
212
+ local url = base_url .. url_fmt :format (package .url_part , core .get_max_supp_proto (), urlencode ( version .string ) )
203
213
204
214
local response = http .fetch_sync ({ url = url })
205
215
if not response .succeeded then
@@ -574,17 +584,16 @@ function store.load()
574
584
local base_url = core .settings :get (" contentdb_url" )
575
585
local url = base_url ..
576
586
" /api/packages/?type=mod&type=game&type=txp&protocol_version=" ..
577
- core .get_max_supp_proto () .. " &engine_version=" .. version .string
587
+ core .get_max_supp_proto () .. " &engine_version=" .. urlencode ( version .string )
578
588
579
589
for _ , item in pairs (core .settings :get (" contentdb_flag_blacklist" ):split (" ," )) do
580
590
item = item :trim ()
581
591
if item ~= " " then
582
- url = url .. " &hide=" .. item
592
+ url = url .. " &hide=" .. urlencode ( item )
583
593
end
584
594
end
585
595
586
- local timeout = tonumber (core .settings :get (" curl_file_download_timeout" ))
587
- local response = http .fetch_sync ({ url = url , timeout = timeout })
596
+ local response = http .fetch_sync ({ url = url })
588
597
if not response .succeeded then
589
598
return
590
599
end
@@ -594,12 +603,16 @@ function store.load()
594
603
595
604
for _ , package in pairs (store .packages_full ) do
596
605
local name_len = # package .name
606
+ -- This must match what store.update_paths() does!
607
+ package .id = package .author :lower () .. " /"
597
608
if package .type == " game" and name_len > 5 and package .name :sub (name_len - 4 ) == " _game" then
598
- package .id = package .author : lower () .. " / " .. package .name :sub (1 , name_len - 5 )
609
+ package .id = package .id .. package .name :sub (1 , name_len - 5 )
599
610
else
600
- package .id = package .author : lower () .. " / " .. package .name
611
+ package .id = package .id .. package .name
601
612
end
602
613
614
+ package .url_part = urlencode (package .author ) .. " /" .. urlencode (package .name )
615
+
603
616
if package .aliases then
604
617
for _ , alias in ipairs (package .aliases ) do
605
618
-- We currently don't support name changing
@@ -1013,9 +1026,9 @@ function store.handle_submit(this, fields)
1013
1026
end
1014
1027
1015
1028
if fields [" view_" .. i ] then
1016
- local url = (" %s/packages/%s/%s ?protocol_version=%d" ):format (
1017
- core .settings :get (" contentdb_url" ),
1018
- package . author , package . name , core .get_max_supp_proto ())
1029
+ local url = (" %s/packages/%s?protocol_version=%d" ):format (
1030
+ core .settings :get (" contentdb_url" ), package . url_part ,
1031
+ core .get_max_supp_proto ())
1019
1032
core .open_url (url )
1020
1033
return true
1021
1034
end
0 commit comments