From 694edcc3c1ac3041ff8cdd753a2f7894e8783e6c Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Fri, 28 May 2004 06:16:43 +0000 Subject: [PATCH] Committing with require. --- etc/b64.lua | 2 ++ etc/dict.lua | 5 ++- samples/cddb.lua | 4 +-- src/ftp.lua | 91 +++++++++++++++++++++++++++++++++++++++-------- src/http.lua | 10 ++++-- src/luasocket.c | 37 ++----------------- src/mime.c | 10 +++--- src/mime.h | 9 ++++- src/mime.lua | 27 ++++++++++++-- src/smtp.lua | 22 ++++++------ src/tp.lua | 10 +++--- src/url.lua | 2 +- test/httptest.lua | 4 +++ 13 files changed, 153 insertions(+), 80 deletions(-) diff --git a/etc/b64.lua b/etc/b64.lua index 3f861b4..1993b01 100644 --- a/etc/b64.lua +++ b/etc/b64.lua @@ -1,3 +1,5 @@ +require("ltn12") +require("mime") local source = ltn12.source.file(io.stdin) local sink = ltn12.sink.file(io.stdout) local convert diff --git a/etc/dict.lua b/etc/dict.lua index 933c1c8..d11ac93 100644 --- a/etc/dict.lua +++ b/etc/dict.lua @@ -8,12 +8,11 @@ function get_status(sock, valid) local line, err = sock:receive() local code, par if not line then sock:close() return err end - _, _, code = string.find(line, "^(%d%d%d)") + code = socket.skip(2, string.find(line, "^(%d%d%d)")) code = tonumber(code) if code ~= valid then return code end if code == 150 then - _,_,_, par = string.find(line, "^(%d%d%d) (%d*)") - par = tonumber(par) + par = tonumber(socket.skip(2, string.find(line, "^%d%d%d (%d*)")) end return nil, par end diff --git a/samples/cddb.lua b/samples/cddb.lua index 6ade3c0..0ed7c71 100644 --- a/samples/cddb.lua +++ b/samples/cddb.lua @@ -8,7 +8,7 @@ local server = arg[3] or "http://freedb.freedb.org/~cddb/cddb.cgi" function parse(body) local lines = string.gfind(body, "(.-)\r\n") local status = lines() - local _, _, code, message = string.find(status, "(%d%d%d) (.*)") + local code, message = socket.skip(2, string.find(status, "(%d%d%d) (.*)")) if tonumber(code) ~= 210 then return nil, code, message end @@ -16,7 +16,7 @@ function parse(body) for l in lines do local c = string.sub(l, 1, 1) if c ~= '#' and c ~= '.' then - local _, _, key, value = string.find(l, "(.-)=(.*)") + local key, value = socket.skip(2, string.find(l, "(.-)=(.*)")) value = string.gsub(value, "\\n", "\n") value = string.gsub(value, "\\\\", "\\") value = string.gsub(value, "\\t", "\t") diff --git a/src/ftp.lua b/src/ftp.lua index 306b77f..efb872a 100644 --- a/src/ftp.lua +++ b/src/ftp.lua @@ -10,6 +10,11 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end -- get LuaSocket namespace local socket = _G[LUASOCKET_LIBNAME] if not socket then error('module requires LuaSocket') end + +-- require other modules +require("ltn12") +require("url") + -- create namespace inside LuaSocket namespace socket.ftp = socket.ftp or {} -- make all module globals fall into namespace @@ -25,6 +30,7 @@ TIMEOUT = 60 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" EMAIL = "anonymous@anonymous.org" -- block size used in transfers BLOCKSIZE = 2048 @@ -48,21 +54,20 @@ local function pasv(pasvt) end function metat.__index:login(user, password) - socket.try(self.tp:command("USER", user)) + socket.try(self.tp:command("user", user or USER)) local code, reply = socket.try(self.tp:check{"2..", 331}) if code == 331 then - socket.try(password, reply) - socket.try(self.tp:command("PASS", password)) + socket.try(self.tp:command("pass", password or EMAIL)) socket.try(self.tp:check("2..")) end return 1 end function metat.__index:pasv() - socket.try(self.tp:command("PASV")) + socket.try(self.tp:command("pasv")) local code, reply = socket.try(self.tp:check("2..")) - local _, _, a, b, c, d, p1, p2 = - string.find(reply, "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)") + local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" + local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern)) socket.try(a and b and c and d and p1 and p2, reply) self.pasvt = { ip = string.format("%d.%d.%d.%d", a, b, c, d), @@ -97,7 +102,7 @@ function metat.__index:send(sendt) local data socket.try(self.pasvt or self.portt, "need port or pasv first") if self.pasvt then data = socket.try(pasv(self.pasvt)) end - socket.try(self.tp:command(sendt.command, sendt.argument)) + socket.try(self.tp:command(sendt.command or "stor", sendt.argument)) local code, reply = socket.try(self.tp:check{"2..", "1.."}) if self.portt then data = socket.try(port(self.portt)) end local step = sendt.step or ltn12.pump.step @@ -124,7 +129,7 @@ function metat.__index:receive(recvt) local data socket.try(self.pasvt or self.portt, "need port or pasv first") if self.pasvt then data = socket.try(pasv(self.pasvt)) end - socket.try(self.tp:command(recvt.command, recvt.argument)) + socket.try(self.tp:command(recvt.command or "retr", recvt.argument)) local code = socket.try(self.tp:check{"1..", "2.."}) if self.portt then data = socket.try(port(self.portt)) end local source = socket.source("until-closed", data) @@ -140,13 +145,13 @@ function metat.__index:receive(recvt) end function metat.__index:cwd(dir) - socket.try(self.tp:command("CWD", dir)) + socket.try(self.tp:command("cwd", dir)) socket.try(self.tp:check(250)) return 1 end function metat.__index:type(type) - socket.try(self.tp:command("TYPE", type)) + socket.try(self.tp:command("type", type)) socket.try(self.tp:check(200)) return 1 end @@ -158,7 +163,7 @@ function metat.__index:greet() end function metat.__index:quit() - socket.try(self.tp:command("QUIT")) + socket.try(self.tp:command("quit")) socket.try(self.tp:check("2..")) return 1 end @@ -171,11 +176,69 @@ end ----------------------------------------------------------------------------- -- High level FTP API ----------------------------------------------------------------------------- - -function put(putt) +local function tput(putt) + local ftp = socket.ftp.open(putt.host, putt.port) + ftp:greet() + ftp:login(putt.user, putt.password) + if putt.type then ftp:type(putt.type) end + ftp:pasv() + ftp:send(putt) + ftp:quit() + return ftp:close() end -function get(gett) +local default = { + path = "/", + scheme = "ftp" +} + +local function parse(url) + local putt = socket.try(socket.url.parse(url, default)) + socket.try(putt.scheme == "ftp", "invalid scheme '" .. putt.scheme .. "'") + socket.try(putt.host, "invalid host") + local pat = "^type=(.)$" + if putt.params then + putt.type = socket.skip(2, string.find(putt.params, pat)) + socket.try(putt.type == "a" or putt.type == "i") + end + -- skip first backslash in path + putt.argument = string.sub(putt.path, 2) + return putt end +local function sput(url, body) + local putt = parse(url) + putt.source = ltn12.source.string(body) + return tput(putt) +end + +put = socket.protect(function(putt, body) + if type(putt) == "string" then return sput(putt, body) + else return tput(putt) end +end) + +local function tget(gett) + local ftp = socket.ftp.open(gett.host, gett.port) + ftp:greet() + ftp:login(gett.user, gett.password) + if gett.type then ftp:type(gett.type) end + ftp:pasv() + ftp:receive(gett) + ftp:quit() + return ftp:close() +end + +local function sget(url, body) + local gett = parse(url) + local t = {} + gett.sink = ltn12.sink.table(t) + tget(gett) + return table.concat(t) +end + +get = socket.protect(function(gett) + if type(gett) == "string" then return sget(gett, body) + else return tget(gett) end +end) + return ftp diff --git a/src/http.lua b/src/http.lua index f787b9d..e6a0928 100644 --- a/src/http.lua +++ b/src/http.lua @@ -10,6 +10,12 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end -- get LuaSocket namespace local socket = _G[LUASOCKET_LIBNAME] if not socket then error('module requires LuaSocket') end + +-- require other modules +require("ltn12") +require("mime") +require("url") + -- create namespace inside LuaSocket namespace socket.http = socket.http or {} -- make all module globals fall into namespace @@ -41,7 +47,7 @@ end local function receive_headers(reqt, respt, tmp) local sock = tmp.sock - local line, name, value, _ + local line, name, value local headers = {} -- store results respt.headers = headers @@ -50,7 +56,7 @@ local function receive_headers(reqt, respt, tmp) -- headers go until a blank line is found while line ~= "" do -- get field-name and value - _, _, name, value = string.find(line, "^(.-):%s*(.*)") + name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)")) socket.try(name and value, "malformed reponse headers") name = string.lower(name) -- get next line (value might be folded) diff --git a/src/luasocket.c b/src/luasocket.c index fe4c96c..8d49be5 100644 --- a/src/luasocket.c +++ b/src/luasocket.c @@ -35,38 +35,6 @@ #include "udp.h" #include "select.h" #include "smtp.h" -#include "mime.h" - -/*=========================================================================*\ -* Declarations -\*=========================================================================*/ -static int mod_open(lua_State *L, const luaL_reg *mod); - - -static int mod_open(lua_State *L, const luaL_reg *mod) -{ - for (; mod->name; mod++) mod->func(L); -#ifdef LUASOCKET_COMPILED -#include "ltn12.lch" -#include "auxiliar.lch" -#include "url.lch" -#include "mime.lch" -#include "tp.lch" -#include "smtp.lch" -#include "http.lch" -#include "ftp.lch" -#else - lua_dofile(L, "ltn12.lua"); - lua_dofile(L, "auxiliar.lua"); - lua_dofile(L, "url.lua"); - lua_dofile(L, "mime.lua"); - lua_dofile(L, "tp.lua"); - lua_dofile(L, "smtp.lua"); - lua_dofile(L, "http.lua"); - lua_dofile(L, "ftp.lua"); -#endif - return 0; -} /*-------------------------------------------------------------------------*\ * Modules @@ -80,7 +48,6 @@ static const luaL_reg mod[] = { {"tcp", tcp_open}, {"udp", udp_open}, {"select", select_open}, - {"mime", mime_open}, {"smtp", smtp_open}, {NULL, NULL} }; @@ -90,11 +57,13 @@ static const luaL_reg mod[] = { \*-------------------------------------------------------------------------*/ LUASOCKET_API int luaopen_socket(lua_State *L) { + int i; if (!sock_open()) { lua_pushnil(L); lua_pushstring(L, "unable to initialize library"); return 2; } - mod_open(L, mod); + for (i = 0; mod[i].name; i++) + mod[i].func(L); return 1; } diff --git a/src/mime.c b/src/mime.c index fe24f9b..7a2baae 100644 --- a/src/mime.c +++ b/src/mime.c @@ -74,15 +74,15 @@ static UC b64unbase[256]; /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int mime_open(lua_State *L) +int luaopen_mime(lua_State *L) { - lua_pushstring(L, "mime"); - lua_newtable(L); - luaL_openlib(L, NULL, func, 0); - lua_settable(L, LUA_GLOBALSINDEX); + lua_pushstring(L, MIME_LIBNAME); + lua_setglobal(L, "MIME_LIBNAME"); + luaL_openlib(L, MIME_LIBNAME, func, 0); /* initialize lookup tables */ qpsetup(qpclass, qpunbase); b64setup(b64unbase); + lua_pop(L, 1); return 0; } diff --git a/src/mime.h b/src/mime.h index b91f735..fee4e5e 100644 --- a/src/mime.h +++ b/src/mime.h @@ -12,6 +12,13 @@ \*=========================================================================*/ #include -int mime_open(lua_State *L); +int luaopen_mime(lua_State *L); + +/*-------------------------------------------------------------------------*\ +* Library's namespace +\*-------------------------------------------------------------------------*/ +#ifndef MIME_LIBNAME +#define MIME_LIBNAME "mime" +#endif #endif /* MIME_H */ diff --git a/src/mime.lua b/src/mime.lua index 37756c7..8f2cfff 100644 --- a/src/mime.lua +++ b/src/mime.lua @@ -1,6 +1,27 @@ -if not ltn12 then error('Requires LTN12 module') end --- create mime namespace -mime = mime or {} +----------------------------------------------------------------------------- +-- MIME support for the Lua language. +-- Author: Diego Nehab +-- Conforming to RFCs 2045-2049 +-- RCS ID: $Id$ +----------------------------------------------------------------------------- + +----------------------------------------------------------------------------- +-- Load MIME from dynamic library +-- Comment these lines if you are loading static +----------------------------------------------------------------------------- +open, err1, err2 = loadlib("mime", "luaopen_mime") +if not open then error(err1) end +open() +if not MIME_LIBNAME then error("MIME init failed") end + +----------------------------------------------------------------------------- +-- Namespace independence +----------------------------------------------------------------------------- +local mime = _G[MIME_LIBNAME] +if not mime then error('MIME init FAILED') end + +require("ltn12") + -- make all module globals fall into mime namespace setmetatable(mime, { __index = _G }) setfenv(1, mime) diff --git a/src/smtp.lua b/src/smtp.lua index 8e672a0..1d1905e 100644 --- a/src/smtp.lua +++ b/src/smtp.lua @@ -1,8 +1,16 @@ +----------------------------------------------------------------------------- +-- SMTP client support for the Lua language. +-- LuaSocket toolkit. +-- Author: Diego Nehab +-- Conforming to RFC 2821 +-- RCS ID: $Id$ +----------------------------------------------------------------------------- -- make sure LuaSocket is loaded if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end -- get LuaSocket namespace local socket = _G[LUASOCKET_LIBNAME] if not socket then error('module requires LuaSocket') end + -- create smtp namespace inside LuaSocket namespace local smtp = socket.smtp or {} socket.smtp = smtp @@ -20,11 +28,6 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost" -- default time zone (means we don't know) ZONE = "-0000" - -local function shift(a, b, c) - return b, c -end - -- high level stuffing filter function stuff() return ltn12.filter.cycle(dot, 2) @@ -82,6 +85,7 @@ function metat.__index:send(mailt) end function open(server, port) + print(server or SERVER, port or PORT) local tp, error = socket.tp.connect(server or SERVER, port or PORT) if not tp then return nil, error end return setmetatable({tp = tp}, metat) @@ -180,17 +184,15 @@ function message(mesgt) adjust_headers(mesgt) -- create and return message source local co = coroutine.create(function() send_message(mesgt) end) - return function() return shift(coroutine.resume(co)) end + return function() return socket.skip(1, coroutine.resume(co)) end end --------------------------------------------------------------------------- -- High level SMTP API ----------------------------------------------------------------------------- send = socket.protect(function(mailt) - local server = mailt.server or SERVER - local port = mailt.port or PORT - local smtp = socket.try(open(server, port)) - smtp:greet(mailt.domain or DOMAIN) + local smtp = socket.try(open(mailt.server, mailt.port)) + smtp:greet(mailt.domain) smtp:send(mailt) smtp:quit() return smtp:close() diff --git a/src/tp.lua b/src/tp.lua index 4f2a615..b671e58 100644 --- a/src/tp.lua +++ b/src/tp.lua @@ -20,20 +20,20 @@ TIMEOUT = 60 -- gets server reply (works for SMTP and FTP) local function get_reply(control) - local code, current, separator, _ + local code, current, sep local line, err = control:receive() local reply = line if err then return nil, err end - _, _, code, separator = string.find(line, "^(%d%d%d)(.?)") + code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) if not code then return nil, "invalid server reply" end - if separator == "-" then -- reply is multiline + if sep == "-" then -- reply is multiline repeat line, err = control:receive() if err then return nil, err end - _,_, current, separator = string.find(line, "^(%d%d%d)(.?)") + current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)")) reply = reply .. "\n" .. line -- reply ends with same code - until code == current and separator == " " + until code == current and sep == " " end return code, reply end diff --git a/src/url.lua b/src/url.lua index 2b9e4dc..0fba14d 100644 --- a/src/url.lua +++ b/src/url.lua @@ -125,7 +125,7 @@ function parse(url, default) -- initialize default parameters local parsed = default or {} -- empty url is parsed to nil - if not url or url == "" then return nil end + if not url or url == "" then return nil, "invalid url" end -- remove whitespace -- url = string.gsub(url, "%s", "") -- get fragment diff --git a/test/httptest.lua b/test/httptest.lua index c16ef2b..d237547 100644 --- a/test/httptest.lua +++ b/test/httptest.lua @@ -3,6 +3,10 @@ -- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi -- to "/luasocket-test-cgi" and "/luasocket-test-cgi/" -- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth + +require("luasocket") +require("http") + dofile("testsupport.lua") local host, proxy, request, response, index_file