aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2014-06-26 21:43:14 -0300
committerHisham Muhammad <hisham@gobolinux.org>2014-06-26 21:43:14 -0300
commitc318a9a6a55ad0c50dc9ec99dbf3aa750ad5021b (patch)
treeb11a596a8d17b5239e68aac02d42dcd059b64cbf /src
parentee69f76118b6c834e2217a0d178e9dee263bfaf1 (diff)
downloadluarocks-c318a9a6a55ad0c50dc9ec99dbf3aa750ad5021b.tar.gz
luarocks-c318a9a6a55ad0c50dc9ec99dbf3aa750ad5021b.tar.bz2
luarocks-c318a9a6a55ad0c50dc9ec99dbf3aa750ad5021b.zip
HTTPS support for downloading and uploading rocks.
HTTPS is set as default for uploading. HTTP is still default for downloading to keep dependencies low and because the HTTPS code is new; might be changed in the future. See #273 and #240.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bin/luarocks4
-rwxr-xr-xsrc/bin/luarocks-admin4
-rw-r--r--src/luarocks/cfg.lua42
-rw-r--r--src/luarocks/fs/lua.lua27
-rw-r--r--src/luarocks/fs/unix/tools.lua2
-rw-r--r--src/luarocks/fs/win32/tools.lua2
-rw-r--r--src/luarocks/loader.lua22
-rw-r--r--src/luarocks/upload/api.lua110
-rw-r--r--src/luarocks/upload/multipart.lua11
-rw-r--r--src/luarocks/util.lua2
10 files changed, 180 insertions, 46 deletions
diff --git a/src/bin/luarocks b/src/bin/luarocks
index 3c9e1b74..9101e675 100755
--- a/src/bin/luarocks
+++ b/src/bin/luarocks
@@ -1,5 +1,9 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3-- this should be loaded first.
4local cfg = require("luarocks.cfg")
5cfg.init_package_paths()
6
3local loader = require("luarocks.loader") 7local loader = require("luarocks.loader")
4local command_line = require("luarocks.command_line") 8local command_line = require("luarocks.command_line")
5 9
diff --git a/src/bin/luarocks-admin b/src/bin/luarocks-admin
index e7f49c25..f49db920 100755
--- a/src/bin/luarocks-admin
+++ b/src/bin/luarocks-admin
@@ -1,5 +1,9 @@
1#!/usr/bin/env lua 1#!/usr/bin/env lua
2 2
3-- this should be loaded first.
4local cfg = require("luarocks.cfg")
5cfg.init_package_paths()
6
3local loader = require("luarocks.loader") 7local loader = require("luarocks.loader")
4local command_line = require("luarocks.command_line") 8local command_line = require("luarocks.command_line")
5 9
diff --git a/src/luarocks/cfg.lua b/src/luarocks/cfg.lua
index 2e86c3ca..8b5984ef 100644
--- a/src/luarocks/cfg.lua
+++ b/src/luarocks/cfg.lua
@@ -17,6 +17,8 @@ local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs,
17local cfg = {} 17local cfg = {}
18package.loaded["luarocks.cfg"] = cfg 18package.loaded["luarocks.cfg"] = cfg
19 19
20local util = require("luarocks.util")
21
20cfg.lua_version = _VERSION:sub(5) 22cfg.lua_version = _VERSION:sub(5)
21local version_suffix = cfg.lua_version:gsub("%.", "_") 23local version_suffix = cfg.lua_version:gsub("%.", "_")
22 24
@@ -167,7 +169,6 @@ if not site_config.LUAROCKS_FORCE_CONFIG then
167 end 169 end
168 if home_overrides then 170 if home_overrides then
169 home_config_ok = true 171 home_config_ok = true
170 local util = require("luarocks.util")
171 if home_overrides.rocks_trees then 172 if home_overrides.rocks_trees then
172 cfg.rocks_trees = nil 173 cfg.rocks_trees = nil
173 end 174 end
@@ -217,12 +218,13 @@ local defaults = {
217 "http://rocks.moonscript.org", 218 "http://rocks.moonscript.org",
218 "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/", 219 "https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/",
219 "http://luafr.org/moonrocks/", 220 "http://luafr.org/moonrocks/",
221 "http://luarocks.logiceditor.com/rocks",
220 } 222 }
221 }, 223 },
222 disabled_servers = {}, 224 disabled_servers = {},
223 225
224 upload = { 226 upload = {
225 server = "rocks.moonscript.org", 227 server = "https://rocks.moonscript.org",
226 tool_version = "0.0.1", 228 tool_version = "0.0.1",
227 api_version = "1", 229 api_version = "1",
228 }, 230 },
@@ -527,20 +529,28 @@ local cfg_mt = {
527} 529}
528setmetatable(cfg, cfg_mt) 530setmetatable(cfg, cfg_mt)
529 531
532function cfg.make_paths_from_tree(tree)
533 local lua_path, lib_path, bin_path
534 if type(tree) == "string" then
535 lua_path = tree..cfg.lua_modules_path
536 lib_path = tree..cfg.lib_modules_path
537 bin_path = tree.."/bin"
538 else
539 lua_path = tree.lua_dir or tree.root..cfg.lua_modules_path
540 lib_path = tree.lib_dir or tree.root..cfg.lib_modules_path
541 bin_path = tree.bin_dir or tree.root.."/bin"
542 end
543 return lua_path, lib_path, bin_path
544end
545
530function cfg.package_paths() 546function cfg.package_paths()
531 local new_path, new_cpath, new_bin = {}, {}, {} 547 local new_path, new_cpath, new_bin = {}, {}, {}
532 for _,tree in ipairs(cfg.rocks_trees) do 548 for _,tree in ipairs(cfg.rocks_trees) do
533 if type(tree) == "string" then 549 local lua_path, lib_path, bin_path = cfg.make_paths_from_tree(tree)
534 table.insert(new_path, tree..cfg.lua_modules_path.."/?.lua") 550 table.insert(new_path, lua_path.."/?.lua")
535 table.insert(new_path, tree..cfg.lua_modules_path.."/?/init.lua") 551 table.insert(new_path, lua_path.."/?/init.lua")
536 table.insert(new_cpath, tree..cfg.lib_modules_path.."/?."..cfg.lib_extension) 552 table.insert(new_cpath, lib_path.."/?."..cfg.lib_extension)
537 table.insert(new_bin, tree.."/bin") 553 table.insert(new_bin, bin_path)
538 else
539 table.insert(new_path, (tree.lua_dir or tree.root..cfg.lua_modules_path).."/?.lua")
540 table.insert(new_path, (tree.lua_dir or tree.root..cfg.lua_modules_path).."/?/init.lua")
541 table.insert(new_cpath, (tree.lib_dir or tree.root..cfg.lib_modules_path).."/?."..cfg.lib_extension)
542 table.insert(new_bin, (tree.bin_dir or tree.root.."/bin"))
543 end
544 end 554 end
545 if extra_luarocks_module_dir then 555 if extra_luarocks_module_dir then
546 table.insert(new_path, extra_luarocks_module_dir) 556 table.insert(new_path, extra_luarocks_module_dir)
@@ -548,6 +558,12 @@ function cfg.package_paths()
548 return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator) 558 return table.concat(new_path, ";"), table.concat(new_cpath, ";"), table.concat(new_bin, cfg.export_path_separator)
549end 559end
550 560
561function cfg.init_package_paths()
562 local lr_path, lr_cpath, lr_bin = cfg.package_paths()
563 package.path = util.remove_path_dupes(package.path .. ";" .. lr_path, ";")
564 package.cpath = util.remove_path_dupes(package.cpath .. ";" .. lr_cpath, ";")
565end
566
551function cfg.which_config() 567function cfg.which_config()
552 return sys_config_file, sys_config_ok, home_config_file, home_config_ok 568 return sys_config_file, sys_config_ok, home_config_file, home_config_ok
553end 569end
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua
index f18deac3..b2619051 100644
--- a/src/luarocks/fs/lua.lua
+++ b/src/luarocks/fs/lua.lua
@@ -592,7 +592,7 @@ local function request(url, method, http, loop_control)
592 loop_control[url] = true 592 loop_control[url] = true
593 return request(location, method, redirect_protocols[protocol], loop_control) 593 return request(location, method, redirect_protocols[protocol], loop_control)
594 else 594 else
595 return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support." 595 return nil, "URL redirected to unsupported protocol - install luasec to get HTTPS support.", "https"
596 end 596 end
597 end 597 end
598 return nil, err 598 return nil, err
@@ -614,7 +614,7 @@ local function http_request(url, http, cached)
614 return true 614 return true
615 end 615 end
616 if not result then 616 if not result then
617 return nil, status 617 return nil, status, headers
618 end 618 end
619 end 619 end
620 end 620 end
@@ -629,10 +629,12 @@ local function http_request(url, http, cached)
629 end 629 end
630 return table.concat(result) 630 return table.concat(result)
631 else 631 else
632 return nil, status 632 return nil, status, headers
633 end 633 end
634end 634end
635 635
636local downloader_warning = false
637
636--- Download a remote file. 638--- Download a remote file.
637-- @param url string: URL to be fetched. 639-- @param url string: URL to be fetched.
638-- @param filename string or nil: this function attempts to detect the 640-- @param filename string or nil: this function attempts to detect the
@@ -647,20 +649,27 @@ function fs_lua.download(url, filename, cache)
647 649
648 filename = fs.absolute_name(filename or dir.base_name(url)) 650 filename = fs.absolute_name(filename or dir.base_name(url))
649 651
650 local content, err 652 local content, err, https_err
651 if util.starts_with(url, "http:") then 653 if util.starts_with(url, "http:") then
652 content, err = http_request(url, http, cache and filename) 654 content, err, https_err = http_request(url, http, cache and filename)
653 elseif util.starts_with(url, "ftp:") then 655 elseif util.starts_with(url, "ftp:") then
654 content, err = ftp.get(url) 656 content, err = ftp.get(url)
655 elseif util.starts_with(url, "https:") then 657 elseif util.starts_with(url, "https:") then
656 if luasec_ok then 658 if luasec_ok then
657 content, err = http_request(url, https, cache and filename) 659 content, err = http_request(url, https, cache and filename)
658 else 660 else
659 err = "Unsupported protocol - install luasec to get HTTPS support." 661 https_err = true
660 end 662 end
661 else 663 else
662 err = "Unsupported protocol" 664 err = "Unsupported protocol"
663 end 665 end
666 if https_err then
667 if not downloader_warning then
668 util.printerr("Warning: falling back to "..cfg.downloader.." - install luasec to get native HTTPS support")
669 downloader_warning = true
670 end
671 return fs.use_downloader(url, filename, cache)
672 end
664 if cache and content == true then 673 if cache and content == true then
665 return true, filename 674 return true, filename
666 end 675 end
@@ -674,6 +683,12 @@ function fs_lua.download(url, filename, cache)
674 return true, filename 683 return true, filename
675end 684end
676 685
686else --...if socket_ok == false then
687
688function fs_lua.download(url, filename, cache)
689 return fs.use_downloader(url, filename, cache)
690end
691
677end 692end
678--------------------------------------------------------------------- 693---------------------------------------------------------------------
679-- MD5 functions 694-- MD5 functions
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua
index 69466931..f36e815a 100644
--- a/src/luarocks/fs/unix/tools.lua
+++ b/src/luarocks/fs/unix/tools.lua
@@ -238,7 +238,7 @@ end
238-- filename can be given explicitly as this second argument. 238-- filename can be given explicitly as this second argument.
239-- @return (boolean, string): true and the filename on success, 239-- @return (boolean, string): true and the filename on success,
240-- false and the error message on failure. 240-- false and the error message on failure.
241function tools.download(url, filename, cache) 241function tools.use_downloader(url, filename, cache)
242 assert(type(url) == "string") 242 assert(type(url) == "string")
243 assert(type(filename) == "string" or not filename) 243 assert(type(filename) == "string" or not filename)
244 244
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua
index a8b2a1db..f970f36a 100644
--- a/src/luarocks/fs/win32/tools.lua
+++ b/src/luarocks/fs/win32/tools.lua
@@ -248,7 +248,7 @@ end
248-- filename can be given explicitly as this second argument. 248-- filename can be given explicitly as this second argument.
249-- @return (boolean, string): true and the filename on success, 249-- @return (boolean, string): true and the filename on success,
250-- false and the error message on failure. 250-- false and the error message on failure.
251function tools.download(url, filename, cache) 251function tools.use_downloader(url, filename, cache)
252 assert(type(url) == "string") 252 assert(type(url) == "string")
253 assert(type(filename) == "string" or not filename) 253 assert(type(filename) == "string" or not filename)
254 254
diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua
index 3d36723f..c200d5ec 100644
--- a/src/luarocks/loader.lua
+++ b/src/luarocks/loader.lua
@@ -128,10 +128,11 @@ end
128-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree 128-- (eg "luasocket"), the version (eg "2.0.2-1"), the path of the rocks tree
129-- (eg "/usr/local"), and the numeric index of the matching entry, so the 129-- (eg "/usr/local"), and the numeric index of the matching entry, so the
130-- filter function can know if the matching module was the first entry or not. 130-- filter function can know if the matching module was the first entry or not.
131-- @return string, string, string: name of the rock containing the module 131-- @return string, string, string, (string or table):
132-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), 132-- * name of the rock containing the module (eg. "luasocket")
133-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is 133-- * version of the rock (eg. "2.0.2-1")
134-- stored versioned). 134-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
135-- * tree of the module (string or table in `rocks_trees` format)
135local function select_module(module, filter_module_name) 136local function select_module(module, filter_module_name)
136 --assert(type(module) == "string") 137 --assert(type(module) == "string")
137 --assert(type(filter_module_name) == "function") 138 --assert(type(filter_module_name) == "function")
@@ -155,7 +156,7 @@ local function select_module(module, filter_module_name)
155 return name, version, module_name 156 return name, version, module_name
156 end 157 end
157 version = deps.parse_version(version) 158 version = deps.parse_version(version)
158 table.insert(providers, {name = name, version = version, module_name = module_name}) 159 table.insert(providers, {name = name, version = version, module_name = module_name, tree = tree})
159 end 160 end
160 end 161 end
161 end 162 end
@@ -163,16 +164,17 @@ local function select_module(module, filter_module_name)
163 if next(providers) then 164 if next(providers) then
164 table.sort(providers, sort_versions) 165 table.sort(providers, sort_versions)
165 local first = providers[1] 166 local first = providers[1]
166 return first.name, first.version.string, first.module_name 167 return first.name, first.version.string, first.module_name, first.tree
167 end 168 end
168end 169end
169 170
170--- Search for a module 171--- Search for a module
171-- @param module string: module name (eg. "socket.core") 172-- @param module string: module name (eg. "socket.core")
172-- @return string, string, string: name of the rock containing the module 173-- @return string, string, string, (string or table):
173-- (eg. "luasocket"), version of the rock (eg. "2.0.2-1"), 174-- * name of the rock containing the module (eg. "luasocket")
174-- name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is 175-- * version of the rock (eg. "2.0.2-1")
175-- stored versioned). 176-- * name of the module (eg. "socket.core", or "socket.core_2_0_2" if file is stored versioned).
177-- * tree of the module (string or table in `rocks_trees` format)
176local function pick_module(module) 178local function pick_module(module)
177 return 179 return
178 select_module(module, function(module_name, name, version, tree, i) 180 select_module(module, function(module_name, name, version, tree, i)
diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua
index 818d293e..4ab311f2 100644
--- a/src/luarocks/upload/api.lua
+++ b/src/luarocks/upload/api.lua
@@ -5,6 +5,7 @@ local cfg = require("luarocks.cfg")
5local fs = require("luarocks.fs") 5local fs = require("luarocks.fs")
6local util = require("luarocks.util") 6local util = require("luarocks.util")
7local persist = require("luarocks.persist") 7local persist = require("luarocks.persist")
8local multipart = require("luarocks.upload.multipart")
8 9
9local Api = {} 10local Api = {}
10 11
@@ -43,7 +44,7 @@ end
43function Api:check_version() 44function Api:check_version()
44 if not self._server_tool_version then 45 if not self._server_tool_version then
45 local tool_version = cfg.upload.tool_version 46 local tool_version = cfg.upload.tool_version
46 local res, err = self:request("http://" .. tostring(self.config.server) .. "/api/tool_version", { 47 local res, err = self:request(tostring(self.config.server) .. "/api/tool_version", {
47 current = tool_version 48 current = tool_version
48 }) 49 })
49 if not res then 50 if not res then
@@ -80,12 +81,11 @@ end
80 81
81function Api:raw_method(path, ...) 82function Api:raw_method(path, ...)
82 self:check_version() 83 self:check_version()
83 local url = "http://" .. tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path) 84 local url = tostring(self.config.server) .. "/api/" .. tostring(cfg.upload.api_version) .. "/" .. tostring(self.config.key) .. "/" .. tostring(path)
84 return self:request(url, ...) 85 return self:request(url, ...)
85end 86end
86 87
87local function encode_query_string(t, sep) 88local function encode_query_string(t, sep)
88 local url = require("socket.url")
89 if sep == nil then 89 if sep == nil then
90 sep = "&" 90 sep = "&"
91 end 91 end
@@ -95,9 +95,9 @@ local function encode_query_string(t, sep)
95 if type(k) == "number" and type(v) == "table" then 95 if type(k) == "number" and type(v) == "table" then
96 k, v = v[1], v[2] 96 k, v = v[1], v[2]
97 end 97 end
98 buf[i + 1] = url.escape(k) 98 buf[i + 1] = multipart.url_escape(k)
99 buf[i + 2] = "=" 99 buf[i + 2] = "="
100 buf[i + 3] = url.escape(v) 100 buf[i + 3] = multipart.url_escape(v)
101 buf[i + 4] = sep 101 buf[i + 4] = sep
102 i = i + 4 102 i = i + 4
103 end 103 end
@@ -116,12 +116,99 @@ local function require_json()
116 return nil 116 return nil
117end 117end
118 118
119local ltn12_ok, ltn12 = pcall(require, "ltn12")
120if not ltn12_ok then -- If not using LuaSocket and/or LuaSec...
121
122function Api:request(url, params, post_params)
123 local vars = cfg.variables
124 local json_ok, json = require_json()
125 if not json_ok then return nil, "A JSON library is required for this command." end
126
127 if cfg.downloader == "wget" then
128 local curl_ok = fs.execute_quiet(vars.CURL, "--version")
129 if not curl_ok then
130 return nil, "Missing network helper program 'curl'.\nMake sure 'curl' is installed and available from your path."
131 end
132 end
133
134 if not self.config.key then
135 return nil, "Must have API key before performing any actions."
136 end
137 local body
138 local headers = {}
139 if params and next(params) then
140 url = url .. ("?" .. encode_query_string(params))
141 end
142 local method = "GET"
143 local out
144 local tmpfile = os.tmpname()
145 if post_params then
146 method = "POST"
147 local curl_cmd = fs.Q(vars.CURL).." -f -k -L --user-agent '"..cfg.user_agent.." via curl' "
148 for k,v in pairs(post_params) do
149 local var = v
150 if type(v) == "table" then
151 var = "@"..v.fname
152 end
153 curl_cmd = curl_cmd .. "--form '"..k.."="..var.."' "
154 end
155 if cfg.connection_timeout and cfg.connection_timeout > 0 then
156 curl_cmd = curl_cmd .. "--connect-timeout "..tonumber(cfg.connection_timeout).." "
157 end
158 ok = fs.execute_string(curl_cmd..fs.Q(url).." 2> /dev/null 1> "..fs.Q(tmpfile))
159 else
160 local ok, err = fs.download(url, tmpfile)
161 if not ok then
162 return nil, "API failure: " .. tostring(err) .. " - " .. tostring(url)
163 end
164 end
165
166 local tmpfd = io.open(tmpfile)
167 if not tmpfd then
168 os.remove(tmpfile)
169 return nil, "API failure reading temporary file - " .. tostring(url)
170 end
171 out = tmpfd:read("*a")
172 tmpfd:close()
173 os.remove(tmpfile)
174
175 if self.debug then
176 util.printout("[" .. tostring(method) .. " via curl] " .. tostring(url) .. " ... ")
177 end
178
179 return json.decode(out)
180end
181
182else -- use LuaSocket and LuaSec
183
184local warned_luasec = false
185
119function Api:request(url, params, post_params) 186function Api:request(url, params, post_params)
120 local http_ok, http = pcall(require, "socket.http")
121 local ltn12_ok, ltn12 = pcall(require, "ltn12")
122 local json_ok, json = require_json() 187 local json_ok, json = require_json()
123 if not http_ok then return nil, "LuaSocket is required for this command." end
124 if not json_ok then return nil, "A JSON library is required for this command." end 188 if not json_ok then return nil, "A JSON library is required for this command." end
189 local server = tostring(self.config.server)
190 local http_ok, http
191 local via = "luasocket"
192 if server:match("^https://") then
193 http_ok, http = pcall(require, "ssl.https")
194 if http_ok then
195 via = "luasec"
196 else
197 if not warned_luasec then
198 util.printerr("LuaSec is not available; using plain HTTP. Install 'luasec' to enable HTTPS.")
199 warned_luasec = true
200 end
201 http_ok, http = pcall(require, "socket.http")
202 server = server:gsub("^https", "http")
203 url = url:gsub("^https", "http")
204 via = "luasocket"
205 end
206 else
207 http_ok, http = pcall(require, "socket.http")
208 end
209 if not http_ok then
210 return nil, "Failed loading socket library!"
211 end
125 212
126 if not self.config.key then 213 if not self.config.key then
127 return nil, "Must have API key before performing any actions." 214 return nil, "Must have API key before performing any actions."
@@ -132,7 +219,6 @@ function Api:request(url, params, post_params)
132 url = url .. ("?" .. encode_query_string(params)) 219 url = url .. ("?" .. encode_query_string(params))
133 end 220 end
134 if post_params then 221 if post_params then
135 local multipart = require("luarocks.upload.multipart")
136 local boundary 222 local boundary
137 body, boundary = multipart.encode(post_params) 223 body, boundary = multipart.encode(post_params)
138 headers["Content-length"] = #body 224 headers["Content-length"] = #body
@@ -140,7 +226,7 @@ function Api:request(url, params, post_params)
140 end 226 end
141 local method = post_params and "POST" or "GET" 227 local method = post_params and "POST" or "GET"
142 if self.debug then 228 if self.debug then
143 util.printout("[" .. tostring(method) .. "] " .. tostring(url) .. " ... ") 229 util.printout("[" .. tostring(method) .. " via "..via.."] " .. tostring(url) .. " ... ")
144 end 230 end
145 local out = {} 231 local out = {}
146 local _, status = http.request({ 232 local _, status = http.request({
@@ -159,6 +245,8 @@ function Api:request(url, params, post_params)
159 return json.decode(table.concat(out)) 245 return json.decode(table.concat(out))
160end 246end
161 247
248end
249
162function api.new(flags, name) 250function api.new(flags, name)
163 local self = {} 251 local self = {}
164 setmetatable(self, { __index = Api }) 252 setmetatable(self, { __index = Api })
@@ -169,7 +257,7 @@ function api.new(flags, name)
169 self.debug = flags["debug"] 257 self.debug = flags["debug"]
170 if not self.config.key then 258 if not self.config.key then
171 return nil, "You need an API key to upload rocks.\n" .. 259 return nil, "You need an API key to upload rocks.\n" ..
172 "Navigate to http://"..self.config.server.."/settings to get a key\n" .. 260 "Navigate to "..self.config.server.."/settings to get a key\n" ..
173 "and then pass it through the --api-key=<key> flag." 261 "and then pass it through the --api-key=<key> flag."
174 end 262 end
175 if flags["api-key"] then 263 if flags["api-key"] then
diff --git a/src/luarocks/upload/multipart.lua b/src/luarocks/upload/multipart.lua
index 95afe1b3..56776570 100644
--- a/src/luarocks/upload/multipart.lua
+++ b/src/luarocks/upload/multipart.lua
@@ -1,14 +1,19 @@
1 1
2local multipart = {} 2local multipart = {}
3 3
4local url = require("socket.url")
5
6local File = {} 4local File = {}
7 5
8local unpack = unpack or table.unpack 6local unpack = unpack or table.unpack
9 7
10math.randomseed(os.time()) 8math.randomseed(os.time())
11 9
10-- socket.url.escape(s) from LuaSocket 3.0rc1
11function multipart.url_escape(s)
12 return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
13 return string.format("%%%02x", string.byte(c))
14 end))
15end
16
12function File:mime() 17function File:mime()
13 if not self.mimetype then 18 if not self.mimetype then
14 local mimetypes_ok, mimetypes = pcall(require, "mimetypes") 19 local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
@@ -64,7 +69,7 @@ function multipart.encode(params)
64 local chunks = {} 69 local chunks = {}
65 for _, tuple in ipairs(tuples) do 70 for _, tuple in ipairs(tuples) do
66 local k,v = unpack(tuple) 71 local k,v = unpack(tuple)
67 k = url.escape(k) 72 k = multipart.url_escape(k)
68 local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' } 73 local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
69 local content 74 local content
70 if type(v) == "table" and v.__class == File then 75 if type(v) == "table" and v.__class == File then
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index 1bf6533b..8772883b 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -392,7 +392,7 @@ function util.deps_mode_help(program)
392end 392end
393 393
394function util.see_help(command, program) 394function util.see_help(command, program)
395 return "See '"..util.this_program(program or "luarocks")..' help '..command.."'." 395 return "See '"..util.this_program(program or "luarocks")..' help'..(command and " "..command or "").."'."
396end 396end
397 397
398-- from http://lua-users.org/wiki/SplitJoin 398-- from http://lua-users.org/wiki/SplitJoin