Changed the naming convention of the mime module.

Looks beautiful.
This commit is contained in:
Diego Nehab 2004-01-21 01:09:50 +00:00
parent 0b61b577f5
commit 3a7ac1e043
7 changed files with 234 additions and 117 deletions

3
TODO
View File

@ -19,6 +19,9 @@ tests
checar garbage collection
check for interrupts
trust character constants in mime.c? noooooo.
smtp.lua needs stuff filter
new option.c module to put all options (TCP and UDP share...)?
testar os options!
add _tostring methods!

View File

@ -19,7 +19,7 @@ function nicetime(s)
end
end
end
if l == "s" then return string.format("%2.0f%s", s, l)
if l == "s" then return string.format("%5.0f%s", s, l)
else return string.format("%5.2f%s", s, l) end
end
@ -42,20 +42,16 @@ function nicesize(b)
end
-- returns a string with the current state of the download
local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining"
local elapsed_s = "%s received, %s/s throughput, %s elapsed "
function gauge(got, delta, size)
local rate = got / delta
if size and size >= 1 then
return string.format("%s received, %s/s throughput, " ..
"%.0f%% done, %s remaining",
nicesize(got),
nicesize(rate),
100*got/size,
nicetime((size-got)/rate))
return string.format(remaining_s, nicesize(got), nicesize(rate),
100*got/size, nicetime((size-got)/rate))
else
return string.format("%s received, %s/s throughput, %s elapsed",
nicesize(got),
nicesize(rate),
nicetime(delta))
return string.format(elapsed_s, nicesize(got),
nicesize(rate), nicetime(delta))
end
end
@ -78,7 +74,7 @@ function stats(size)
return chunk
else
-- close up
io.stderr:write("\n")
io.stderr:write("\r", gauge(got, delta), "\n")
return ""
end
end

View File

@ -70,7 +70,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="net/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE, LUASOCKET_DEBUG"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE, LUASOCKET_DEBUG, LUASOCKET_COMPILED"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"

View File

@ -35,17 +35,20 @@ static int mime_global_unqp(lua_State *L);
static int mime_global_qpfmt(lua_State *L);
static int mime_global_eol(lua_State *L);
static void b64fill(UC *b64unbase);
static void b64setup(UC *b64unbase);
static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer);
static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
static void qpfill(UC *qpclass, UC *qpunbase);
static void qpsetup(UC *qpclass, UC *qpunbase);
static void qpquote(UC c, luaL_Buffer *buffer);
static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
static size_t qpencode(UC c, UC *input, size_t size,
const char *marker, luaL_Buffer *buffer);
static const char *checklstring(lua_State *L, int n, size_t *l);
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l);
/* code support functions */
static luaL_reg func[] = {
{ "eol", mime_global_eol },
@ -96,8 +99,27 @@ void mime_open(lua_State *L)
lua_settable(L, -3);
lua_pop(L, 1);
/* initialize lookup tables */
qpfill(qpclass, qpunbase);
b64fill(b64unbase);
qpsetup(qpclass, qpunbase);
b64setup(b64unbase);
}
/*-------------------------------------------------------------------------*\
* Check if a string was provided. We accept false also.
\*-------------------------------------------------------------------------*/
static const char *checklstring(lua_State *L, int n, size_t *l)
{
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
*l = 0;
return NULL;
} else return luaL_checklstring(L, n, l);
}
static const char *optlstring(lua_State *L, int n, const char *v, size_t *l)
{
if (lua_isnil(L, n) || (lua_isboolean(L, n) && !lua_toboolean(L, n))) {
*l = 0;
return NULL;
} else return luaL_optlstring(L, n, v, l);
}
/*=========================================================================*\
@ -105,19 +127,19 @@ void mime_open(lua_State *L)
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Incrementaly breaks a string into lines
* A, n = fmt(B, length, left)
* A, n = fmt(l, B, length, marker)
* A is a copy of B, broken into lines of at most 'length' bytes.
* Left is how many bytes are left in the first line of B. 'n' is the number
* of bytes left in the last line of A.
* 'l' is how many bytes are left for the first line of B.
* 'n' is the number of bytes left in the last line of A.
* Marker is the end-of-line marker.
\*-------------------------------------------------------------------------*/
static int mime_global_fmt(lua_State *L)
{
size_t size = 0;
const UC *input = (UC *) (lua_isnil(L, 1)? NULL:
luaL_checklstring(L, 1, &size));
int left = (int) luaL_checknumber(L, 1);
const UC *input = (UC *) checklstring(L, 2, &size);
const UC *last = input + size;
int length = (int) luaL_checknumber(L, 2);
int left = (int) luaL_optnumber(L, 3, length);
int length = (int) luaL_optnumber(L, 3, 76);
const char *marker = luaL_optstring(L, 4, CRLF);
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
@ -140,7 +162,7 @@ static int mime_global_fmt(lua_State *L)
/*-------------------------------------------------------------------------*\
* Fill base64 decode map.
\*-------------------------------------------------------------------------*/
static void b64fill(UC *b64unbase)
static void b64setup(UC *b64unbase)
{
int i;
for (i = 0; i < 255; i++) b64unbase[i] = 255;
@ -255,7 +277,7 @@ static int mime_global_b64(lua_State *L)
luaL_buffinit(L, &buffer);
while (input < last)
asize = b64encode(*input++, atom, asize, &buffer);
input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
input = (UC *) optlstring(L, 2, NULL, &isize);
if (input) {
last = input + isize;
while (input < last)
@ -283,7 +305,7 @@ static int mime_global_unb64(lua_State *L)
luaL_buffinit(L, &buffer);
while (input < last)
asize = b64decode(*input++, atom, asize, &buffer);
input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
input = (UC *) optlstring(L, 2, NULL, &isize);
if (input) {
last = input + isize;
while (input < last)
@ -311,7 +333,7 @@ static int mime_global_unb64(lua_State *L)
* Split quoted-printable characters into classes
* Precompute reverse map for encoding
\*-------------------------------------------------------------------------*/
static void qpfill(UC *qpclass, UC *qpunbase)
static void qpsetup(UC *qpclass, UC *qpunbase)
{
int i;
for (i = 0; i < 256; i++) qpclass[i] = QP_QUOTED;
@ -417,15 +439,14 @@ static int mime_global_qp(lua_State *L)
size_t asize = 0, isize = 0;
UC atom[3];
const UC *input = (UC *) (lua_isnil(L, 1) ? NULL:
luaL_checklstring(L, 1, &isize));
const UC *input = (UC *) checklstring(L, 1, &isize);
const UC *last = input + isize;
const char *marker = luaL_optstring(L, 3, CRLF);
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
while (input < last)
asize = qpencode(*input++, atom, asize, marker, &buffer);
input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
input = (UC *) optlstring(L, 2, NULL, &isize);
if (input) {
last = input + isize;
while (input < last)
@ -486,14 +507,13 @@ static int mime_global_unqp(lua_State *L)
size_t asize = 0, isize = 0;
UC atom[3];
const UC *input = (UC *) (lua_isnil(L, 1) ? NULL:
luaL_checklstring(L, 1, &isize));
const UC *input = (UC *) checklstring(L, 1, &isize);
const UC *last = input + isize;
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
while (input < last)
asize = qpdecode(*input++, atom, asize, &buffer);
input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
input = (UC *) optlstring(L, 2, NULL, &isize);
if (input) {
last = input + isize;
while (input < last)
@ -506,21 +526,20 @@ static int mime_global_unqp(lua_State *L)
/*-------------------------------------------------------------------------*\
* Incrementally breaks a quoted-printed string into lines
* A, n = qpfmt(B, length, left)
* A, n = qpfmt(l, B, length)
* A is a copy of B, broken into lines of at most 'length' bytes.
* Left is how many bytes are left in the first line of B. 'n' is the number
* of bytes left in the last line of A.
* 'l' is how many bytes are left for the first line of B.
* 'n' is the number of bytes left in the last line of A.
* There are two complications: lines can't be broken in the middle
* of an encoded =XX, and there might be line breaks already
\*-------------------------------------------------------------------------*/
static int mime_global_qpfmt(lua_State *L)
{
size_t size = 0;
const UC *input = (UC *) (lua_isnil(L, 1)? NULL:
luaL_checklstring(L, 1, &size));
int left = (int) luaL_checknumber(L, 1);
const UC *input = (UC *) checklstring(L, 2, &size);
const UC *last = input + size;
int length = (int) luaL_checknumber(L, 2);
int left = (int) luaL_optnumber(L, 3, length);
int length = (int) luaL_optnumber(L, 3, 76);
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
while (input < last) {
@ -597,15 +616,14 @@ static int mime_global_eol(lua_State *L)
{
size_t asize = 0, isize = 0;
UC atom[2];
const UC *input = (UC *) (lua_isnil(L, 1)? NULL:
luaL_checklstring(L, 1, &isize));
const UC *input = (UC *) checklstring(L, 1, &isize);
const UC *last = input + isize;
const char *marker = luaL_optstring(L, 3, CRLF);
luaL_Buffer buffer;
luaL_buffinit(L, &buffer);
while (input < last)
asize = eolconvert(*input++, atom, asize, marker, &buffer);
input = (UC *) luaL_optlstring(L, 2, NULL, &isize);
input = (UC *) optlstring(L, 2, NULL, &isize);
if (input) {
last = input + isize;
while (input < last)

View File

@ -10,75 +10,71 @@ socket.mime = mime
setmetatable(mime, { __index = _G })
setfenv(1, mime)
base64 = {}
qprint = {}
-- encode, decode and wrap algorithm tables
local et = {}
local dt = {}
local wt = {}
function base64.encode()
local unfinished = ""
return function(chunk)
local done
done, unfinished = b64(unfinished, chunk)
return done
-- creates a function that chooses an algorithm from a given table
local function choose(table)
return function(method, ...)
local f = table[method or "nil"]
if not f then return nil, "unknown method (" .. tostring(method) .. ")"
else return f(unpack(arg)) end
end
end
function base64.decode()
local unfinished = ""
-- creates a function that cicles a filter with a given initial
-- context and extra arguments
local function cicle(f, ctx, ...)
return function(chunk)
local done
done, unfinished = unb64(unfinished, chunk)
return done
local ret
ret, ctx = f(ctx, chunk, unpack(arg))
return ret
end
end
function qprint.encode(mode)
mode = (mode == "binary") and "=0D=0A" or "\13\10"
local unfinished = ""
return function(chunk)
local done
done, unfinished = qp(unfinished, chunk, mode)
return done
end
-- function that choose the encoding, decoding or wrap algorithm
encode = choose(et)
decode = choose(dt)
wrap = choose(wt)
-- define the encoding algorithms
et['base64'] = function()
return cicle(b64, "")
end
function qprint.decode()
local unfinished = ""
return function(chunk)
local done
done, unfinished = unqp(unfinished, chunk)
return done
end
et['quoted-printable'] = function(mode)
return cicle(qp, "", (mode == "binary") and "=0D=0A" or "\13\10")
end
function split(length, marker)
-- define the decoding algorithms
dt['base64'] = function()
return cicle(unb64, "")
end
dt['quoted-printable'] = function()
return cicle(unqp, "")
end
-- define the wrap algorithms
wt['character'] = function(length)
length = length or 76
local left = length
return function(chunk)
local done
done, left = fmt(chunk, length, left, marker)
return done
end
return cicle(fmt, length, length)
end
wt['base64'] = wt['character']
function qprint.split(length)
wt['quoted-printable'] = function(length)
length = length or 76
local left = length
return function(chunk)
local done
done, left = qpfmt(chunk, length, left)
return done
end
return cicle(qpfmt, length, length)
end
-- define the end-of-line translation function
function canonic(marker)
local unfinished = ""
return function(chunk)
local done
done, unfinished = eol(unfinished, chunk, marker)
return done
end
return cicle(eol, "", marker)
end
-- chains several filters together
function chain(...)
local layers = table.getn(arg)
return function (chunk)

View File

@ -5,8 +5,8 @@
-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth
dofile("noglobals.lua")
local host, proxy, request, response
local ignore, expect, index, prefix, cgiprefix
local host, proxy, request, response, index_file
local ignore, expect, index, prefix, cgiprefix, index_crlf
socket.http.TIMEOUT = 5
@ -16,6 +16,7 @@ host = host or "diego.student.dyn.cs.princeton.edu"
proxy = proxy or "http://localhost:3128"
prefix = prefix or "/luasocket-test"
cgiprefix = cgiprefix or "/luasocket-test-cgi"
index_file = "test/index.html"
local readfile = function(name)
local f = io.open(name, "r")
@ -25,7 +26,8 @@ local readfile = function(name)
return s
end
index = readfile("test/index.html")
-- read index with CRLF convention
index = readfile(index_file)
local similar = function(s1, s2)
return string.lower(string.gsub(s1 or "", "%s", "")) ==
@ -43,12 +45,12 @@ local check = function (v, e)
else fail(e) end
end
local check_request = function(request, expect, ignore)
local response = socket.http.request(request)
local check_result = function(response, expect, ignore)
for i,v in response do
if not ignore[i] then
if v ~= expect[i] then
if string.len(v) < 80 then print(v) end
v = string.sub(type(v) == "string" and v or "", 1, 70)
print(v)
fail(i .. " differs!")
end
end
@ -56,7 +58,8 @@ local check_request = function(request, expect, ignore)
for i,v in expect do
if not ignore[i] then
if v ~= response[i] then
if string.len(v) < 80 then print(v) end
v = string.sub(type(v) == "string" and v or "", 1, 70)
print(v)
fail(i .. " differs!")
end
end
@ -64,6 +67,17 @@ local check_request = function(request, expect, ignore)
print("ok")
end
local check_request = function(request, expect, ignore)
local response = socket.http.request(request)
check_result(response, expect, ignore)
end
local check_request_cb = function(request, response, expect, ignore)
local response = socket.http.request_cb(request, response)
check_result(response, expect, ignore)
end
------------------------------------------------------------------------
io.write("testing request uri correctness: ")
local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string"
local back, h, c, e = socket.http.get("http://" .. host .. forth)
@ -72,12 +86,15 @@ back = socket.url.parse(back)
if similar(back.query, "this+is+the+query+string") then print("ok")
else fail() end
------------------------------------------------------------------------
io.write("testing query string correctness: ")
forth = "this+is+the+query+string"
back = socket.http.get("http://" .. host .. cgiprefix .. "/query-string?" .. forth)
back = socket.http.get("http://" .. host .. cgiprefix ..
"/query-string?" .. forth)
if similar(back, forth) then print("ok")
else fail("failed!") end
------------------------------------------------------------------------
io.write("testing document retrieval: ")
request = {
url = "http://" .. host .. prefix .. "/index.html"
@ -92,6 +109,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing redirect loop: ")
request = {
url = "http://" .. host .. cgiprefix .. "/redirect-loop"
@ -106,6 +124,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing post method: ")
-- wanted to test chunked post, but apache doesn't support it...
request = {
@ -125,6 +144,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing proxy with post method: ")
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
@ -143,10 +163,78 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing simple post function: ")
back = socket.http.post("http://" .. host .. cgiprefix .. "/cat", index)
check(back == index)
------------------------------------------------------------------------
io.write("testing send.file and receive.file callbacks: ")
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body_cb = socket.callback.send.file(io.open(index_file, "r")),
headers = { ["content-length"] = string.len(index) }
}
response = {
body_cb = socket.callback.receive.file(io.open(index_file .. "-back", "w"))
}
expect = {
code = 200
}
ignore = {
body_cb = 1,
status = 1,
headers = 1
}
check_request_cb(request, response, expect, ignore)
back = readfile(index_file .. "-back")
check(back == index)
os.remove(index_file .. "-back")
------------------------------------------------------------------------
io.write("testing send.chain and receive.chain callbacks: ")
local function b64length(len)
local a = math.ceil(len/3)*4
local l = math.ceil(a/76)
return a + l*2
end
local req_cb = socket.callback.send.chain(
socket.callback.send.file(io.open(index_file, "r")),
socket.mime.chain(
socket.mime.encode("base64"),
socket.mime.wrap("base64")
)
)
local resp_cb = socket.callback.receive.chain(
socket.mime.decode("base64"),
socket.callback.receive.file(io.open(index_file .. "-back", "w"))
)
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body_cb = req_cb,
headers = { ["content-length"] = b64length(string.len(index)) }
}
response = { body_cb = resp_cb }
expect = {
code = 200
}
ignore = {
body_cb = 1,
status = 1,
headers = 1
}
check_request_cb(request, response, expect, ignore)
back = readfile(index_file .. "-back")
check(back == index)
os.remove(index_file .. "-back")
------------------------------------------------------------------------
io.write("testing simple post function with table args: ")
back = socket.http.post {
url = "http://" .. host .. cgiprefix .. "/cat",
@ -154,6 +242,7 @@ back = socket.http.post {
}
check(back == index)
------------------------------------------------------------------------
io.write("testing http redirection: ")
request = {
url = "http://" .. host .. prefix
@ -168,6 +257,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing proxy with redirection: ")
request = {
url = "http://" .. host .. prefix,
@ -183,7 +273,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing automatic auth failure: ")
request = {
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html"
@ -198,6 +288,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing http redirection failure: ")
request = {
url = "http://" .. host .. prefix,
@ -213,6 +304,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing host not found: ")
request = {
url = "http://wronghost/does/not/exist"
@ -224,6 +316,7 @@ expect = {
ignore = {}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing invalid url: ")
request = {
url = host .. prefix
@ -235,6 +328,7 @@ expect = {
ignore = {}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing document not found: ")
request = {
url = "http://" .. host .. "/wrongdocument.html"
@ -249,6 +343,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing auth failure: ")
request = {
url = "http://" .. host .. prefix .. "/auth/index.html"
@ -263,6 +358,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing manual basic auth: ")
request = {
url = "http://" .. host .. prefix .. "/auth/index.html",
@ -280,6 +376,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing automatic basic auth: ")
request = {
url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html"
@ -294,6 +391,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing auth info overriding: ")
request = {
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
@ -310,6 +408,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing cgi output retrieval (probably chunked...): ")
request = {
url = "http://" .. host .. cgiprefix .. "/cat-index-html"
@ -324,6 +423,7 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing wrong scheme: ")
request = {
url = "wrong://" .. host .. cgiprefix .. "/cat",
@ -336,11 +436,13 @@ ignore = {
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
local body
io.write("testing simple get function: ")
body = socket.http.get("http://" .. host .. prefix .. "/index.html")
check(body == index)
------------------------------------------------------------------------
io.write("testing simple get function with table args: ")
body = socket.http.get {
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
@ -349,6 +451,7 @@ body = socket.http.get {
}
check(body == index)
------------------------------------------------------------------------
io.write("testing HEAD method: ")
socket.http.TIMEOUT = 1
response = socket.http.request {
@ -357,6 +460,7 @@ response = socket.http.request {
}
check(response and response.headers)
------------------------------------------------------------------------
print("passed all tests")
print(string.format("done in %.2fs", socket.time() - t))

View File

@ -66,8 +66,8 @@ local function compare(input, output)
end
local function encode_qptest(mode)
local encode = socket.mime.qprint.encode(mode)
local split = socket.mime.qprint.split()
local encode = socket.mime.encode("quoted-printable", mode)
local split = socket.mime.wrap("quoted-printable")
local chain = socket.mime.chain(encode, split)
transform(qptest, eqptest, chain)
end
@ -77,7 +77,7 @@ local function compare_qptest()
end
local function decode_qptest()
local decode = socket.mime.qprint.decode()
local decode = socket.mime.decode("quoted-printable")
transform(eqptest, dqptest, decode)
end
@ -151,23 +151,23 @@ local function cleanup_qptest()
end
local function encode_b64test()
local e1 = socket.mime.base64.encode()
local e2 = socket.mime.base64.encode()
local e3 = socket.mime.base64.encode()
local e4 = socket.mime.base64.encode()
local sp4 = socket.mime.split()
local sp3 = socket.mime.split(59)
local sp2 = socket.mime.split(30)
local sp1 = socket.mime.split(27)
local e1 = socket.mime.encode("base64")
local e2 = socket.mime.encode("base64")
local e3 = socket.mime.encode("base64")
local e4 = socket.mime.encode("base64")
local sp4 = socket.mime.wrap("character")
local sp3 = socket.mime.wrap("character", 59)
local sp2 = socket.mime.wrap("character", 30)
local sp1 = socket.mime.wrap("character", 27)
local chain = socket.mime.chain(e1, sp1, e2, sp2, e3, sp3, e4, sp4)
transform(b64test, eb64test, chain)
end
local function decode_b64test()
local d1 = socket.mime.base64.decode()
local d2 = socket.mime.base64.decode()
local d3 = socket.mime.base64.decode()
local d4 = socket.mime.base64.decode()
local d1 = socket.mime.decode("base64")
local d2 = socket.mime.decode("base64")
local d3 = socket.mime.decode("base64")
local d4 = socket.mime.decode("base64")
local chain = socket.mime.chain(d1, d2, d3, d4)
transform(eb64test, db64test, chain)
end