aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorV1K1NGbg <victor@ilchev.com>2024-07-31 14:46:02 +0300
committerV1K1NGbg <victor@ilchev.com>2024-08-05 20:51:31 +0300
commit09eea7b88d1566991b74f618537b97b68ddba51e (patch)
tree0677c4fae1fd2b38ff828836268935a879ad5cd6
parent3d2135842a703edae632f4623f466c0c8132ffb2 (diff)
downloadluarocks-09eea7b88d1566991b74f618537b97b68ddba51e.tar.gz
luarocks-09eea7b88d1566991b74f618537b97b68ddba51e.tar.bz2
luarocks-09eea7b88d1566991b74f618537b97b68ddba51e.zip
started multipart
-rw-r--r--src/luarocks/upload/multipart-original.lua (renamed from src/luarocks/upload/multipart.lua)0
-rw-r--r--src/luarocks/upload/multipart.tl111
2 files changed, 111 insertions, 0 deletions
diff --git a/src/luarocks/upload/multipart.lua b/src/luarocks/upload/multipart-original.lua
index 790e368f..790e368f 100644
--- a/src/luarocks/upload/multipart.lua
+++ b/src/luarocks/upload/multipart-original.lua
diff --git a/src/luarocks/upload/multipart.tl b/src/luarocks/upload/multipart.tl
new file mode 100644
index 00000000..b2cfe8de
--- /dev/null
+++ b/src/luarocks/upload/multipart.tl
@@ -0,0 +1,111 @@
1
2local record multipart
3end
4
5local record File
6 mimetype: string --! TEMP
7 fname: string
8end
9
10-- socket.url.escape(s) from LuaSocket 3.0rc1 --?
11function multipart.url_escape(s: string): string
12 return (string.gsub(s, "([^A-Za-z0-9_])", function(c: string): string
13 return string.format("%%%02x", string.byte(c))
14 end))
15end
16
17function File:mime()
18 if not self.mimetype then
19 local mimetypes_ok, mimetypes = pcall(require, "mimetypes")
20 if mimetypes_ok then
21 self.mimetype = mimetypes.guess(self.fname)
22 end
23 self.mimetype = self.mimetype or "application/octet-stream"
24 end
25 return self.mimetype
26end
27
28function File:content(): string, string
29 local fd = io.open(self.fname, "rb")
30 if not fd then
31 return nil, "Failed to open file: "..self.fname
32 end
33 local data = fd:read("*a")
34 fd:close()
35 return data
36end
37
38local function rand_string(len): string
39 local shuffled: {integer} = {}
40 for i = 1, len do
41 local r = math.random(97, 122)
42 if math.random() >= 0.5 then
43 r = r - 32
44 end
45 shuffled[i as integer] = r --! cast because math.tointeger returns an integer?
46 end
47 return string.char(table.unpack(shuffled))
48end
49
50-- multipart encodes params
51-- returns encoded string,boundary
52-- params is an a table of tuple tables:
53-- params = {
54-- {key1, value2},
55-- {key2, value2},
56-- key3: value3
57-- }
58function multipart.encode(params: ) --? arain a table that is indexed by string and number
59 local tuples = { }
60 for i = 1, #params do
61 tuples[i] = params[i]
62 end
63 for k,v in pairs(params) do
64 if k is string then
65 table.insert(tuples, {k, v})
66 end
67 end
68 local chunks = {}
69 for _, tuple in ipairs(tuples) do
70 local k,v = table.unpack(tuple)
71 k = multipart.url_escape(k)
72 local buffer = { 'Content-Disposition: form-data; name="' .. k .. '"' }
73 local content
74 if type(v) == "table" and v.__class == File then
75 buffer[1] = buffer[1] .. ('; filename="' .. v.fname:gsub(".*[/\\]", "") .. '"')
76 table.insert(buffer, "Content-type: " .. v:mime())
77 content = v:content()
78 else
79 content = v
80 end
81 table.insert(buffer, "")
82 table.insert(buffer, content)
83 table.insert(chunks, table.concat(buffer, "\r\n"))
84 end
85 local boundary
86 while not boundary do
87 boundary = "Boundary" .. rand_string(16)
88 for _, chunk in ipairs(chunks) do
89 if chunk:find(boundary) then
90 boundary = nil
91 break
92 end
93 end
94 end
95 local inner = "\r\n--" .. boundary .. "\r\n"
96 return table.concat({ "--", boundary, "\r\n",
97 table.concat(chunks, inner),
98 "\r\n", "--", boundary, "--", "\r\n" }), boundary
99end
100
101function multipart.new_file(fname, mime)
102 local self = {}
103 setmetatable(self, { __index = File })
104 self.__class = File
105 self.fname = fname
106 self.mimetype = mime
107 return self
108end
109
110return multipart
111