slot0 = _G
slot1 = require("table")
slot2 = require("string")
slot3 = require("math")
slot4 = require("socket")
slot5 = require("socket.url")
slot6 = require("socket.tp")
slot7 = require("ltn12")
slot4.ftp = {}
slot8 = slot4.ftp
slot8.TIMEOUT = 60
slot9 = 21
slot8.USER = "ftp"
slot8.PASSWORD = "anonymous@anonymous.org"
slot10 = {
	__index = {}
}

function slot8.open(slot0, slot1, slot2)
	slot4 = uv4.setmetatable({
		tp = uv0.try(uv1.connect(slot0, slot1 or uv2, uv3.TIMEOUT, slot2))
	}, uv5)
	slot4.try = uv0.newtry(function ()
		uv0:close()
	end)

	return slot4
end

function slot10.__index.portconnect(slot0)
	slot0.try(slot0.server:settimeout(uv0.TIMEOUT))

	slot0.data = slot0.try(slot0.server:accept())

	slot0.try(slot0.data:settimeout(uv0.TIMEOUT))
end

function slot10.__index.pasvconnect(slot0)
	slot0.data = slot0.try(uv0.tcp())

	slot0.try(slot0.data:settimeout(uv1.TIMEOUT))
	slot0.try(slot0.data:connect(slot0.pasvt.address, slot0.pasvt.port))
end

function slot10.__index.login(slot0, slot1, slot2)
	slot0.try(slot0.tp:command("user", slot1 or uv0.USER))

	slot3, slot4 = slot0.try(slot0.tp:check({
		"2..",
		331
	}))

	if slot3 == 331 then
		slot0.try(slot0.tp:command("pass", slot2 or uv0.PASSWORD))
		slot0.try(slot0.tp:check("2.."))
	end

	return 1
end

function slot10.__index.pasv(slot0)
	slot0.try(slot0.tp:command("pasv"))

	slot1, slot2 = slot0.try(slot0.tp:check("2.."))
	slot4, slot5, slot6, slot7, slot8, slot9 = uv0.skip(2, uv1.find(slot2, "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"))

	slot0.try(slot4 and slot5 and slot6 and slot7 and slot8 and slot9, slot2)

	slot0.pasvt = {
		address = uv1.format("%d.%d.%d.%d", slot4, slot5, slot6, slot7),
		port = slot8 * 256 + slot9
	}

	if slot0.server then
		slot0.server:close()

		slot0.server = nil
	end

	return slot0.pasvt.address, slot0.pasvt.port
end

function slot10.__index.epsv(slot0)
	slot0.try(slot0.tp:command("epsv"))

	slot1, slot2 = slot0.try(slot0.tp:check("229"))
	slot4, slot5, slot6, slot7 = uv0.match(slot2, "%((.)(.-)%1(.-)%1(.-)%1%)")

	slot0.try(slot7, "invalid epsv response")

	slot0.pasvt = {
		address = slot0.tp:getpeername(),
		port = slot7
	}

	if slot0.server then
		slot0.server:close()

		slot0.server = nil
	end

	return slot0.pasvt.address, slot0.pasvt.port
end

function slot10.__index.port(slot0, slot1, slot2)
	slot0.pasvt = nil

	if not slot1 then
		slot3, slot2 = slot0.try(slot0.tp:getsockname())
		slot0.server = slot0.try(uv0.bind(slot3, 0))
		slot1, slot2 = slot0.try(slot0.server:getsockname())

		slot0.try(slot0.server:settimeout(uv1.TIMEOUT))
	end

	slot3 = slot2 % 256

	slot0.try(slot0.tp:command("port", uv2.gsub(uv2.format("%s,%d,%d", slot1, (slot2 - slot3) / 256, slot3), "%.", ",")))
	slot0.try(slot0.tp:check("2.."))

	return 1
end

function slot10.__index.eprt(slot0, slot1, slot2, slot3)
	slot0.pasvt = nil

	if not slot2 then
		slot4, slot3 = slot0.try(slot0.tp:getsockname())
		slot0.server = slot0.try(uv0.bind(slot4, 0))
		slot2, slot3 = slot0.try(slot0.server:getsockname())

		slot0.try(slot0.server:settimeout(uv1.TIMEOUT))
	end

	slot0.try(slot0.tp:command("eprt", uv2.format("|%s|%s|%d|", slot1, slot2, slot3)))
	slot0.try(slot0.tp:check("2.."))

	return 1
end

function slot10.__index.send(slot0, slot1)
	slot0.try(slot0.pasvt or slot0.server, "need port or pasv first")

	if slot0.pasvt then
		slot0:pasvconnect()
	end

	if (slot1.argument or uv0.unescape(uv1.gsub(slot1.path or "", "^[/\\]", ""))) == "" then
		slot2 = nil
	end

	slot0.try(slot0.tp:command(slot1.command or "stor", slot2))

	slot4, slot5 = slot0.try(slot0.tp:check({
		"2..",
		"1.."
	}))

	if not slot0.pasvt then
		slot0:portconnect()
	end

	slot6 = slot1.step or uv2.pump.step
	slot7 = {
		slot0.tp
	}

	slot0.try(uv2.pump.all(slot1.source, uv3.sink("close-when-done", slot0.data), function (slot0, slot1)
		if uv0.select(uv1, nil, 0)[uv2] then
			uv3 = uv4.try(uv4.tp:check("2.."))
		end

		return uv5(slot0, slot1)
	end))

	if uv1.find(slot4, "1..") then
		slot0.try(slot0.tp:check("2.."))
	end

	slot0.data:close()

	slot0.data = nil

	return uv3.skip(1, slot0.data:getstats())
end

function slot10.__index.receive(slot0, slot1)
	slot0.try(slot0.pasvt or slot0.server, "need port or pasv first")

	if slot0.pasvt then
		slot0:pasvconnect()
	end

	if (slot1.argument or uv0.unescape(uv1.gsub(slot1.path or "", "^[/\\]", ""))) == "" then
		slot2 = nil
	end

	slot0.try(slot0.tp:command(slot1.command or "retr", slot2))

	slot4, slot5 = slot0.try(slot0.tp:check({
		"1..",
		"2.."
	}))

	if slot4 >= 200 and slot4 <= 299 then
		slot1.sink(slot5)

		return 1
	end

	if not slot0.pasvt then
		slot0:portconnect()
	end

	slot0.try(uv3.pump.all(uv2.source("until-closed", slot0.data), slot1.sink, slot1.step or uv3.pump.step))

	if uv1.find(slot4, "1..") then
		slot0.try(slot0.tp:check("2.."))
	end

	slot0.data:close()

	slot0.data = nil

	return 1
end

function slot10.__index.cwd(slot0, slot1)
	slot0.try(slot0.tp:command("cwd", slot1))
	slot0.try(slot0.tp:check(250))

	return 1
end

function slot10.__index.type(slot0, slot1)
	slot0.try(slot0.tp:command("type", slot1))
	slot0.try(slot0.tp:check(200))

	return 1
end

function slot10.__index.greet(slot0)
	if uv0.find(slot0.try(slot0.tp:check({
		"1..",
		"2.."
	})), "1..") then
		slot0.try(slot0.tp:check("2.."))
	end

	return 1
end

function slot10.__index.quit(slot0)
	slot0.try(slot0.tp:command("quit"))
	slot0.try(slot0.tp:check("2.."))

	return 1
end

function slot10.__index.close(slot0)
	if slot0.data then
		slot0.data:close()
	end

	if slot0.server then
		slot0.server:close()
	end

	return slot0.tp:close()
end

function slot11(slot0)
	if slot0.url then
		slot1 = uv0.parse(slot0.url)

		for slot5, slot6 in uv1.pairs(slot0) do
			slot1[slot5] = slot6
		end

		return slot1
	else
		return slot0
	end
end

function slot12(slot0)
	slot0 = uv0(slot0)

	uv1.try(slot0.host, "missing hostname")

	slot1 = uv2.open(slot0.host, slot0.port, slot0.create)

	slot1:greet()
	slot1:login(slot0.user, slot0.password)

	if slot0.type then
		slot1:type(slot0.type)
	end

	slot1:epsv()
	slot1:quit()
	slot1:close()

	return slot1:send(slot0)
end

slot13 = {
	scheme = "ftp",
	path = "/"
}

function slot8.genericform(slot0)
	uv0.try(uv0.try(uv1.parse(slot0, uv2)).scheme == "ftp", "wrong scheme '" .. slot1.scheme .. "'")
	uv0.try(slot1.host, "missing hostname")

	if slot1.params then
		slot1.type = uv0.skip(2, uv3.find(slot1.params, "^type=(.)$"))

		uv0.try(slot1.type == "a" or slot1.type == "i", "invalid type '" .. slot1.type .. "'")
	end

	return slot1
end

function slot15(slot0, slot1)
	slot2 = uv0(slot0)
	slot2.source = uv1.source.string(slot1)

	return uv2(slot2)
end

slot8.put = slot4.protect(function (slot0, slot1)
	if uv0.type(slot0) == "string" then
		return uv1(slot0, slot1)
	else
		return uv2(slot0)
	end
end)

function slot16(slot0)
	slot0 = uv0(slot0)

	uv1.try(slot0.host, "missing hostname")

	slot1 = uv2.open(slot0.host, slot0.port, slot0.create)

	slot1:greet()
	slot1:login(slot0.user, slot0.password)

	if slot0.type then
		slot1:type(slot0.type)
	end

	slot1:epsv()
	slot1:receive(slot0)
	slot1:quit()

	return slot1:close()
end

function slot17(slot0)
	slot1 = uv0(slot0)
	slot2 = {}
	slot1.sink = uv1.sink.table(slot2)

	uv2(slot1)

	return uv3.concat(slot2)
end

slot8.command = slot4.protect(function (slot0)
	slot0 = uv0(slot0)

	uv1.try(slot0.host, "missing hostname")
	uv1.try(slot0.command, "missing command")

	slot1 = uv2.open(slot0.host, slot0.port, slot0.create)

	slot1:greet()
	slot1:login(slot0.user, slot0.password)

	if type(slot0.command) == "table" then
		slot3 = slot0.check or {}

		for slot7, slot8 in ipairs(slot0.command) do
			slot1.try(slot1.tp:command(slot8, (slot0.argument or {})[slot7]))

			if slot3[slot7] then
				slot1.try(slot1.tp:check(slot3[slot7]))
			end
		end
	else
		slot1.try(slot1.tp:command(slot0.command, slot0.argument))

		if slot0.check then
			slot1.try(slot1.tp:check(slot0.check))
		end
	end

	slot1:quit()

	return slot1:close()
end)
slot8.get = slot4.protect(function (slot0)
	if uv0.type(slot0) == "string" then
		return uv1(slot0)
	else
		return uv2(slot0)
	end
end)

return slot8
