#!/usr/bin/lua
pcall(require, "luarocks.require")
local socket = require ("socket")
local ftp = require("socket.ftp")
local http = require "socket.http"
local ltn12 = require "ltn12"
pcall(dofile,"luapaste.conf")
local Services, Options, Files = {}, {}, {}
local LP = {
default_matcher = "", --function to process response from server for url
service = DEFAULT_SERVICE or "", --service to use
language = DEFAULT_LANGUAGE or "", --language to use
services = {}, --available services (addService)
options = {}, --available options (addOption)
files = {}, --files to create textdata (fileList)
textdata = "", --what to send (fData)
description = "", --description of paste, filename or -d or stdin
run = false,
private = false,
boundary = "##ThIs_iS_ThE_BoUnDaRy##",
nick = DEFAULT_NICK or os.getenv("USER"),
concat = false,
}
-- url = "http://codepad.org/";
-- url = "http://www.rafb.net/paste/paste.php";
-- url = "http://pastebin.ca/";
-- url = "http://dpaste.com/";
-- url = "http://pastebin.osuosl.org/";
function str__mod(lhs, rhs)
if type(rhs) == "table" then
return lhs:format(unpack(rhs))
else
return lhs:gsub('%%', '%%%%'):gsub('%%%%', '%%', 1):format(rhs)
end
end
getmetatable("").__mod = str__mod
function createFormData(name, info)
local t = {
'--'..LP.boundary,
'Content-Disposition: form-data; name="%s"' % name,
'',
'%s' % info,
}
return table.concat(t, "\r\n")
end
function createEnd()
local t = {
'--'..LP.boundary..'--',
'',
}
return table.concat(t, "\r\n")
end
function fdata(file)
local fd = assert(io.open(file, "rb"))
local buf = fd:read "*a"
fd:close()
-- return buf
LP.textdata = buf
end
function fdataConcat()
local fd
local buf = ""
for k, file in pairs(LP.files) do
fd = assert(io.open(file, "rb"))
buf = buf..file.."\n"..fd:read "*a"
fd:close()
end
LP.textdata = buf
-- return buf
end
function addService(tbl, service_name, service_url, languages_tbl, body_func, url_match) --tbl = LP
tbl.services[service_name] = {
url = service_url,
languages = languages_tbl,
-- body = "",
matcher = url_match or nil, --
BODY = body_func, --function to create a body from LP.textdata (made with fData)
}
end
CODEPAD_LANGUAGES = {
"C", "C++", "D", "Haskell", "Lua", "OCaml", "PHP", "Perl", "Plain Text", "Python", "Ruby", "Scheme", "Tcl",
}
CA_LANGUAGES = {
["ASP"] = "22";
["Action Script"] = "18";
["Ada"] = "19";
["Apache Configuration"] = "20";
["Assembl (NASM)"] = "21";
["Asterisk Configuration"] = "2";
["BASH"] = "23";
["C"] = "3";
["C#"] = "9";
["C++"] = "4";
["CSS"] = "24";
["Delphi"] = "25";
["HTML 4.0 Strict"] = "26";
["Java"] = "7";
["JavaScript"] = "27";
["LISP"] = "28";
["Lua"] = "29";
["Microprocessor ASM"] = "30";
["Objective C"] = "31";
["PHP"] = "5";
["PL/I"] = "14";
["Pascal"] = "12";
["Perl"] = "6";
["Python"] = "11";
["Raw"] = "1";
["Ruby"] = "10";
["SQL Statement"] = "16";
["Scheme"] = "17";
["Visual Basic .NET"] = "32";
["Visual Basic"] = "8";
["XML Document"] = "15";
["mIRC Script"] = "13";
}
MYSTIC_LANGUAGES = {
"as3", "bash", "csharp", "cpp", "css", "delphi", "diff", "groovy", "java", "js", "javafx", "perl", "php", "text", "powershell", "python", "ruby", "scala", "sql", "vb", "xml",
}
DPASTE_LANGUAGES = {
"Python", "PythonConsole", "Sql", "DjangoTemplate", "JScript", "Css", "XmL", "Diff", "Ruby", "Rhtml", "Haskell", "Apache", "Bash", "Plain",
}
function CODEPAD_BODY() --passed to addService as body_func
local run = LP.run
local private = LP.private
if run then run = "True" else run = "False" end
if private then private = "True" else private = "False" end
local body = {
createFormData("client", "luapaste.lua"),
createFormData("run", run),
createFormData("lang", LP.language),
createFormData("private", private),
createFormData("submit", "Submit"),
createFormData("code", LP.textdata),
-- table.insert(body, createFormData("code", fdata(file)))
createEnd(),
}
return table.concat(body, "\r\n")
end
function CA_BODY()
--[[ local language = "Raw"
if LP.services[LP.service].languages[LP.language] then
language = LP.language
else
print("Invalid service, defaulting to Raw")
end
--]]
local body = {
createFormData("s", "Submit Post"),
createFormData("name", LP.nick),
createFormData("description", LP.description),
createFormData("type", LP.language),
createFormData("expiry", "15 minutes"),
createFormData("content", LP.textdata),
-- createFormData("api", "moFXXusXQpQ3zlOyYgsXuG74HzYErXkx"),
createEnd(),
}
return table.concat(body, "\r\n")
end
function MYSTIC_BODY()
local private = LP.private
if private then private = "true" else private = "false" end
local body = {
createFormData("description", 'luapaste'),
-- createFormData("", "hi"),
-- createFormData("submit", "Paste"),
-- createFormData("type", LP.language),
-- createFormData("pasteForm1_hf_0", "Submit"),
createFormData("fileExt", 'bash'),
createFormData("name", 'kiwi'),
createFormData("content", 'HI'),
-- createFormData("paste_submit", "Paste"),
createEnd(),
}
return table.concat(body, "\r\n")
end
local function DPASTE_BODY()
local body = {
-- createFormData("pasteform", ""),
createFormData("content", LP.textdata),
-- createFormData("language", LP.language),
createFormData("title", LP.description),
-- createFormData("poster", LP.nick),
--createFormData("pasteform", "Paste it"),
-- createFormData("pasteform", "post"),
createEnd(),
-- '--'..LP.boundary..'--',
-- ' ',
}
return table.concat(body, "\r\n")
end
function CODEPAD_MATCHER(response)
local url = response:match('The resource was found at (.*);')
return "\nhttp://codepad.org"..url
end
function CA_MATCHER(response)
local url = response:match('SUCCESS:(.*)')
return "\nhttp://pastebin.ca/"..url
--return response
end
local function MYSTIC_MATCHER(response)
local url = response
return "http://mysticpaste.com/view/"..url
end
function DPASTE_MATCHER(response)
local url = response
return url
end
addService(LP, "codepad", "http://codepad.org/", CODEPAD_LANGUAGES, CODEPAD_BODY, CODEPAD_MATCHER)
--moFXXusXQpQ3zlOyYgsXuG74HzYErXkx
addService(LP, "ca", "http://pastebin.ca/quiet-paste.php?api=moFXXusXQpQ3zlOyYgsXuG74HzYErXkx", CA_LANGUAGES, CA_BODY, CA_MATCHER)
addService(LP, "mystic", "http://www.mysticpaste.com/servlet/plugin", MYSTIC_LANGUAGES, MYSTIC_BODY, MYSTIC_MATCHER)
--addService(LP, "mystic", "http://www.mysticpaste.com/new", MYSTIC_LANGUAGES, MYSTIC_BODY, MYSTIC_MATCHER)
addService(LP, "dpaste", "http://dpaste.com/api/v1", DPASTE_LANGUAGES, DPASTE_BODY, DPASTE_MATCHER)
function addOption(option_name, func_name, secondary_name)
LP.options[option_name] = {on = false, params = {}, func = func_name}
if secondary_name and secondary_name ~= option_name then
LP.options[secondary_name] = {on = false, params = LP.options[option_name].params, func = func_name}
end
end
function getOptions(options)
local function resetFlags()
for k in pairs(options) do
options[k].on = false
end
end
local cur_opt
local args_left = #arg
for i = 1, #arg do
if string.match(arg[i], "^%-%-") then
s = string.gsub(arg[i], "^%-%-", "")
--if options[s] and string.len(s) > 1 then
if options[s] and #s > 1 then
options[s].on = true
cur_opt = s
else
print("--"..s.." is an invalid option")
resetFlags()
end
elseif string.match(arg[i], "^%-%a+") then
--for j = 1, arg[i]:len()-1 do
for j = 1, #arg[i]-1 do
s = string.sub(arg[i], j+1, j+1)
if options[s] then
options[s].on = true
cur_opt = s
else
print("-"..s.." is an invalid option")
resetFlags()
end
end
elseif cur_opt then
table.insert(options[cur_opt].params, arg[i])
else
-- table.insert(files, arg[i])
end
end
end
function fileList(tbl)
for k, v in ipairs(tbl) do
table.insert(LP.files, v)
end
end
addOption("f", fileList, "file")
function pickService(tbl)
LP.service = tbl[1]
end
addOption("s", pickService, "service")
function pickLanguage(tbl)
LP.language = tbl[1]
end
addOption("l", pickLanguage, "language")
function private(tbl)
LP.private = true
end
addOption("p", private, "private")
function run(tbl)
LP.run = true
end
addOption("r", run, "run")
function concat(tbl)
LP.concat = true
end
addOption("concat", concat)
function post(filename)
local body = LP.services[LP.service].BODY()
local s_url = LP.services[LP.service].url
local matcher = LP.services[LP.service].matcher or LP.default_matcher
local head = {
-- ["content-type"] = 'application/x-www-form-urlencoded; boundary=%s' % LP.boundary;
["content-type"] = 'multipart/form-data; boundary=%s' % LP.boundary;
["content-length"] = tostring(#body);
["accept"] = "text/xml", "text/html", "text/plain";
}
local response = {}
local source = ltn12.source.string(body)
local sent = 0
local function progress()
local data = source()
sent = sent + #(data or "")
local progress = sent/#body * 100
io.stdout:write("\rUploading %s: %d%" % filename % progress)
return data
end
local r, e = http.request {
method = "POST";
url = s_url;
headers = head;
source = progress;
sink = ltn12.sink.table(response);
}
print()
if not r then
return nil, tostring(e)
end
response = table.concat(response)
local err = response:match('')
if err then
return nil, err
end
local response_url = matcher(response)
return response_url
end
getOptions(LP.options)
for k in pairs(LP.options) do
if LP.options[k].on == true then
LP.options[k].func(LP.options[k].params)
end
end
--sanity checks to decide if the program should continue to upload
--service
if not LP.services[LP.service] then
print("Invalid service")
return
end
--language
if not (function()
---[[
for k, v in ipairs(LP.services[LP.service].languages) do
if v == LP.language then
return true
end
end
--]]
if LP.services[LP.service].languages[LP.language] then
return true
end
end)()
then
print("Invalid language")
return
end
if LP.concat then
fdataConcat()
local filelist = ""
for k, v in ipairs(LP.files) do
filelist = filelist..v
end
print(post(filelist))
else
for k, v in ipairs(LP.files) do
fdata(v)
print(post(v))
end
end