diff options
author | V1K1NGbg <victor@ilchev.com> | 2024-07-31 14:46:02 +0300 |
---|---|---|
committer | V1K1NGbg <victor@ilchev.com> | 2024-08-05 20:51:31 +0300 |
commit | 09eea7b88d1566991b74f618537b97b68ddba51e (patch) | |
tree | 0677c4fae1fd2b38ff828836268935a879ad5cd6 | |
parent | 3d2135842a703edae632f4623f466c0c8132ffb2 (diff) | |
download | luarocks-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.tl | 111 |
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 | |||
2 | local record multipart | ||
3 | end | ||
4 | |||
5 | local record File | ||
6 | mimetype: string --! TEMP | ||
7 | fname: string | ||
8 | end | ||
9 | |||
10 | -- socket.url.escape(s) from LuaSocket 3.0rc1 --? | ||
11 | function 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)) | ||
15 | end | ||
16 | |||
17 | function 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 | ||
26 | end | ||
27 | |||
28 | function 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 | ||
36 | end | ||
37 | |||
38 | local 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)) | ||
48 | end | ||
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 | -- } | ||
58 | function 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 | ||
99 | end | ||
100 | |||
101 | function 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 | ||
108 | end | ||
109 | |||
110 | return multipart | ||
111 | |||