Build with Lua 5.2 without LUA_COMPAT_MODULE flag.

LUASOCKET_USE_GLOBAL flag enable create global variables when load socket/mime modules.
This commit is contained in:
moteus 2013-05-27 12:45:09 +04:00
parent bd51d8c1a5
commit 920bc97629
14 changed files with 179 additions and 115 deletions

View File

@ -15,27 +15,27 @@ local socket = require("socket")
local url = require("socket.url")
local tp = require("socket.tp")
local ltn12 = require("ltn12")
module("socket.ftp")
socket.ftp = {}
local _M = socket.ftp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
-- timeout in seconds before the program gives up on a connection
TIMEOUT = 60
_M.TIMEOUT = 60
-- default port for ftp service
PORT = 21
_M.PORT = 21
-- this is the default anonymous password. used when no password is
-- provided in url. should be changed to your e-mail.
USER = "ftp"
PASSWORD = "anonymous@anonymous.org"
_M.USER = "ftp"
_M.PASSWORD = "anonymous@anonymous.org"
-----------------------------------------------------------------------------
-- Low level FTP API
-----------------------------------------------------------------------------
local metat = { __index = {} }
function open(server, port, create)
local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT, create))
function _M.open(server, port, create)
local tp = socket.try(tp.connect(server, port or _M.PORT, _M.TIMEOUT, create))
local f = base.setmetatable({ tp = tp }, metat)
-- make sure everything gets closed in an exception
f.try = socket.newtry(function() f:close() end)
@ -43,22 +43,22 @@ function open(server, port, create)
end
function metat.__index:portconnect()
self.try(self.server:settimeout(TIMEOUT))
self.try(self.server:settimeout(_M.TIMEOUT))
self.data = self.try(self.server:accept())
self.try(self.data:settimeout(TIMEOUT))
self.try(self.data:settimeout(_M.TIMEOUT))
end
function metat.__index:pasvconnect()
self.data = self.try(socket.tcp())
self.try(self.data:settimeout(TIMEOUT))
self.try(self.data:settimeout(_M.TIMEOUT))
self.try(self.data:connect(self.pasvt.ip, self.pasvt.port))
end
function metat.__index:login(user, password)
self.try(self.tp:command("user", user or USER))
self.try(self.tp:command("user", user or _M.USER))
local code, reply = self.try(self.tp:check{"2..", 331})
if code == 331 then
self.try(self.tp:command("pass", password or PASSWORD))
self.try(self.tp:command("pass", password or _M.PASSWORD))
self.try(self.tp:check("2.."))
end
return 1
@ -87,7 +87,7 @@ function metat.__index:port(ip, port)
ip, port = self.try(self.tp:getcontrol():getsockname())
self.server = self.try(socket.bind(ip, 0))
ip, port = self.try(self.server:getsockname())
self.try(self.server:settimeout(TIMEOUT))
self.try(self.server:settimeout(_M.TIMEOUT))
end
local pl = math.mod(port, 256)
local ph = (port - pl)/256
@ -199,7 +199,7 @@ end
local function tput(putt)
putt = override(putt)
socket.try(putt.host, "missing hostname")
local f = open(putt.host, putt.port, putt.create)
local f = _M.open(putt.host, putt.port, putt.create)
f:greet()
f:login(putt.user, putt.password)
if putt.type then f:type(putt.type) end
@ -234,7 +234,7 @@ local function sput(u, body)
return tput(putt)
end
put = socket.protect(function(putt, body)
_M.put = socket.protect(function(putt, body)
if base.type(putt) == "string" then return sput(putt, body)
else return tput(putt) end
end)
@ -242,7 +242,7 @@ end)
local function tget(gett)
gett = override(gett)
socket.try(gett.host, "missing hostname")
local f = open(gett.host, gett.port, gett.create)
local f = _M.open(gett.host, gett.port, gett.create)
f:greet()
f:login(gett.user, gett.password)
if gett.type then f:type(gett.type) end
@ -260,7 +260,7 @@ local function sget(u)
return table.concat(t)
end
command = socket.protect(function(cmdt)
_M.command = socket.protect(function(cmdt)
cmdt = override(cmdt)
socket.try(cmdt.host, "missing hostname")
socket.try(cmdt.command, "missing command")
@ -273,8 +273,9 @@ command = socket.protect(function(cmdt)
return f:close()
end)
get = socket.protect(function(gett)
_M.get = socket.protect(function(gett)
if base.type(gett) == "string" then return sget(gett)
else return tget(gett) end
end)
return _M

View File

@ -3,9 +3,11 @@
-- LuaSocket toolkit.
-- Author: Diego Nehab
-----------------------------------------------------------------------------
module("socket.headers")
local socket = require("socket")
socket.headers = {}
local _M = socket.headers
canonic = {
_M.canonic = {
["accept"] = "Accept",
["accept-charset"] = "Accept-Charset",
["accept-encoding"] = "Accept-Encoding",
@ -98,3 +100,5 @@ canonic = {
["www-authenticate"] = "WWW-Authenticate",
["x-mailer"] = "X-Mailer",
}
return _M

View File

@ -15,7 +15,8 @@ local string = require("string")
local headers = require("socket.headers")
local base = _G
local table = require("table")
module("socket.http")
socket.http = {}
local _M = socket.http
-----------------------------------------------------------------------------
-- Program constants
@ -23,9 +24,9 @@ module("socket.http")
-- connection timeout in seconds
TIMEOUT = 60
-- default port for document retrieval
PORT = 80
_M.PORT = 80
-- user agent field sent in request
USERAGENT = socket._VERSION
_M.USERAGENT = socket._VERSION
-----------------------------------------------------------------------------
-- Reads MIME headers from a connection, unfolding where needed
@ -105,15 +106,15 @@ end
-----------------------------------------------------------------------------
local metat = { __index = {} }
function open(host, port, create)
function _M.open(host, port, create)
-- create socket with user connect function, or with default
local c = socket.try((create or socket.tcp)())
local h = base.setmetatable({ c = c }, metat)
-- create finalized try
h.try = socket.newtry(function() h:close() end)
-- set timeout before connecting
h.try(c:settimeout(TIMEOUT))
h.try(c:connect(host, port or PORT))
h.try(c:settimeout(_M.TIMEOUT))
h.try(c:connect(host, port or _M.PORT))
-- here everything worked
return h
end
@ -209,7 +210,7 @@ end
local function adjustheaders(reqt)
-- default headers
local lower = {
["user-agent"] = USERAGENT,
["user-agent"] = _M.USERAGENT,
["host"] = reqt.host,
["connection"] = "close, TE",
["te"] = "trailers"
@ -229,7 +230,7 @@ end
-- default url parts
local default = {
host = "",
port = PORT,
port = _M.PORT,
path ="/",
scheme = "http"
}
@ -270,7 +271,7 @@ end
-- forward declarations
local trequest, tredirect
function tredirect(reqt, location)
--[[local]] function tredirect(reqt, location)
local result, code, headers, status = trequest {
-- the RFC says the redirect URL has to be absolute, but some
-- servers do not respect that
@ -288,11 +289,11 @@ function tredirect(reqt, location)
return result, code, headers, status
end
function trequest(reqt)
--[[local]] function trequest(reqt)
-- we loop until we get what we want, or
-- until we are sure there is no way to get it
local nreqt = adjustrequest(reqt)
local h = open(nreqt.host, nreqt.port, nreqt.create)
local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
-- send request line and headers
h:sendrequestline(nreqt.method, nreqt.uri)
h:sendheaders(nreqt.headers)
@ -345,7 +346,9 @@ local function srequest(u, b)
return table.concat(t), code, headers, status
end
request = socket.protect(function(reqt, body)
_M.request = socket.protect(function(reqt, body)
if base.type(reqt) == "string" then return srequest(reqt, body)
else return trequest(reqt) end
end)
return _M

View File

@ -10,16 +10,19 @@
local string = require("string")
local table = require("table")
local base = _G
module("ltn12")
ltn12 = {}
local _M = ltn12
filter = {}
source = {}
sink = {}
pump = {}
local filter,source,sink,pump = {},{},{},{}
_M.filter = filter
_M.source = source
_M.sink = sink
_M.pump = pump
-- 2048 seems to be better in windows...
BLOCKSIZE = 2048
_VERSION = "LTN12 1.0.2"
_M.BLOCKSIZE = 2048
_M._VERSION = "LTN12 1.0.2"
-----------------------------------------------------------------------------
-- Filter stuff
@ -38,7 +41,7 @@ end
-- (thanks to Wim Couwenberg)
function filter.chain(...)
local arg = {...}
local n = #arg
local n = select('#',...)
local top, index = 1, 1
local retry = ""
return function(chunk)
@ -89,7 +92,7 @@ end
function source.file(handle, io_err)
if handle then
return function()
local chunk = handle:read(BLOCKSIZE)
local chunk = handle:read(_M.BLOCKSIZE)
if not chunk then handle:close() end
return chunk
end
@ -112,8 +115,8 @@ function source.string(s)
if s then
local i = 1
return function()
local chunk = string.sub(s, i, i+BLOCKSIZE-1)
i = i + BLOCKSIZE
local chunk = string.sub(s, i, i+_M.BLOCKSIZE-1)
i = i + _M.BLOCKSIZE
if chunk ~= "" then return chunk
else return nil end
end
@ -291,3 +294,4 @@ function pump.all(src, snk, step)
end
end
return _M

View File

@ -18,9 +18,6 @@
#include "lua.h"
#include "lauxlib.h"
#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include "compat-5.1.h"
#endif
/*=========================================================================*\
* LuaSocket includes
@ -81,6 +78,34 @@ static int global_unload(lua_State *L) {
return 0;
}
#if LUA_VERSION_NUM > 501
int luaL_typerror (lua_State *L, int narg, const char *tname) {
const char *msg = lua_pushfstring(L, "%s expected, got %s",
tname, luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}
#if ! defined(LUA_COMPAT_MODULE)
void luaL_openlib(lua_State *L, const char *name, const luaL_Reg *funcs, int idx) {
if (name != NULL) {
#ifdef LUASOCKET_USE_GLOBAL
lua_getglobal(L,name);
if (lua_isnil(L,-1)) {
lua_newtable(L);
lua_setglobal(L,name);
lua_getglobal(L,name);
}
#else
lua_newtable(L);
#endif
}
luaL_setfuncs(L,funcs,0);
}
#endif
#endif
/*-------------------------------------------------------------------------*\
* Setup basic stuff.
\*-------------------------------------------------------------------------*/

View File

@ -22,10 +22,6 @@
#define LUASOCKET_API extern
#endif
#if LUA_VERSION_NUM > 501 & !( defined LUA_COMPAT_MODULE)
# error Lua 5.2 requires LUA_COMPAT_MODULE defined for luaL_openlib
#endif
/*-------------------------------------------------------------------------*\
* Initializes the library.
\*-------------------------------------------------------------------------*/

View File

@ -86,3 +86,5 @@ function Public.parse_message(message_s)
message.headers = Public.parse_headers(message.headers)
return message
end
return mbox

View File

@ -81,7 +81,16 @@ static UC b64unbase[256];
\*-------------------------------------------------------------------------*/
MIME_API int luaopen_mime_core(lua_State *L)
{
#if LUA_VERSION_NUM > 501
lua_newtable(L);
#ifdef LUASOCKET_USE_GLOBAL
lua_setglobal(L,"mime");
lua_getglobal(L,"mime");
#endif
luaL_setfuncs(L,func,0);
#else
luaL_openlib(L, "mime", func, 0);
#endif
/* make version string available to scripts */
lua_pushstring(L, "_VERSION");
lua_pushstring(L, MIME_VERSION);

View File

@ -10,13 +10,16 @@
local base = _G
local ltn12 = require("ltn12")
local mime = require("mime.core")
local io = require("io")
local string = require("string")
module("mime")
local _M = mime
-- encode, decode and wrap algorithm tables
encodet = {}
decodet = {}
wrapt = {}
local encodet, decodet, wrapt = {},{},{}
_M.encodet = encodet
_M.decodet = decodet
_M.wrapt = wrapt
-- creates a function that chooses a filter by name from a given table
local function choose(table)
@ -33,21 +36,21 @@ end
-- define the encoding filters
encodet['base64'] = function()
return ltn12.filter.cycle(b64, "")
return ltn12.filter.cycle(_M.b64, "")
end
encodet['quoted-printable'] = function(mode)
return ltn12.filter.cycle(qp, "",
return ltn12.filter.cycle(_M.qp, "",
(mode == "binary") and "=0D=0A" or "\r\n")
end
-- define the decoding filters
decodet['base64'] = function()
return ltn12.filter.cycle(unb64, "")
return ltn12.filter.cycle(_M.unb64, "")
end
decodet['quoted-printable'] = function()
return ltn12.filter.cycle(unqp, "")
return ltn12.filter.cycle(_M.unqp, "")
end
local function format(chunk)
@ -60,26 +63,28 @@ end
-- define the line-wrap filters
wrapt['text'] = function(length)
length = length or 76
return ltn12.filter.cycle(wrp, length, length)
return ltn12.filter.cycle(_M.wrp, length, length)
end
wrapt['base64'] = wrapt['text']
wrapt['default'] = wrapt['text']
wrapt['quoted-printable'] = function()
return ltn12.filter.cycle(qpwrp, 76, 76)
return ltn12.filter.cycle(_M.qpwrp, 76, 76)
end
-- function that choose the encoding, decoding or wrap algorithm
encode = choose(encodet)
decode = choose(decodet)
wrap = choose(wrapt)
_M.encode = choose(encodet)
_M.decode = choose(decodet)
_M.wrap = choose(wrapt)
-- define the end-of-line normalization filter
function normalize(marker)
return ltn12.filter.cycle(eol, 0, marker)
function _M.normalize(marker)
return ltn12.filter.cycle(_M.eol, 0, marker)
end
-- high level stuffing filter
function stuff()
return ltn12.filter.cycle(dot, 2)
function _M.stuff()
return ltn12.filter.cycle(_M.dot, 2)
end
return _M

View File

@ -17,22 +17,24 @@ local tp = require("socket.tp")
local ltn12 = require("ltn12")
local headers = require("socket.headers")
local mime = require("mime")
module("socket.smtp")
socket.smtp = {}
local _M = socket.smtp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
-- timeout for connection
TIMEOUT = 60
_M.TIMEOUT = 60
-- default server used to send e-mails
SERVER = "localhost"
_M.SERVER = "localhost"
-- default port
PORT = 25
_M.PORT = 25
-- domain used in HELO command and default sendmail
-- If we are under a CGI, try to get from environment
DOMAIN = os.getenv("SERVER_NAME") or "localhost"
_M.DOMAIN = os.getenv("SERVER_NAME") or "localhost"
-- default time zone (means we don't know)
ZONE = "-0000"
_M.ZONE = "-0000"
---------------------------------------------------------------------------
-- Low level SMTP API
@ -41,7 +43,7 @@ local metat = { __index = {} }
function metat.__index:greet(domain)
self.try(self.tp:check("2.."))
self.try(self.tp:command("EHLO", domain or DOMAIN))
self.try(self.tp:command("EHLO", domain or _M.DOMAIN))
return socket.skip(1, self.try(self.tp:check("2..")))
end
@ -111,9 +113,9 @@ function metat.__index:send(mailt)
self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
end
function open(server, port, create)
local tp = socket.try(tp.connect(server or SERVER, port or PORT,
TIMEOUT, create))
function _M.open(server, port, create)
local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT,
_M.TIMEOUT, create))
local s = base.setmetatable({tp = tp}, metat)
-- make sure tp is closed if we get an exception
s.try = socket.newtry(function()
@ -221,14 +223,14 @@ end
local function adjust_headers(mesgt)
local lower = lower_headers(mesgt.headers)
lower["date"] = lower["date"] or
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE)
os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE)
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
-- this can't be overriden
lower["mime-version"] = "1.0"
return lower
end
function message(mesgt)
function _M.message(mesgt)
mesgt.headers = adjust_headers(mesgt)
-- create and return message source
local co = coroutine.create(function() send_message(mesgt) end)
@ -242,11 +244,13 @@ end
---------------------------------------------------------------------------
-- High level SMTP API
-----------------------------------------------------------------------------
send = socket.protect(function(mailt)
local s = open(mailt.server, mailt.port, mailt.create)
_M.send = socket.protect(function(mailt)
local s = _M.open(mailt.server, mailt.port, mailt.create)
local ext = s:greet(mailt.domain)
s:auth(mailt.user, mailt.password, ext)
s:send(mailt)
s:quit()
return s:close()
end)
return _M

View File

@ -10,20 +10,21 @@ local base = _G
local string = require("string")
local math = require("math")
local socket = require("socket.core")
module("socket")
local _M = socket
-----------------------------------------------------------------------------
-- Exported auxiliar functions
-----------------------------------------------------------------------------
function connect4(address, port, laddress, lport)
function _M.connect4(address, port, laddress, lport)
return socket.connect(address, port, laddress, lport, "inet")
end
function connect6(address, port, laddress, lport)
function _M.connect6(address, port, laddress, lport)
return socket.connect(address, port, laddress, lport, "inet6")
end
function bind(host, port, backlog)
function _M.bind(host, port, backlog)
if host == "*" then host = "0.0.0.0" end
local addrinfo, err = socket.dns.getaddrinfo(host);
if not addrinfo then return nil, err end
@ -52,9 +53,9 @@ function bind(host, port, backlog)
return nil, err
end
try = newtry()
_M.try = _M.newtry()
function choose(table)
function _M.choose(table)
return function(name, opt1, opt2)
if base.type(name) ~= "string" then
name, opt1, opt2 = "default", name, opt1
@ -69,10 +70,11 @@ end
-- Socket sources and sinks, conforming to LTN12
-----------------------------------------------------------------------------
-- create namespaces inside LuaSocket namespace
sourcet = {}
sinkt = {}
local sourcet, sinkt = {}, {}
_M.sourcet = sourcet
_M.sinkt = sinkt
BLOCKSIZE = 2048
_M.BLOCKSIZE = 2048
sinkt["close-when-done"] = function(sock)
return base.setmetatable({
@ -102,7 +104,7 @@ end
sinkt["default"] = sinkt["keep-open"]
sink = choose(sinkt)
_M.sink = _M.choose(sinkt)
sourcet["by-length"] = function(sock, length)
return base.setmetatable({
@ -142,5 +144,6 @@ end
sourcet["default"] = sourcet["until-closed"]
source = choose(sourcet)
_M.source = _M.choose(sourcet)
return _M

View File

@ -11,12 +11,14 @@ local base = _G
local string = require("string")
local socket = require("socket")
local ltn12 = require("ltn12")
module("socket.tp")
socket.tp = {}
local _M = socket.tp
-----------------------------------------------------------------------------
-- Program constants
-----------------------------------------------------------------------------
TIMEOUT = 60
_M.TIMEOUT = 60
-----------------------------------------------------------------------------
-- Implementation
@ -109,10 +111,10 @@ function metat.__index:close()
end
-- connect with server and return c object
function connect(host, port, timeout, create)
function _M.connect(host, port, timeout, create)
local c, e = (create or socket.tcp)()
if not c then return nil, e end
c:settimeout(timeout or TIMEOUT)
c:settimeout(timeout or _M.TIMEOUT)
local r, e = c:connect(host, port)
if not r then
c:close()
@ -121,3 +123,4 @@ function connect(host, port, timeout, create)
return base.setmetatable({c = c}, metat)
end
return _M

View File

@ -10,12 +10,15 @@
local string = require("string")
local base = _G
local table = require("table")
module("socket.url")
local socket = require("socket")
socket.url = {}
local _M = socket.url
-----------------------------------------------------------------------------
-- Module version
-----------------------------------------------------------------------------
_VERSION = "URL 1.0.2"
_M._VERSION = "URL 1.0.2"
-----------------------------------------------------------------------------
-- Encodes a string into its escaped hexadecimal representation
@ -24,7 +27,7 @@ _VERSION = "URL 1.0.2"
-- Returns
-- escaped representation of string binary
-----------------------------------------------------------------------------
function escape(s)
function _M.escape(s)
return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
return string.format("%%%02x", string.byte(c))
end))
@ -67,7 +70,7 @@ end
-- Returns
-- escaped representation of string binary
-----------------------------------------------------------------------------
function unescape(s)
function _M.unescape(s)
return (string.gsub(s, "%%(%x%x)", function(hex)
return string.char(base.tonumber(hex, 16))
end))
@ -120,7 +123,7 @@ end
-- Obs:
-- the leading '/' in {/<path>} is considered part of <path>
-----------------------------------------------------------------------------
function parse(url, default)
function _M.parse(url, default)
-- initialize default parameters
local parsed = {}
for i,v in base.pairs(default or parsed) do parsed[i] = v end
@ -179,9 +182,9 @@ end
-- Returns
-- a stringing with the corresponding URL
-----------------------------------------------------------------------------
function build(parsed)
local ppath = parse_path(parsed.path or "")
local url = build_path(ppath)
function _M.build(parsed)
local ppath = _M.parse_path(parsed.path or "")
local url = _M.build_path(ppath)
if parsed.params then url = url .. ";" .. parsed.params end
if parsed.query then url = url .. "?" .. parsed.query end
local authority = parsed.authority
@ -215,14 +218,14 @@ end
-- Returns
-- corresponding absolute url
-----------------------------------------------------------------------------
function absolute(base_url, relative_url)
function _M.absolute(base_url, relative_url)
if base.type(base_url) == "table" then
base_parsed = base_url
base_url = build(base_parsed)
base_url = _M.build(base_parsed)
else
base_parsed = parse(base_url)
base_parsed = _M.parse(base_url)
end
local relative_parsed = parse(relative_url)
local relative_parsed = _M.parse(relative_url)
if not base_parsed then return relative_url
elseif not relative_parsed then return base_url
elseif relative_parsed.scheme then return relative_url
@ -243,7 +246,7 @@ function absolute(base_url, relative_url)
relative_parsed.path)
end
end
return build(relative_parsed)
return _M.build(relative_parsed)
end
end
@ -254,13 +257,13 @@ end
-- Returns
-- segment: a table with one entry per segment
-----------------------------------------------------------------------------
function parse_path(path)
function _M.parse_path(path)
local parsed = {}
path = path or ""
--path = string.gsub(path, "%s", "")
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
for i = 1, #parsed do
parsed[i] = unescape(parsed[i])
parsed[i] = _M.unescape(parsed[i])
end
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
@ -275,7 +278,7 @@ end
-- Returns
-- path: corresponding path stringing
-----------------------------------------------------------------------------
function build_path(parsed, unsafe)
function _M.build_path(parsed, unsafe)
local path = ""
local n = #parsed
if unsafe then
@ -300,3 +303,5 @@ function build_path(parsed, unsafe)
if parsed.is_absolute then path = "/" .. path end
return path
end
return _M

View File

@ -1,3 +1,3 @@
require"socket"
require"mime"
local socket = require"socket"
local mime = require"mime"
print("Hello from " .. socket._VERSION .. " and " .. mime._VERSION .. "!")