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 | |||
