Couple bug fixes.

This commit is contained in:
Diego Nehab 2007-03-12 04:08:40 +00:00
parent 8bf9fb51dd
commit be2e467929
11 changed files with 77 additions and 74 deletions

25
NEW
View File

@ -1,24 +1 @@
What's New Fixed case sensitivity in headers of multipart messages in smtp.message.
This is just a bug-fix/update release.
* Updated: now using compat-5.1r5;
* Improved: http.request is more robust to malformed
URLs (Adrian Sietsma);
* Improved: the simple http.request interface sends a
"Content-type: application/x-www-form-urlencoded" header
(William Trenker);
* Improved: http.request is robust to evil servers that
send inappropriate 100-continue messages (David Burgess);
* Fixed: http.request was using the old host header during
redirects (Florian Berger);
* Fixed: sample unix.c had fallen through the cracks
during development (Matthew Percival);
* Fixed: error code was not being propagated correctly
in ftp.lua (David Burgess).

25
WISH
View File

@ -1,5 +1,22 @@
... as an l-value ... as an l-value to get all results of a function call?
tupples? at least ...[i] and #...
extend to full tuples?
__and __or __not metamethods
lua_tostring, lua_tonumber, lua_touseradta etc push values in stack
__tostring,__tonumber, __touserdata metamethods are checked
and expected to push an object of correct type on stack
lua_rawtostring, lua_rawtonumber, lua_rawtouserdata don't
push anything on stack, return data of appropriate type,
skip metamethods and throw error if object not of exact type
package.findfile exported package.findfile exported
assert returns all arguments on success module not polluting the global namespace
module does not pollute the global namespace
coxpcall with a coroutine pool for efficiency (reusing coroutines)
exception mechanism formalized? just like the package system was.
a nice bitlib in the core

33
config
View File

@ -15,22 +15,23 @@ UNIX_SO=unix.$(EXT)
#------ #------
# Lua includes and libraries # Lua includes and libraries
# #
LUAINC=-I/usr/local/include/lua50 #LUAINC=-I/usr/local/include/lua50
#LUAINC=-I/usr/local/include/lua5.1 #LUAINC=-I/usr/local/include/lua5.1
LUAINC=-Ilua-5.1.1/src
#------ #------
# Compat-5.1 directory # Compat-5.1 directory
# #
COMPAT=compat-5.1r5 #COMPAT=compat-5.1r5
#------ #------
# Top of your Lua installation # Top of your Lua installation
# Relative paths will be inside the src tree # Relative paths will be inside the src tree
# #
INSTALL_TOP_SHARE=/usr/local/share/lua/5.0 #INSTALL_TOP_SHARE=/usr/local/share/lua/5.0
INSTALL_TOP_LIB=/usr/local/lib/lua/5.0 #INSTALL_TOP_LIB=/usr/local/lib/lua/5.0
#INSTALL_TOP_SHARE=/usr/local/share/lua/5.1 INSTALL_TOP_SHARE=/usr/local/share/lua/5.1
#INSTALL_TOP_LIB=/usr/local/lib/lua/5.1 INSTALL_TOP_LIB=/usr/local/lib/lua/5.1
INSTALL_DATA=cp INSTALL_DATA=cp
INSTALL_EXEC=cp INSTALL_EXEC=cp
@ -39,20 +40,20 @@ INSTALL_EXEC=cp
# Compiler and linker settings # Compiler and linker settings
# for Mac OS X # for Mac OS X
# #
#CC=gcc CC=gcc
#DEF=-DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN DEF=-DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN
#CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common
#LDFLAGS=-bundle -undefined dynamic_lookup LDFLAGS=-bundle -undefined dynamic_lookup
#LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc LD=export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
#------ #------
# Compiler and linker settings # Compiler and linker settings
# for Linux # for Linux
CC=gcc #CC=gcc
DEF=-DLUASOCKET_DEBUG #DEF=-DLUASOCKET_DEBUG
CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fpic #CFLAGS= $(LUAINC) -I$(COMPAT) $(DEF) -pedantic -Wall -O2 -fpic
LDFLAGS=-O -shared -fpic #LDFLAGS=-O -shared -fpic
LD=gcc #LD=gcc
#------ #------
# End of makefile configuration # End of makefile configuration

View File

@ -65,21 +65,23 @@ end
-- kind of copied from luasocket's manual callback examples -- kind of copied from luasocket's manual callback examples
function stats(size) function stats(size)
local start = socket.gettime() local start = socket.gettime()
local last = start
local got = 0 local got = 0
return function(chunk) return function(chunk)
-- elapsed time since start -- elapsed time since start
local delta = socket.gettime() - start local current = socket.gettime()
if chunk then if chunk then
-- total bytes received -- total bytes received
got = got + string.len(chunk) got = got + string.len(chunk)
-- not enough time for estimate -- not enough time for estimate
if delta > 0.1 then if current - last > 1 then
io.stderr:write("\r", gauge(got, delta, size)) io.stderr:write("\r", gauge(got, current - start, size))
io.stderr:flush() io.stderr:flush()
last = current
end end
else else
-- close up -- close up
io.stderr:write("\r", gauge(got, delta), "\n") io.stderr:write("\r", gauge(got, current - start), "\n")
end end
return chunk return chunk
end end

View File

@ -25,7 +25,6 @@ TO_SOCKET_SHARE:= \
smtp.lua smtp.lua
TO_TOP_SHARE:= \ TO_TOP_SHARE:= \
$(COMPAT)/compat-5.1.lua \
ltn12.lua \ ltn12.lua \
socket.lua \ socket.lua \
mime.lua mime.lua

View File

@ -107,7 +107,7 @@ local metat = { __index = {} }
function open(host, port, create) function open(host, port, create)
-- create socket with user connect function, or with default -- create socket with user connect function, or with default
local c = socket.try(create or socket.tcp)() local c = socket.try((create or socket.tcp)())
local h = base.setmetatable({ c = c }, metat) local h = base.setmetatable({ c = c }, metat)
-- create finalized try -- create finalized try
h.try = socket.newtry(function() h:close() end) h.try = socket.newtry(function() h:close() end)
@ -228,7 +228,8 @@ local function adjustrequest(reqt)
-- explicit components override url -- explicit components override url
for i,v in base.pairs(reqt) do nreqt[i] = v end for i,v in base.pairs(reqt) do nreqt[i] = v end
if nreqt.port == "" then nreqt.port = 80 end if nreqt.port == "" then nreqt.port = 80 end
socket.try(nreqt.host, "invalid host '" .. base.tostring(nreqt.host) .. "'") socket.try(nreqt.host and nreqt.host ~= "",
"invalid host '" .. base.tostring(nreqt.host) .. "'")
-- compute uri if user hasn't overriden -- compute uri if user hasn't overriden
nreqt.uri = reqt.uri or adjusturi(nreqt) nreqt.uri = reqt.uri or adjusturi(nreqt)
-- ajust host and port if there is a proxy -- ajust host and port if there is a proxy

View File

@ -11,8 +11,9 @@ include ../config
# Modules belonging to socket-core # Modules belonging to socket-core
# #
#$(COMPAT)/compat-5.1.o \
SOCKET_OBJS:= \ SOCKET_OBJS:= \
$(COMPAT)/compat-5.1.o \
luasocket.o \ luasocket.o \
timeout.o \ timeout.o \
buffer.o \ buffer.o \
@ -29,10 +30,10 @@ SOCKET_OBJS:= \
#------ #------
# Modules belonging mime-core # Modules belonging mime-core
# #
MIME_OBJS:=\ #$(COMPAT)/compat-5.1.o \
$(COMPAT)/compat-5.1.o \
mime.o
MIME_OBJS:=\
mime.o
#------ #------
# Modules belonging unix (local domain sockets) # Modules belonging unix (local domain sockets)

View File

@ -122,6 +122,15 @@ function open(server, port, create)
return s return s
end end
-- convert headers to lowercase
local function lower_headers(headers)
local lower = {}
for i,v in base.pairs(headers or lower) do
lower[string.lower(i)] = v
end
return lower
end
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Multipart message source -- Multipart message source
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
@ -149,7 +158,7 @@ end
local function send_multipart(mesgt) local function send_multipart(mesgt)
-- make sure we have our boundary and send headers -- make sure we have our boundary and send headers
local bd = newboundary() local bd = newboundary()
local headers = mesgt.headers or {} local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or 'multipart/mixed' headers['content-type'] = headers['content-type'] or 'multipart/mixed'
headers['content-type'] = headers['content-type'] .. headers['content-type'] = headers['content-type'] ..
'; boundary="' .. bd .. '"' '; boundary="' .. bd .. '"'
@ -176,7 +185,7 @@ end
-- yield message body from a source -- yield message body from a source
local function send_source(mesgt) local function send_source(mesgt)
-- make sure we have a content-type -- make sure we have a content-type
local headers = mesgt.headers or {} local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or headers['content-type'] = headers['content-type'] or
'text/plain; charset="iso-8859-1"' 'text/plain; charset="iso-8859-1"'
send_headers(headers) send_headers(headers)
@ -192,7 +201,7 @@ end
-- yield message body from a string -- yield message body from a string
local function send_string(mesgt) local function send_string(mesgt)
-- make sure we have a content-type -- make sure we have a content-type
local headers = mesgt.headers or {} local headers = lower_headers(mesgt.headers or {})
headers['content-type'] = headers['content-type'] or headers['content-type'] = headers['content-type'] or
'text/plain; charset="iso-8859-1"' 'text/plain; charset="iso-8859-1"'
send_headers(headers) send_headers(headers)
@ -209,20 +218,17 @@ end
-- set defaul headers -- set defaul headers
local function adjust_headers(mesgt) local function adjust_headers(mesgt)
local lower = {} local lower = lower_headers(mesgt.headers)
for i,v in base.pairs(mesgt.headers or lower) do
lower[string.lower(i)] = v
end
lower["date"] = lower["date"] or 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 ZONE)
lower["x-mailer"] = lower["x-mailer"] or socket._VERSION lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
-- this can't be overriden -- this can't be overriden
lower["mime-version"] = "1.0" lower["mime-version"] = "1.0"
mesgt.headers = lower return lower
end end
function message(mesgt) function message(mesgt)
adjust_headers(mesgt) mesgt.headers = adjust_headers(mesgt)
-- create and return message source -- create and return message source
local co = coroutine.create(function() send_message(mesgt) end) local co = coroutine.create(function() send_message(mesgt) end)
return function() return function()

View File

@ -119,9 +119,8 @@ check_request(request, expect, ignore)
------------------------------------------------------------------------ ------------------------------------------------------------------------
io.write("testing invalid url: ") io.write("testing invalid url: ")
local c, e = socket.connect("", 80) local r, e = http.request{url = host .. prefix}
local r, re = http.request{url = host .. prefix} assert(r == nil and e == "invalid host ''")
assert(r == nil and e == re)
r, re = http.request(host .. prefix) r, re = http.request(host .. prefix)
assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) .. assert(r == nil and e == re, tostring(r) ..", " .. tostring(re) ..
" vs " .. tostring(e)) " vs " .. tostring(e))

View File

@ -101,7 +101,7 @@ control:setoption("tcp-nodelay", true)
------------------------------------------------------------------------ ------------------------------------------------------------------------
function test_methods(sock, methods) function test_methods(sock, methods)
for _, v in methods do for _, v in pairs(methods) do
if type(sock[v]) ~= "function" then if type(sock[v]) ~= "function" then
fail(sock.class .. " method '" .. v .. "' not registered") fail(sock.class .. " method '" .. v .. "' not registered")
end end

View File

@ -12,7 +12,7 @@ source = smtp.message {
headers = { ['content-type'] = 'multipart/alternative' }, headers = { ['content-type'] = 'multipart/alternative' },
body = { body = {
[1] = { [1] = {
headers = { ['content-type'] = 'text/html' }, headers = { ['Content-type'] = 'text/html' },
body = "<html> <body> Hi, <b>there</b>...</body> </html>" body = "<html> <body> Hi, <b>there</b>...</body> </html>"
}, },
[2] = { [2] = {
@ -60,7 +60,7 @@ source = smtp.message{
-- chunks are loaded into memory and translation happens on the fly. -- chunks are loaded into memory and translation happens on the fly.
[2] = { [2] = {
headers = { headers = {
["content-type"] = 'image/png; name="luasocket.png"', ["ConTenT-tYpE"] = 'image/png; name="luasocket.png"',
["content-disposition"] = 'attachment; filename="luasocket.png"', ["content-disposition"] = 'attachment; filename="luasocket.png"',
["content-description"] = 'a beautiful image', ["content-description"] = 'a beautiful image',
["content-transfer-encoding"] = "BASE64" ["content-transfer-encoding"] = "BASE64"
@ -83,10 +83,10 @@ r, e = smtp.send{
"<diego@princeton.edu>" }, "<diego@princeton.edu>" },
from = "<diego@princeton.edu>", from = "<diego@princeton.edu>",
source = ltn12.source.chain(source, filter), source = ltn12.source.chain(source, filter),
server = "mail.cs.princeton.edu", --server = "mail.cs.princeton.edu",
--server = "localhost", --port = 25
--port = 2525 server = "localhost",
port = 25 port = 2525
} }
print(r, e) print(r, e)