Saving before big changes to support IPv6.

This commit is contained in:
Diego Nehab 2011-05-25 20:57:22 +00:00
parent bce60be30f
commit 3a8ba90dfb
30 changed files with 948 additions and 850 deletions

13
FIX
View File

@ -1,15 +1,14 @@
http was preserving old host header during redirects
fix smtp.send hang on source error
add create field to FTP and SMTP and fix HTTP ugliness
clean timeout argument to open functions in SMTP, HTTP and FTP
eliminate globals from namespaces created by module().
url.absolute was not working when base_url was already parsed
http.request was redirecting even when the location header was empty
tcp{client}:shutdown() was checking for group instead of class.

46
NEW
View File

@ -2,19 +2,37 @@ What's New
This is just a bug-fix/update release.
* Fixed: manual links to home.html changed to index.html (Robert Hahn)
* Fixed: mime.unb64() returns empty string on results that start
with a null character (Robert Raschke)
* Fixed: HTTP now automatically redirecting on 303 and 307 (Jonathan Gray)
* Fixed: sleep(-1) could sleep forever wasting CPU. Now it
returns immediately (MPB);
* Fixed: manual sample of HTTP authentication now uses correct
"authorization" header (Alexandre Ittner);
* Fixed: failure on bind() was destroying the socket (Sam Roberts);
* Fixed: receive() returns immediatelly if prefix can satisfy
bytes requested (M Joonas Pihlaja);
* Fixed: multicast didn't work on Windows, or anywhere
else for that matter (Herbert Leuwer, Adrian Sietsma);
* Fixed: select() now reports an error when called with more
sockets than FD_SETSIZE (Lorenzo Leonini);
* Fixed: manual links to home.html changed to index.html (Robert Hahn);
* Fixed: mime.unb64() would return an empty string on results that started
with a null character (Robert Raschke);
* Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray);
* Fixed: calling sleep() with negative numbers could
block forever, wasting CPU. Now it returns immediately (MPB);
* Improved: FTP commands are now sent in upper case to
help buggy servers (Anders Eurenius);
* Improved: known headers now sent in canonic
capitalization to help buggy servers (Joseph Stewart);
* Improved: Clarified tcp:receive() in the manual (MPB);
* Improved: Decent makefiles (LHF).
* Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei).
* Improved: FTP commands are now sent in upper case to
help buggy servers (Anders Eurenius)
* Improved: known headers now sent in canonic
capitalization to help buggy servers (Joseph Stewart);
* Improved: Clarified tcp:receive() in the manual (MPB);
* Fixed: multicast didn't work on Windows (Herbert Leuwer, Adrian Sietsma)
* Fixed: select() reports an error when called with more
sockets than FD_SETSIZE (Lorenzo Leonini)
Yuri's bug?
Dahlberg
Sam Roberts
Thomas Harning Jr.
Sebastien Perin
remove getn in all files
ltn12.pump.all(
ltn12.source.file(io.open("original.png")),
ltn12.sink.file(io.open("copy.png", "wb"))
)

View File

@ -42,7 +42,7 @@
FTP (File Transfer Protocol) is a protocol used to transfer files
between hosts. The <tt>ftp</tt> namespace offers thorough support
to FTP, under a simple interface. The implementation conforms to
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc0959.txt">RFC 959</a>.
<a href="http://www.ietf.org/rfc/rfc959.txt">RFC 959</a>.
</p>
<p>
@ -70,8 +70,8 @@ local ftp = require("socket.ftp")
<p>
URLs MUST conform to
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
1738</a>, that is, an URL is a string in the form:
<a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>,
that is, an URL is a string in the form:
</p>
<blockquote>

View File

@ -45,8 +45,7 @@ namespace offers full support for the client side of the HTTP
protocol (i.e.,
the facilities that would be used by a web-browser implementation). The
implementation conforms to the HTTP/1.1 standard,
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
2616</a>.
<a href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>.
</p>
<p>
@ -67,8 +66,7 @@ local http = require("socket.http")
<p>
URLs must conform to
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
1738</a>,
<a href="http://www.ietf.org/rfc/rfc1738.txt">RFC 1738</a>,
that is, an URL is a string in the form:
</p>
@ -199,8 +197,7 @@ it usually returns a message body (a web page informing the
URL was not found or some other useless page). To make sure the
operation was successful, check the returned status <tt>code</tt>. For
a list of the possible values and their meanings, refer to <a
href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
2616</a>.
href="http://www.ietf.org/rfc/rfc2616.txt">RFC 2616</a>.
</p>
<p class=description>
@ -278,7 +275,7 @@ download and return status "401&nbsp;Authentication Required".
The HTTP/1.1 standard defines two authentication methods: the Basic
Authentication Scheme and the Digest Authentication Scheme, both
explained in detail in
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2068.txt">RFC 2068</a>.
<a href="http://www.ietf.org/rfc/rfc2068.txt">RFC 2068</a>.
</p>
<p class=note>The Basic Authentication Scheme sends
@ -304,7 +301,7 @@ b, c, h = http.request("http://fulano:silva@www.example.com/private/index.html")
-- the request directly.
r, c = http.request {
url = "http://www.example.com/private/index.html",
headers = { authentication = "Basic " .. (mime.b64("fulano:silva")) }
headers = { authorization = "Basic " .. (mime.b64("fulano:silva")) }
}
</pre>

View File

@ -138,18 +138,22 @@ all!
</p>
<ul>
<li> Fixed: manual sample of HTTP authentication now uses correct
"authorization" header (Alexandre Ittner);
<li> Fixed: receive() returns immediatelly if prefix can satisfy
bytes requested (M Joonas Pihlaja);
<li> Fixed: multicast didn't work on Windows, or anywhere
else for that matter (Herbert Leuwer, Adrian Sietsma)
else for that matter (Herbert Leuwer, Adrian Sietsma);
<li> Fixed: select() now reports an error when called with more
sockets than FD_SETSIZE (Lorenzo Leonini)
<li> Fixed: manual links to home.html changed to index.html (Robert Hahn)
sockets than FD_SETSIZE (Lorenzo Leonini);
<li> Fixed: manual links to home.html changed to index.html (Robert Hahn);
<li> Fixed: mime.unb64() would return an empty string on results that started
with a null character (Robert Raschke)
<li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray)
with a null character (Robert Raschke);
<li> Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray);
<li> Fixed: calling sleep() with negative numbers could
block forever, wasting CPU. Now it returns immediately (MPB);
<li> Improved: FTP commands are now sent in upper case to
help buggy servers (Anders Eurenius)
help buggy servers (Anders Eurenius);
<li> Improved: known headers now sent in canonic
capitalization to help buggy servers (Joseph Stewart);
<li> Improved: Clarified tcp:receive() in the manual (MPB);

View File

@ -44,11 +44,11 @@ content transfer encodings, such as Base64 and Quoted-Printable.
It also provides functions to break text into lines and change
the end-of-line convention.
MIME is described mainly in
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2045.txt">RFC 2045</a>,
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">2046</a>,
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2047</a>,
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2048</a>, and
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2048.txt">2049</a>.
<a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>,
<a href="http://www.ietf.org/rfc/rfc2046.txt">2046</a>,
<a href="http://www.ietf.org/rfc/rfc2047.txt">2047</a>,
<a href="http://www.ietf.org/rfc/rfc2047.txt">2048</a>, and
<a href="http://www.ietf.org/rfc/rfc2048.txt">2049</a>.
</p>
<p>

View File

@ -48,14 +48,13 @@ control (if you bother to read the code).
</p>
<p>The implementation conforms to the Simple Mail Transfer Protocol,
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>.
<a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a>.
Another RFC of interest is <a
href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>,
href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>,
which governs the Internet Message Format.
Multipart messages (those that contain attachments) are part
of the MIME standard, but described mainly
in <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">RFC
2046</a>
in <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>
<p> In the description below, good understanding of <a
href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters
@ -196,7 +195,7 @@ part of the message and will not be sent to anyone.
</p>
<p class=note>
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>
<a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>
has two <em>important and short</em> sections, "3.6.3. Destination address
fields" and "5. Security considerations", explaining the proper
use of these headers. Here is a summary of what it says:
@ -236,9 +235,9 @@ exactly what you <em>don't</em> want to happen!
<p class=note>
I hope this clarifies the issue. Otherwise, please refer to
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>
<a href="http://www.ietf.org/rfc/rfc2821.txt">RFC 2821</a>
and
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>.
<a href="http://www.ietf.org/rfc/rfc2822.txt">RFC 2822</a>.
</p>
<pre class=example>

View File

@ -42,8 +42,7 @@
The <tt>url</tt> namespace provides functions to parse, protect,
and build URLs, as well as functions to compose absolute URLs
from base and relative URLs, according to
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC
2396</a>.
<a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
</p>
<p>
@ -91,7 +90,7 @@ The function returns a string with the absolute URL.
<p class=note>
Note: The rules that
govern the composition are fairly complex, and are described in detail in
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC 2396</a>.
<a href="http://www.ietf.org/rfc/rfc2396.txt">RFC 2396</a>.
The example bellow should give an idea of what the rules are.
</p>

View File

@ -44,48 +44,48 @@ function metat.__index:check(ok)
end
function metat.__index:getdef()
local line = socket.try(self.tp:receive())
local def = {}
while line ~= "." do
table.insert(def, line)
line = socket.try(self.tp:receive())
end
return table.concat(def, "\n")
local line = socket.try(self.tp:receive())
local def = {}
while line ~= "." do
table.insert(def, line)
line = socket.try(self.tp:receive())
end
return table.concat(def, "\n")
end
function metat.__index:define(database, word)
database = database or "!"
socket.try(self.tp:command("DEFINE", database .. " " .. word))
socket.try(self.tp:command("DEFINE", database .. " " .. word))
local code, count = self:check(150)
local defs = {}
for i = 1, count do
self:check(151)
table.insert(defs, self:getdef())
end
self:check(250)
local defs = {}
for i = 1, count do
self:check(151)
table.insert(defs, self:getdef())
end
self:check(250)
return defs
end
function metat.__index:match(database, strat, word)
database = database or "!"
strat = strat or "."
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
self:check(152)
local mat = {}
local line = socket.try(self.tp:receive())
local mat = {}
local line = socket.try(self.tp:receive())
while line ~= '.' do
database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
if not mat[database] then mat[database] = {} end
table.insert(mat[database], word)
line = socket.try(self.tp:receive())
end
self:check(250)
line = socket.try(self.tp:receive())
end
self:check(250)
return mat
end
function metat.__index:quit()
self.tp:command("QUIT")
return self:check(221)
self.tp:command("QUIT")
return self:check(221)
end
function metat.__index:close()

View File

@ -12,53 +12,53 @@ local ltn12 = require("ltn12")
-- formats a number of seconds into human readable form
function nicetime(s)
local l = "s"
if s > 60 then
s = s / 60
l = "m"
if s > 60 then
s = s / 60
l = "h"
if s > 24 then
s = s / 24
l = "d" -- hmmm
end
end
end
if l == "s" then return string.format("%5.0f%s", s, l)
else return string.format("%5.2f%s", s, l) end
local l = "s"
if s > 60 then
s = s / 60
l = "m"
if s > 60 then
s = s / 60
l = "h"
if s > 24 then
s = s / 24
l = "d" -- hmmm
end
end
end
if l == "s" then return string.format("%5.0f%s", s, l)
else return string.format("%5.2f%s", s, l) end
end
-- formats a number of bytes into human readable form
function nicesize(b)
local l = "B"
if b > 1024 then
b = b / 1024
l = "KB"
if b > 1024 then
b = b / 1024
l = "MB"
if b > 1024 then
b = b / 1024
l = "GB" -- hmmm
end
end
end
return string.format("%7.2f%2s", b, l)
local l = "B"
if b > 1024 then
b = b / 1024
l = "KB"
if b > 1024 then
b = b / 1024
l = "MB"
if b > 1024 then
b = b / 1024
l = "GB" -- hmmm
end
end
end
return string.format("%7.2f%2s", b, l)
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(remaining_s, nicesize(got), nicesize(rate),
100*got/size, nicetime((size-got)/rate))
else
return string.format(elapsed_s, nicesize(got),
nicesize(rate), nicetime(delta))
end
local rate = got / delta
if size and size >= 1 then
return string.format(remaining_s, nicesize(got), nicesize(rate),
100*got/size, nicetime((size-got)/rate))
else
return string.format(elapsed_s, nicesize(got),
nicesize(rate), nicetime(delta))
end
end
-- creates a new instance of a receive_cb that saves to disk
@ -89,10 +89,10 @@ end
-- determines the size of a http file
function gethttpsize(u)
local r, c, h = http.request {method = "HEAD", url = u}
if c == 200 then
return tonumber(h["content-length"])
end
local r, c, h = http.request {method = "HEAD", url = u}
if c == 200 then
return tonumber(h["content-length"])
end
end
-- downloads a file using the http protocol
@ -101,7 +101,7 @@ function getbyhttp(u, file)
-- only print feedback if output is not stdout
if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end
local r, c, h, s = http.request {url = u, sink = save }
if c ~= 200 then io.stderr:write(s or c, "\n") end
if c ~= 200 then io.stderr:write(s or c, "\n") end
end
-- downloads a file using the ftp protocol
@ -114,29 +114,29 @@ function getbyftp(u, file)
gett.sink = save
gett.type = "i"
local ret, err = ftp.get(gett)
if err then print(err) end
if err then print(err) end
end
-- determines the scheme
function getscheme(u)
-- this is an heuristic to solve a common invalid url poblem
if not string.find(u, "//") then u = "//" .. u end
local parsed = url.parse(u, {scheme = "http"})
return parsed.scheme
-- this is an heuristic to solve a common invalid url poblem
if not string.find(u, "//") then u = "//" .. u end
local parsed = url.parse(u, {scheme = "http"})
return parsed.scheme
end
-- gets a file either by http or ftp, saving as <name>
function get(u, name)
local fout = name and io.open(name, "wb")
local scheme = getscheme(u)
if scheme == "ftp" then getbyftp(u, fout)
elseif scheme == "http" then getbyhttp(u, fout)
else print("unknown scheme" .. scheme) end
local scheme = getscheme(u)
if scheme == "ftp" then getbyftp(u, fout)
elseif scheme == "http" then getbyhttp(u, fout)
else print("unknown scheme" .. scheme) end
end
-- main program
arg = arg or {}
if table.getn(arg) < 1 then
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
os.exit(1)
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
os.exit(1)
else get(arg[1], arg[2]) end

View File

@ -268,11 +268,11 @@ send = socket.protect(function(option)
local class = string.sub(option.class or localip or localhost,1,31)
local _,_,ctlfn = string.find(file,".*[%/%\\](.*)")
ctlfn = string.sub(ctlfn or file,1,131)
local cfile =
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
localhost,
local cfile =
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
localhost,
class,
option.job or "LuaSocket",
option.job or "LuaSocket",
user,
fmt, lpfile,
lpfile,

View File

@ -35,18 +35,18 @@ local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"}
-- Packet creation functions
-----------------------------------------------------------------------------
local function RRQ(source, mode)
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
end
local function WRQ(source, mode)
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
end
local function ACK(block)
local low, high
low = math.mod(block, 256)
high = (block - low)/256
return char(0, OP_ACK, high, low)
local low, high
low = math.mod(block, 256)
high = (block - low)/256
return char(0, OP_ACK, high, low)
end
local function get_OP(dgram)
@ -58,16 +58,16 @@ end
-- Packet analysis functions
-----------------------------------------------------------------------------
local function split_DATA(dgram)
local block = byte(dgram, 3)*256 + byte(dgram, 4)
local data = string.sub(dgram, 5)
return block, data
local block = byte(dgram, 3)*256 + byte(dgram, 4)
local data = string.sub(dgram, 5)
return block, data
end
local function get_ERROR(dgram)
local code = byte(dgram, 3)*256 + byte(dgram, 4)
local msg
_,_, msg = string.find(dgram, "(.*)\000", 5)
return string.format("error code %d: %s", code, msg)
local code = byte(dgram, 3)*256 + byte(dgram, 4)
local msg
_,_, msg = string.find(dgram, "(.*)\000", 5)
return string.format("error code %d: %s", code, msg)
end
-----------------------------------------------------------------------------
@ -77,40 +77,40 @@ local function tget(gett)
local retries, dgram, sent, datahost, dataport, code
local last = 0
socket.try(gett.host, "missing host")
local con = socket.try(socket.udp())
local con = socket.try(socket.udp())
local try = socket.newtry(function() con:close() end)
-- convert from name to ip if needed
gett.host = try(socket.dns.toip(gett.host))
con:settimeout(1)
gett.host = try(socket.dns.toip(gett.host))
con:settimeout(1)
-- first packet gives data host/port to be used for data transfers
local path = string.gsub(gett.path or "", "^/", "")
path = url.unescape(path)
retries = 0
repeat
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
dgram, datahost, dataport = con:receivefrom()
repeat
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
dgram, datahost, dataport = con:receivefrom()
retries = retries + 1
until dgram or datahost ~= "timeout" or retries > 5
try(dgram, datahost)
until dgram or datahost ~= "timeout" or retries > 5
try(dgram, datahost)
-- associate socket with data host/port
try(con:setpeername(datahost, dataport))
try(con:setpeername(datahost, dataport))
-- default sink
local sink = gett.sink or ltn12.sink.null()
-- process all data packets
while 1 do
while 1 do
-- decode packet
code = get_OP(dgram)
try(code ~= OP_ERROR, get_ERROR(dgram))
code = get_OP(dgram)
try(code ~= OP_ERROR, get_ERROR(dgram))
try(code == OP_DATA, "unhandled opcode " .. code)
-- get data packet parts
local block, data = split_DATA(dgram)
local block, data = split_DATA(dgram)
-- if not repeated, write
if block == last+1 then
try(sink(data))
try(sink(data))
last = block
end
-- last packet brings less than 512 bytes of data
if string.len(data) < 512 then
if string.len(data) < 512 then
try(con:send(ACK(block)))
try(con:close())
try(sink(nil))
@ -118,13 +118,13 @@ local function tget(gett)
end
-- get the next packet
retries = 0
repeat
sent = try(con:send(ACK(last)))
dgram, err = con:receive()
repeat
sent = try(con:send(ACK(last)))
dgram, err = con:receive()
retries = retries + 1
until dgram or err ~= "timeout" or retries > 5
try(dgram, err)
end
until dgram or err ~= "timeout" or retries > 5
try(dgram, err)
end
end
local default = {

View File

@ -1,21 +1,13 @@
PLAT= none
PLATS= macosx linux
PLAT?= macosx
PLATS= macosx linux win32
#------
# Hopefully no need to change anything below this line
#
all: $(PLAT)
none:
@echo "Please run"
@echo " make PLATFORM"
@echo "where PLATFORM is one of these:"
@echo " $(PLATS)"
$(PLATS) install local clean:
cd src; $(MAKE) $@
dummy:
$(PLATS) none install local clean:
@cd src; $(MAKE) $@
test: dummy
lua test/hello.lua

View File

@ -42,7 +42,7 @@ int buffer_open(lua_State *L) {
* Initializes C structure
\*-------------------------------------------------------------------------*/
void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
buf->first = buf->last = 0;
buf->first = buf->last = 0;
buf->io = io;
buf->tm = tm;
buf->received = buf->sent = 0;
@ -122,9 +122,15 @@ int buffer_meth_receive(lua_State *L, p_buffer buf) {
if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
else luaL_argcheck(L, 0, 2, "invalid receive pattern");
/* get a fixed number of bytes (minus what was already partially
* received) */
} else err = recvraw(buf, (size_t) lua_tonumber(L, 2)-size, &b);
/* get a fixed number of bytes (minus what was already partially
* received) */
} else {
double n = lua_tonumber(L, 2);
size_t wanted = (size_t) n;
luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
if (size == 0 || wanted > size)
err = recvraw(buf, wanted-size, &b);
}
/* check if there was an error */
if (err != IO_DONE) {
/* we can't push anyting in the stack before pushing the

View File

@ -29,8 +29,8 @@ typedef struct t_buffer_ {
size_t sent, received; /* bytes sent, and bytes received */
p_io io; /* IO driver used for this buffer */
p_timeout tm; /* timeout management for this buffer */
size_t first, last; /* index of first and last bytes of stored data */
char data[BUF_SIZE]; /* storage space for buffer data */
size_t first, last; /* index of first and last bytes of stored data */
char data[BUF_SIZE]; /* storage space for buffer data */
} t_buffer;
typedef t_buffer *p_buffer;

View File

@ -212,8 +212,8 @@ local function tput(putt)
end
local default = {
path = "/",
scheme = "ftp"
path = "/",
scheme = "ftp"
}
local function parse(u)

View File

@ -213,7 +213,7 @@ const char *inet_tryconnect(p_socket ps, const char *address,
memset(&remote, 0, sizeof(remote));
remote.sin_family = AF_INET;
remote.sin_port = htons(port);
if (strcmp(address, "*")) {
if (strcmp(address, "*")) {
if (!inet_aton(address, &remote.sin_addr)) {
struct hostent *hp = NULL;
struct in_addr **addr;
@ -248,7 +248,6 @@ const char *inet_trybind(p_socket ps, const char *address, unsigned short port)
memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
}
err = socket_bind(ps, (SA *) &local, sizeof(local));
if (err != IO_DONE) socket_destroy(ps);
return socket_strerror(err);
}

View File

@ -1,8 +1,13 @@
PLAT = none
PLAT?=macosx
INSTALL_DATA=cp
INSTALL_EXEC=cp
INSTALL_TOP= /opt/local
LUAINC= $(LUAINC_$(PLAT))
INSTALL_TOP=/opt/local
LUAINC_macosx=/opt/local/include
LUAINC_linux=/usr/include/lua5.1
LUAINC_win32="../../lua-5.1.3/src"
LUALIB_win32="../../lua-5.1.3"
#------
# Install directories
@ -15,40 +20,76 @@ INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
#------
# Output file names
# Supported platforms
#
EXT=so
SOCKET_V=2.0.3
MIME_V=1.0.3
SOCKET_SO=socket.$(EXT).$(SOCKET_V)
MIME_SO=mime.$(EXT).$(MIME_V)
UNIX_SO=unix.$(EXT)
PLATS= macosx linux win32
#------
# Compiler and linker settings
# for Mac OS X
LUAINC_macosx= -I/opt/local/include
SO_macosx=so
O_macosx=o
CC_macosx=gcc
DEF_macosx= -DLUASOCKET_DEBUG -DUNIX_HAS_SUN_LEN \
-DLUASOCKET_API='__attribute__((visibility("default")))' \
-DMIME_API='__attribute__((visibility("default")))'
CFLAGS_macosx= $(LUAINC) $(COMPAT) $(DEF) -pedantic -Wall -O2 -fno-common \
CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \
-fvisibility=hidden
LDFLAGS_macosx= -bundle -undefined dynamic_lookup
LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o
LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc
SOCKET_macosx=usocket.o
#------
# Compiler and linker settings
# for Linux
LUAINC_linux= -I/usr/local/include/lua5.1
SO_linux=so
O_linux=o
CC_linux=gcc
DEF_linux=-DLUASOCKET_DEBUG \
-DLUASOCKET_API='__attribute__((visibility("default")))' \
-DMIME_API='__attribute__((visibility("default")))'
CFLAGS_linux= $(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \
CFLAGS_linux= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fpic \
-fvisibility=hidden
LDFLAGS_linux=-O -shared -fpic
LD_linux= gcc
LDFLAGS_linux=-O -shared -fpic -o
LD_linux=gcc
SOCKET_linux=usocket.o
#------
# Compiler and linker settings
# for Win32
SO_win32=dll
O_win32=obj
CC_win32=cl
DEF_win32= /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" \
/D "LUASOCKET_API=__declspec(dllexport)" /D "LUASOCKET_DEBUG" \
/D "_CRT_SECURE_NO_WARNINGS" /D "_WINDLL"
CFLAGS_win32=/I$(LUAINC) $(DEF) /O2 /Ot /MD /W3 /nologo
LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \
/LIBPATH:$(LUALIB) \
/MANIFEST \
/MANIFESTFILE:"intermediate.manifest" \
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \
/MACHINE:X86 ws2_32.lib lua5.1.lib /OUT:
LD_win32=cl
SOCKET_win32=wsocket.obj
.SUFFIXES: .obj
.c.obj:
$(CC) $(CFLAGS) /Fo"$@" /c $<
#------
# Output file names
#
SO=$(SO_$(PLAT))
O=$(O_$(PLAT))
SOCKET_V=2.0.3
MIME_V=1.0.3
SOCKET_SO=socket.$(SO).$(SOCKET_V)
MIME_SO=mime.$(SO).$(MIME_V)
UNIX_SO=unix.$(SO)
SOCKET=$(SOCKET_$(PLAT))
#------
# Settings selected for platform
@ -58,46 +99,48 @@ DEF=$(DEF_$(PLAT))
CFLAGS=$(CFLAGS_$(PLAT))
LDFLAGS=$(LDFLAGS_$(PLAT))
LD=$(LD_$(PLAT))
LUAINC= $(LUAINC_$(PLAT))
LUALIB= $(LUALIB_$(PLAT))
#------
# Modules belonging to socket-core
#
SOCKET_OBJS= \
luasocket.o \
timeout.o \
buffer.o \
io.o \
auxiliar.o \
options.o \
inet.o \
usocket.o \
except.o \
select.o \
tcp.o \
udp.o
luasocket.$(O) \
timeout.$(O) \
buffer.$(O) \
io.$(O) \
auxiliar.$(O) \
options.$(O) \
inet.$(O) \
$(SOCKET) \
except.$(O) \
select.$(O) \
tcp.$(O) \
udp.$(O)
#------
# Modules belonging mime-core
#
MIME_OBJS= \
mime.o
mime.$(O)
#------
# Modules belonging unix (local domain sockets)
#
UNIX_OBJS:=\
buffer.o \
auxiliar.o \
options.o \
timeout.o \
io.o \
usocket.o \
unix.o
UNIX_OBJS=\
buffer.$(O) \
auxiliar.$(O) \
options.$(O) \
timeout.$(O) \
io.$(O) \
usocket.$(O) \
unix.$(O)
#------
# Files to install
#
TO_SOCKET_SHARE:= \
TO_SOCKET_SHARE= \
http.lua \
url.lua \
tp.lua \
@ -105,33 +148,41 @@ TO_SOCKET_SHARE:= \
headers.lua \
smtp.lua
TO_TOP_SHARE:= \
TO_TOP_SHARE= \
ltn12.lua \
socket.lua \
mime.lua
#------
# Targets
#
default: $(PLAT)
macosx:
$(MAKE) all PLAT=macosx
win32:
$(MAKE) all PLAT=win32
linux:
$(MAKE) all PLAT=linux
none:
@echo "Please choose a platform:"
@echo "Please run"
@echo " make PLATFORM"
@echo "where PLATFORM is one of these:"
@echo " $(PLATS)"
all: $(SOCKET_SO) $(MIME_SO)
$(SOCKET_SO): $(SOCKET_OBJS)
$(LD) $(LDFLAGS) -o $@ $(SOCKET_OBJS)
$(LD) $(SOCKET_OBJS) $(LDFLAGS)$@
$(MIME_SO): $(MIME_OBJS)
$(LD) $(LDFLAGS) -o $@ $(MIME_OBJS)
$(LD) $(MIME_OBJS) $(LDFLAGS)$@
$(UNIX_SO): $(UNIX_OBJS)
$(LD) $(LDFLAGS) -o $@ $(UNIX_OBJS)
$(LD) $(UNIX_OBJS) $(LDFLAGS)$@
install:
mkdir -p $(INSTALL_TOP_SHARE)
@ -139,9 +190,9 @@ install:
mkdir -p $(INSTALL_SOCKET_SHARE)
$(INSTALL_DATA) $(TO_SOCKET_SHARE) $(INSTALL_SOCKET_SHARE)
mkdir -p $(INSTALL_SOCKET_LIB)
$(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(EXT)
$(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_LIB)/core.$(SO)
mkdir -p $(INSTALL_MIME_LIB)
$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(EXT)
$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO)
local:
$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
@ -155,24 +206,24 @@ clean:
#------
# List of dependencies
#
auxiliar.o: auxiliar.c auxiliar.h
buffer.o: buffer.c buffer.h io.h timeout.h
except.o: except.c except.h
inet.o: inet.c inet.h socket.h io.h timeout.h usocket.h
io.o: io.c io.h timeout.h
luasocket.o: luasocket.c luasocket.h auxiliar.h except.h \
auxiliar.$(O): auxiliar.c auxiliar.h
buffer.$(O): buffer.c buffer.h io.h timeout.h
except.$(O): except.c except.h
inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h
io.$(O): io.c io.h timeout.h
luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \
timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \
udp.h select.h
mime.o: mime.c mime.h
options.o: options.c auxiliar.h options.h socket.h io.h \
mime.$(O): mime.c mime.h
options.$(O): options.c auxiliar.h options.h socket.h io.h \
timeout.h usocket.h inet.h
select.o: select.c socket.h io.h timeout.h usocket.h select.h
tcp.o: tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
select.$(O): select.c socket.h io.h timeout.h usocket.h select.h
tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
inet.h options.h tcp.h buffer.h
timeout.o: timeout.c auxiliar.h timeout.h
udp.o: udp.c auxiliar.h socket.h io.h timeout.h usocket.h \
timeout.$(O): timeout.c auxiliar.h timeout.h
udp.$(O): udp.c auxiliar.h socket.h io.h timeout.h usocket.h \
inet.h options.h udp.h
unix.o: unix.c auxiliar.h socket.h io.h timeout.h usocket.h \
unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \
options.h unix.h buffer.h
usocket.o: usocket.c socket.h io.h timeout.h usocket.h
wsocket.o: wsocket.c socket.h io.h timeout.h usocket.h
usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h
wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h

View File

@ -5,10 +5,10 @@ mbox = Public
function Public.split_message(message_s)
local message = {}
message_s = string.gsub(message_s, "\r\n", "\n")
string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
if not message.body then
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
end
if not message.headers and not message.body then
message.headers = message_s
@ -54,30 +54,30 @@ function Public.parse_from(from)
name = name or ""
address = address or ""
if name == "" then name = address end
name = string.gsub(name, '"', "")
name = string.gsub(name, '"', "")
return name, address
end
function Public.split_mbox(mbox_s)
mbox = {}
mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
local nj, i, j = 1, 1, 1
while 1 do
i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
if not i then break end
local message = string.sub(mbox_s, j, i-1)
table.insert(mbox, message)
j = nj+1
end
return mbox
mbox = {}
mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
local nj, i, j = 1, 1, 1
while 1 do
i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
if not i then break end
local message = string.sub(mbox_s, j, i-1)
table.insert(mbox, message)
j = nj+1
end
return mbox
end
function Public.parse(mbox_s)
local mbox = Public.split_mbox(mbox_s)
for i = 1, table.getn(mbox) do
mbox[i] = Public.parse_message(mbox[i])
end
return mbox
local mbox = Public.split_mbox(mbox_s)
for i = 1, table.getn(mbox) do
mbox[i] = Public.parse_message(mbox[i])
end
return mbox
end
function Public.parse_message(message_s)

View File

@ -106,7 +106,7 @@ end
-- closes the underlying c
function metat.__index:close()
self.c:close()
return 1
return 1
end
-- connect with server and return c object

View File

@ -40,25 +40,25 @@ end
-- escaped representation of string binary
-----------------------------------------------------------------------------
local function make_set(t)
local s = {}
for i,v in base.ipairs(t) do
s[t[i]] = 1
end
return s
local s = {}
for i,v in base.ipairs(t) do
s[t[i]] = 1
end
return s
end
-- these are allowed withing a path segment, along with alphanum
-- other characters must be escaped
local segment_set = make_set {
"-", "_", ".", "!", "~", "*", "'", "(",
")", ":", "@", "&", "=", "+", "$", ",",
")", ":", "@", "&", "=", "+", "$", ",",
}
local function protect_segment(s)
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
if segment_set[c] then return c
else return string.format("%%%02x", string.byte(c)) end
end)
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
if segment_set[c] then return c
else return string.format("%%%02x", string.byte(c)) end
end)
end
-----------------------------------------------------------------------------
@ -182,20 +182,26 @@ function build(parsed)
local url = 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
if parsed.host then
authority = parsed.host
if parsed.port then authority = authority .. ":" .. parsed.port end
local userinfo = parsed.userinfo
if parsed.user then
userinfo = parsed.user
if parsed.password then
userinfo = userinfo .. ":" .. parsed.password
end
end
if userinfo then authority = userinfo .. "@" .. authority end
end
if authority then url = "//" .. authority .. url end
local authority = parsed.authority
if parsed.host then
authority = parsed.host
if parsed.port then authority = authority .. ":" .. parsed.port end
local userinfo = parsed.userinfo
if parsed.user then
userinfo = parsed.user
if parsed.password then
userinfo = userinfo .. ":" .. parsed.password
end
end
if userinfo then authority = userinfo .. "@" .. authority end
end
if authority then
if string.sub(url, 1, 1) == "/" then
url = "//" .. authority .. url
else
url = "//" .. authority .. "/" .. url
end
end
if parsed.scheme then url = parsed.scheme .. ":" .. url end
if parsed.fragment then url = url .. "#" .. parsed.fragment end
-- url = string.gsub(url, "%s", "")
@ -211,8 +217,8 @@ end
-- corresponding absolute url
-----------------------------------------------------------------------------
function absolute(base_url, relative_url)
local base_parsed = base_url
if base.type(base_url) == "table" then
base_parsed = base_url
base_url = build(base_parsed)
else
base_parsed = parse(base_url)
@ -250,16 +256,16 @@ end
-- segment: a table with one entry per segment
-----------------------------------------------------------------------------
function 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, table.getn(parsed) do
parsed[i] = 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
return parsed
local parsed = {}
path = path or ""
--path = string.gsub(path, "%s", "")
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
for i = 1, table.getn(parsed) do
parsed[i] = 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
return parsed
end
-----------------------------------------------------------------------------
@ -271,27 +277,27 @@ end
-- path: corresponding path stringing
-----------------------------------------------------------------------------
function build_path(parsed, unsafe)
local path = ""
local n = table.getn(parsed)
if unsafe then
for i = 1, n-1 do
path = path .. parsed[i]
path = path .. "/"
end
if n > 0 then
path = path .. parsed[n]
if parsed.is_directory then path = path .. "/" end
end
else
for i = 1, n-1 do
path = path .. protect_segment(parsed[i])
path = path .. "/"
end
if n > 0 then
path = path .. protect_segment(parsed[n])
if parsed.is_directory then path = path .. "/" end
end
end
if parsed.is_absolute then path = "/" .. path end
return path
local path = ""
local n = table.getn(parsed)
if unsafe then
for i = 1, n-1 do
path = path .. parsed[i]
path = path .. "/"
end
if n > 0 then
path = path .. parsed[n]
if parsed.is_directory then path = path .. "/" end
end
else
for i = 1, n-1 do
path = path .. protect_segment(parsed[i])
path = path .. "/"
end
if n > 0 then
path = path .. protect_segment(parsed[n])
if parsed.is_directory then path = path .. "/" end
end
end
if parsed.is_absolute then path = "/" .. path end
return path
end

View File

@ -30,9 +30,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
pfd.revents = 0;
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
do {
int t = (int)(timeout_getretry(tm)*1e3);
ret = poll(&pfd, 1, t >= 0? t: -1);
} while (ret == -1 && errno == EINTR);
int t = (int)(timeout_getretry(tm)*1e3);
ret = poll(&pfd, 1, t >= 0? t: -1);
} while (ret == -1 && errno == EINTR);
if (ret == -1) return errno;
if (ret == 0) return IO_TIMEOUT;
if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;

View File

@ -54,7 +54,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
if (sw & WAITFD_R) {
FD_ZERO(&rfds);
FD_SET(*ps, &rfds);
FD_SET(*ps, &rfds);
rp = &rfds;
}
if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
@ -207,7 +207,7 @@ int socket_send(p_socket ps, const char *data, size_t count,
/* loop until we send something or we give up on error */
for ( ;; ) {
/* try to send something */
int put = send(*ps, data, (int) count, 0);
int put = send(*ps, data, (int) count, 0);
/* if we sent something, we are done */
if (put > 0) {
*sent = put;
@ -346,8 +346,8 @@ const char *socket_strerror(int err) {
}
const char *socket_ioerror(p_socket ps, int err) {
(void) ps;
return socket_strerror(err);
(void) ps;
return socket_strerror(err);
}
static const char *wstrerror(int err) {

View File

@ -82,10 +82,10 @@ print("ok")
io.write("testing parameter overriding: ")
local back = {}
ret, err = ftp.get{
url = "//stupid:mistake@" .. host .. "/index.html",
user = "luasocket",
password = "pedrovian",
type = "i",
url = "//stupid:mistake@" .. host .. "/index.html",
user = "luasocket",
password = "pedrovian",
type = "i",
sink = ltn12.sink.table(back)
}
assert(ret and not err and table.concat(back) == index, err)

View File

@ -34,28 +34,28 @@ index_file = "index.html"
index = readfile(index_file)
local check_result = function(response, expect, ignore)
for i,v in pairs(response) do
if not ignore[i] then
if v ~= expect[i] then
for i,v in pairs(response) do
if not ignore[i] then
if v ~= expect[i] then
local f = io.open("err", "w")
f:write(tostring(v), "\n\n versus\n\n", tostring(expect[i]))
f:close()
fail(i .. " differs!")
end
end
end
for i,v in pairs(expect) do
if not ignore[i] then
if v ~= response[i] then
end
end
for i,v in pairs(expect) do
if not ignore[i] then
if v ~= response[i] then
local f = io.open("err", "w")
f:write(tostring(response[i]), "\n\n versus\n\n", tostring(v))
v = string.sub(type(v) == "string" and v or "", 1, 70)
f:close()
fail(i .. " differs!")
end
end
end
print("ok")
end
end
print("ok")
end
local check_request = function(request, expect, ignore)
@ -63,7 +63,7 @@ local check_request = function(request, expect, ignore)
if not request.sink then request.sink, t = ltn12.sink.table() end
request.source = request.source or
(request.body and ltn12.source.string(request.body))
local response = {}
local response = {}
response.code, response.headers, response.status =
socket.skip(1, http.request(request))
if t and table.getn(t) > 0 then response.body = table.concat(t) end
@ -90,15 +90,15 @@ else fail("failed!") end
------------------------------------------------------------------------
io.write("testing document retrieval: ")
request = {
url = "http://" .. host .. prefix .. "/index.html"
url = "http://" .. host .. prefix .. "/index.html"
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
@ -111,9 +111,9 @@ expect = {
code = 302
}
ignore = {
status = 1,
headers = 1,
body = 1
status = 1,
headers = 1,
body = 1
}
check_request(request, expect, ignore)
@ -144,19 +144,19 @@ check_request(request, expect, ignore)
io.write("testing post method: ")
-- wanted to test chunked post, but apache doesn't support it...
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body = index,
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body = index,
-- remove content-length header to send chunked body
headers = { ["content-length"] = string.len(index) }
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
@ -164,19 +164,19 @@ check_request(request, expect, ignore)
--[[
io.write("testing proxy with post method: ")
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body = index,
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
body = index,
headers = { ["content-length"] = string.len(index) },
proxy= proxy
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
]]
@ -190,18 +190,18 @@ print("ok")
------------------------------------------------------------------------
io.write("testing ltn12.(sink|source).file: ")
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
source = ltn12.source.file(io.open(index_file, "rb")),
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
source = ltn12.source.file(io.open(index_file, "rb")),
sink = ltn12.sink.file(io.open(index_file .. "-back", "wb")),
headers = { ["content-length"] = string.len(index) }
}
expect = {
code = 200
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
back = readfile(index_file .. "-back")
@ -231,19 +231,19 @@ local sink = ltn12.sink.chain(
)
request = {
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
source = source,
url = "http://" .. host .. cgiprefix .. "/cat",
method = "POST",
source = source,
sink = sink,
headers = { ["content-length"] = b64length(string.len(index)) }
}
expect = {
code = 200
code = 200
}
ignore = {
body_cb = 1,
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
back = readfile(index_file .. "-back")
@ -253,15 +253,15 @@ os.remove(index_file .. "-back")
------------------------------------------------------------------------
io.write("testing http redirection: ")
request = {
url = "http://" .. host .. prefix
url = "http://" .. host .. prefix
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
@ -269,16 +269,16 @@ check_request(request, expect, ignore)
--[[
io.write("testing proxy with redirection: ")
request = {
url = "http://" .. host .. prefix,
url = "http://" .. host .. prefix,
proxy = proxy
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
]]
@ -293,104 +293,104 @@ expect = {
}
ignore = {
body = 1,
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing http redirection failure: ")
request = {
url = "http://" .. host .. prefix,
redirect = false
url = "http://" .. host .. prefix,
redirect = false
}
expect = {
code = 301
}
ignore = {
body = 1,
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing document not found: ")
request = {
url = "http://" .. host .. "/wrongdocument.html"
url = "http://" .. host .. "/wrongdocument.html"
}
expect = {
code = 404
code = 404
}
ignore = {
body = 1,
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing auth failure: ")
request = {
url = "http://" .. host .. prefix .. "/auth/index.html"
url = "http://" .. host .. prefix .. "/auth/index.html"
}
expect = {
code = 401
code = 401
}
ignore = {
body = 1,
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing manual basic auth: ")
request = {
url = "http://" .. host .. prefix .. "/auth/index.html",
headers = {
authorization = "Basic " .. (mime.b64("luasocket:password"))
}
url = "http://" .. host .. prefix .. "/auth/index.html",
headers = {
authorization = "Basic " .. (mime.b64("luasocket:password"))
}
}
expect = {
code = 200,
body = index
code = 200,
body = index
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing automatic basic auth: ")
request = {
url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html"
url = "http://luasocket:password@" .. host .. prefix .. "/auth/index.html"
}
expect = {
code = 200,
body = index
code = 200,
body = index
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
------------------------------------------------------------------------
io.write("testing auth info overriding: ")
request = {
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
user = "luasocket",
password = "password"
url = "http://really:wrong@" .. host .. prefix .. "/auth/index.html",
user = "luasocket",
password = "password"
}
expect = {
code = 200,
body = index
code = 200,
body = index
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)
@ -400,12 +400,12 @@ request = {
url = "http://" .. host .. cgiprefix .. "/cat-index-html"
}
expect = {
body = index,
code = 200
body = index,
code = 200
}
ignore = {
status = 1,
headers = 1
status = 1,
headers = 1
}
check_request(request, expect, ignore)

View File

@ -19,11 +19,11 @@ local parse = mbox.parse
dofile("testsupport.lua")
local total = function()
local t = 0
for i = 1, table.getn(sent) do
t = t + sent[i].count
end
return t
local t = 0
for i = 1, table.getn(sent) do
t = t + sent[i].count
end
return t
end
local similar = function(s1, s2)
@ -39,14 +39,14 @@ local fail = function(s)
end
local readfile = function(name)
local f = io.open(name, "r")
if not f then
local f = io.open(name, "r")
if not f then
fail("unable to open file!")
return nil
end
local s = f:read("*a")
f:close()
return s
local s = f:read("*a")
f:close()
return s
end
local empty = function()
@ -62,7 +62,7 @@ end
local get = function()
local s = ""
for i,v in ipairs(files) do
s = s .. "\n" .. readfile(v)
s = s .. "\n" .. readfile(v)
end
return s
end
@ -82,40 +82,40 @@ local check_body = function(sent, got)
end
local check = function(sent, m)
io.write("checking ", m.headers.title, ": ")
for i = 1, table.getn(sent) do
local s = sent[i]
if s.title == m.headers.title and s.count > 0 then
check_headers(s.headers, m.headers)
check_body(s.body, m.body)
s.count = s.count - 1
print("ok")
return
end
end
fail("not found")
io.write("checking ", m.headers.title, ": ")
for i = 1, table.getn(sent) do
local s = sent[i]
if s.title == m.headers.title and s.count > 0 then
check_headers(s.headers, m.headers)
check_body(s.body, m.body)
s.count = s.count - 1
print("ok")
return
end
end
fail("not found")
end
local insert = function(sent, message)
if type(message.rcpt) == "table" then
message.count = table.getn(message.rcpt)
else message.count = 1 end
message.headers = message.headers or {}
message.headers.title = message.title
table.insert(sent, message)
if type(message.rcpt) == "table" then
message.count = table.getn(message.rcpt)
else message.count = 1 end
message.headers = message.headers or {}
message.headers.title = message.title
table.insert(sent, message)
end
local mark = function()
local time = socket.time()
local time = socket.time()
return { time = time }
end
local wait = function(sentinel, n)
local to
io.write("waiting for ", n, " messages: ")
io.write("waiting for ", n, " messages: ")
while 1 do
local mbox = parse(get())
if n == table.getn(mbox) then break end
local mbox = parse(get())
if n == table.getn(mbox) then break end
if socket.time() - sentinel.time > 50 then
to = 1
break
@ -124,8 +124,8 @@ local wait = function(sentinel, n)
io.write(".")
io.stdout:flush()
end
if to then fail("timeout")
else print("ok") end
if to then fail("timeout")
else print("ok") end
end
local stuffed_body = [[
@ -144,21 +144,21 @@ a lot of trouble.
insert(sent, {
from = from,
rcpt = {
"luasocket@localhost",
"luasock3@dell-diego.cs.princeton.edu",
"luasock1@dell-diego.cs.princeton.edu"
},
body = "multiple rcpt body",
title = "multiple rcpt",
"luasocket@localhost",
"luasock3@dell-diego.cs.princeton.edu",
"luasock1@dell-diego.cs.princeton.edu"
},
body = "multiple rcpt body",
title = "multiple rcpt",
})
insert(sent, {
from = from,
rcpt = {
"luasock2@localhost",
"luasock3",
"luasock1"
},
"luasock2@localhost",
"luasock3",
"luasock1"
},
headers = {
header1 = "header 1",
header2 = "header 2",
@ -210,24 +210,24 @@ insert(sent, {
io.write("testing host not found: ")
local c, e = socket.connect("wrong.host", 25)
local ret, err = socket.smtp.mail{
from = from,
rcpt = rcpt,
server = "wrong.host"
from = from,
rcpt = rcpt,
server = "wrong.host"
}
if ret or e ~= err then fail("wrong error message")
else print("ok") end
io.write("testing invalid from: ")
local ret, err = socket.smtp.mail{
from = ' " " (( _ * ',
rcpt = rcpt,
from = ' " " (( _ * ',
rcpt = rcpt,
}
if ret or not err then fail("wrong error message")
else print(err) end
io.write("testing no rcpt: ")
local ret, err = socket.smtp.mail{
from = from,
from = from,
}
if ret or not err then fail("wrong error message")
else print(err) end
@ -252,7 +252,7 @@ local mbox = parse(get())
print(table.getn(mbox) .. " messages found!")
for i = 1, table.getn(mbox) do
check(sent, mbox[i])
check(sent, mbox[i])
end
print("passed all tests")

View File

@ -3,15 +3,20 @@ local socket = require"socket"
host = host or "localhost"
port = port or "8383"
function pass(...)
function printf(...)
local s = string.format(unpack(arg))
io.stderr:write(s, "\n")
io.stderr:write(s)
end
function pass(...)
printf(...)
io.stderr:write("\n")
end
function fail(...)
local s = string.format(unpack(arg))
io.stderr:write("ERROR: ", s, "!\n")
socket.sleep(3)
io.stderr:write("ERROR: ")
printf(...)
io.stderr:write("!\n")
os.exit()
end
@ -80,7 +85,6 @@ io.stderr:write("----------------------------------------------\n",
start = socket.gettime()
function reconnect()
io.stderr:write("attempting data connection... ")
if data then data:close() end
remote [[
if data then data:close() data = nil end
@ -88,12 +92,11 @@ function reconnect()
data:setoption("tcp-nodelay", true)
]]
data, err = socket.connect(host, port)
if not data then fail(err)
else pass("connected!") end
if not data then fail(err) end
data:setoption("tcp-nodelay", true)
end
pass("attempting control connection...")
printf("attempting control connection...")
control, err = socket.connect(host, port)
if err then fail(err)
else pass("connected!") end
@ -112,6 +115,7 @@ end
------------------------------------------------------------------------
function test_mixed(len)
reconnect()
io.stderr:write("length " .. len .. ": ")
local inter = math.ceil(len/4)
local p1 = "unix " .. string.rep("x", inter) .. "line\n"
local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
@ -139,6 +143,7 @@ end
------------------------------------------------------------------------
function test_asciiline(len)
reconnect()
io.stderr:write("length " .. len .. ": ")
local str, str10, back, err
str = string.rep("x", math.mod(len, 10))
str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
@ -156,6 +161,7 @@ end
------------------------------------------------------------------------
function test_rawline(len)
reconnect()
io.stderr:write("length " .. len .. ": ")
local str, str10, back, err
str = string.rep(string.char(47), math.mod(len, 10))
str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
@ -174,6 +180,7 @@ end
------------------------------------------------------------------------
function test_raw(len)
reconnect()
io.stderr:write("length " .. len .. ": ")
local half = math.floor(len/2)
local s1, s2, back, err
s1 = string.rep("x", half)
@ -194,7 +201,7 @@ end
function test_totaltimeoutreceive(len, tm, sl)
reconnect()
local str, err, partial
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl)
remote (string.format ([[
data:settimeout(%d)
str = string.rep('a', %d)
@ -215,7 +222,7 @@ end
function test_totaltimeoutsend(len, tm, sl)
reconnect()
local str, err, total
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
printf("%d bytes, %ds total timeout, %ds pause: ", len, tm, sl)
remote (string.format ([[
data:settimeout(%d)
str = data:receive(%d)
@ -235,7 +242,7 @@ end
function test_blockingtimeoutreceive(len, tm, sl)
reconnect()
local str, err, partial
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl)
remote (string.format ([[
data:settimeout(%d)
str = string.rep('a', %d)
@ -255,7 +262,7 @@ end
function test_blockingtimeoutsend(len, tm, sl)
reconnect()
local str, err, total
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
printf("%d bytes, %ds blocking timeout, %ds pause: ", len, tm, sl)
remote (string.format ([[
data:settimeout(%d)
str = data:receive(%d)
@ -273,6 +280,7 @@ end
------------------------------------------------------------------------
function empty_connect()
printf("empty connect: ")
reconnect()
if data then data:close() data = nil end
remote [[
@ -284,7 +292,7 @@ function empty_connect()
pass("ok")
data = socket.connect(host, port)
else
pass("gethostbyname returns localhost on empty string...")
pass("gethostbyname returns localhost on empty string...")
end
end
@ -311,7 +319,7 @@ function test_closed()
local back, partial, err
local str = 'little string'
reconnect()
pass("trying read detection")
printf("trying read detection: ")
remote (string.format ([[
data:send('%s')
data:close()
@ -324,7 +332,7 @@ function test_closed()
elseif str ~= partial then fail("didn't receive partial result.")
else pass("graceful 'closed' received") end
reconnect()
pass("trying write detection")
printf("trying write detection: ")
remote [[
data:close()
data = nil
@ -342,7 +350,6 @@ end
------------------------------------------------------------------------
function test_selectbugs()
local r, s, e = socket.select(nil, nil, 0.1)
print(r, s, e)
assert(type(r) == "table" and type(s) == "table" and
(e == "timeout" or e == "error"))
pass("both nil: ok")
@ -374,7 +381,7 @@ end
------------------------------------------------------------------------
function accept_timeout()
io.stderr:write("accept with timeout (if it hangs, it failed): ")
printf("accept with timeout (if it hangs, it failed): ")
local s, e = socket.bind("*", 0, 0)
assert(s, e)
local t = socket.gettime()
@ -390,23 +397,22 @@ end
------------------------------------------------------------------------
function connect_timeout()
io.stderr:write("connect with timeout (if it hangs, it failed!): ")
printf("connect with timeout (if it hangs, it failed!): ")
local t = socket.gettime()
local c, e = socket.tcp()
assert(c, e)
c:settimeout(0.1)
local t = socket.gettime()
local r, e = c:connect("10.0.0.1", 81)
print(r, e)
assert(not r, "should not connect")
assert(socket.gettime() - t < 2, "took too long to give up.")
c:close()
print("ok")
pass("ok")
end
------------------------------------------------------------------------
function accept_errors()
io.stderr:write("not listening: ")
printf("not listening: ")
local d, e = socket.bind("*", 0)
assert(d, e);
local c, e = socket.tcp();
@ -415,26 +421,26 @@ function accept_errors()
d:settimeout(2)
local r, e = d:accept()
assert(not r and e)
print("ok: ", e)
io.stderr:write("not supported: ")
pass("ok")
printf("not supported: ")
local c, e = socket.udp()
assert(c, e);
d:setfd(c:getfd())
local r, e = d:accept()
assert(not r and e)
print("ok: ", e)
pass("ok")
end
------------------------------------------------------------------------
function connect_errors()
io.stderr:write("connection refused: ")
printf("connection refused: ")
local c, e = socket.connect("localhost", 1);
assert(not c and e)
print("ok: ", e)
io.stderr:write("host not found: ")
pass("ok")
printf("host not found: ")
local c, e = socket.connect("host.is.invalid", 1);
assert(not c and e, e)
print("ok: ", e)
pass("ok")
end
------------------------------------------------------------------------
@ -447,7 +453,7 @@ function rebind_test()
r, e = s:bind("localhost", p)
assert(not r, "managed to rebind!")
assert(e)
print("ok: ", e)
pass("ok")
end
------------------------------------------------------------------------
@ -469,14 +475,14 @@ function getstats_test()
assert(s == t, "sent count failed" .. tostring(s)
.. "/" .. tostring(t))
end
print("ok")
pass("ok")
end
------------------------------------------------------------------------
function test_nonblocking(size)
reconnect()
print("Testing " .. 2*size .. " bytes")
printf("testing " .. 2*size .. " bytes: ")
remote(string.format([[
data:send(string.rep("a", %d))
socket.sleep(0.5)
@ -508,7 +514,7 @@ remote(string.format([[
data:settimeout(-1)
local back = data:receive(2*size)
assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
print("ok")
pass("ok")
end
------------------------------------------------------------------------
@ -516,7 +522,7 @@ function test_readafterclose()
local back, partial, err
local str = 'little string'
reconnect()
pass("trying repeated '*a' pattern")
printf("trying repeated '*a' pattern")
remote (string.format ([[
data:send('%s')
data:close()
@ -526,9 +532,9 @@ function test_readafterclose()
assert(back == str, "unexpected data read")
back, err, partial = data:receive("*a")
assert(back == nil and err == "closed", "should have returned 'closed'")
print("ok")
pass("ok")
reconnect()
pass("trying active close before '*a'")
printf("trying active close before '*a'")
remote (string.format ([[
data:close()
data = nil
@ -536,9 +542,9 @@ function test_readafterclose()
data:close()
back, err, partial = data:receive("*a")
assert(back == nil and err == "closed", "should have returned 'closed'")
print("ok")
pass("ok")
reconnect()
pass("trying active close before '*l'")
printf("trying active close before '*l'")
remote (string.format ([[
data:close()
data = nil
@ -546,9 +552,9 @@ function test_readafterclose()
data:close()
back, err, partial = data:receive()
assert(back == nil and err == "closed", "should have returned 'closed'")
print("ok")
pass("ok")
reconnect()
pass("trying active close before raw 1")
printf("trying active close before raw 1")
remote (string.format ([[
data:close()
data = nil
@ -556,9 +562,9 @@ function test_readafterclose()
data:close()
back, err, partial = data:receive(1)
assert(back == nil and err == "closed", "should have returned 'closed'")
print("ok")
pass("ok")
reconnect()
pass("trying active close before raw 0")
printf("trying active close before raw 0")
remote (string.format ([[
data:close()
data = nil
@ -566,7 +572,7 @@ function test_readafterclose()
data:close()
back, err, partial = data:receive(0)
assert(back == nil and err == "closed", "should have returned 'closed'")
print("ok")
pass("ok")
end
------------------------------------------------------------------------
@ -581,13 +587,29 @@ function test_writeafterclose()
while not err do
sent, err, errsent, time = data:send(str)
end
print(sent, err, errsent, time)
print("ok")
assert(err == "closed", "should have returned 'closed'")
pass("ok")
end
------------------------------------------------------------------------
--test_writeafterclose()
function test_partialrecv()
local str = 'little string'
reconnect()
remote([[
data:send("7890")
]])
data:settimeout(1)
back, err = data:receive(10, "123456")
assert(back == "1234567890", "failed on exact mixed length")
back, err = data:receive(8, "87654321")
assert(back == "87654321", "failed on exact length")
back, err = data:receive(4, "87654321")
assert(back == "87654321", "failed on smaller length")
pass("ok")
end
------------------------------------------------------------------------
test("method registration")
test_methods(socket.tcp(), {
"accept",
@ -629,12 +651,18 @@ test_methods(socket.udp(), {
"settimeout"
})
test("partial receive")
test_partialrecv()
test("select function")
test_selectbugs()
test("testing read after close")
test("read after close")
test_readafterclose()
test("write after close")
test_writeafterclose()
test("connect function")
connect_timeout()
empty_connect()

View File

@ -1,13 +1,13 @@
function readfile(name)
local f = io.open(name, "rb")
if not f then return nil end
local s = f:read("*a")
f:close()
return s
local f = io.open(name, "rb")
if not f then return nil end
local s = f:read("*a")
f:close()
return s
end
function similar(s1, s2)
return string.lower(string.gsub(s1 or "", "%s", "")) ==
return string.lower(string.gsub(s1 or "", "%s", "")) ==
string.lower(string.gsub(s2 or "", "%s", ""))
end
@ -28,7 +28,7 @@ local set = rawset
local warn = print
local setglobal = function(table, key, value)
warn("changed " .. key)
warn("changed " .. key)
set(table, key, value)
end

View File

@ -3,439 +3,439 @@ socket.url = require("socket.url")
dofile("testsupport.lua")
local check_build_url = function(parsed)
local built = socket.url.build(parsed)
local built = socket.url.build(parsed)
if built ~= parsed.url then
print("built is different from expected")
print(built)
print(expected)
exit()
end
print("built is different from expected")
print(built)
print(expected)
exit()
end
end
local check_protect = function(parsed, path, unsafe)
local built = socket.url.build_path(parsed, unsafe)
if built ~= path then
print(built, path)
print("path composition failed.")
exit()
end
local built = socket.url.build_path(parsed, unsafe)
if built ~= path then
print(built, path)
print("path composition failed.")
exit()
end
end
local check_invert = function(url)
local parsed = socket.url.parse(url)
parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path))
local rebuilt = socket.url.build(parsed)
if rebuilt ~= url then
print(url, rebuilt)
print("original and rebuilt are different")
exit()
end
local parsed = socket.url.parse(url)
parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path))
local rebuilt = socket.url.build(parsed)
if rebuilt ~= url then
print(url, rebuilt)
print("original and rebuilt are different")
exit()
end
end
local check_parse_path = function(path, expect)
local parsed = socket.url.parse_path(path)
for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
if parsed[i] ~= expect[i] then
print(path)
local parsed = socket.url.parse_path(path)
for i = 1, math.max(table.getn(parsed), table.getn(expect)) do
if parsed[i] ~= expect[i] then
print(path)
exit()
end
end
if expect.is_directory ~= parsed.is_directory then
print(path)
print("is_directory mismatch")
exit()
end
if expect.is_absolute ~= parsed.is_absolute then
print(path)
print("is_absolute mismatch")
exit()
end
local built = socket.url.build_path(expect)
if built ~= path then
print(built, path)
print("path composition failed.")
exit()
end
end
end
if expect.is_directory ~= parsed.is_directory then
print(path)
print("is_directory mismatch")
exit()
end
if expect.is_absolute ~= parsed.is_absolute then
print(path)
print("is_absolute mismatch")
exit()
end
local built = socket.url.build_path(expect)
if built ~= path then
print(built, path)
print("path composition failed.")
exit()
end
end
local check_absolute_url = function(base, relative, absolute)
local res = socket.url.absolute(base, relative)
if res ~= absolute then
io.write("absolute: In test for '", relative, "' expected '",
local res = socket.url.absolute(base, relative)
if res ~= absolute then
io.write("absolute: In test for '", relative, "' expected '",
absolute, "' but got '", res, "'\n")
exit()
end
exit()
end
end
local check_parse_url = function(gaba)
local url = gaba.url
gaba.url = nil
local parsed = socket.url.parse(url)
for i, v in pairs(gaba) do
if v ~= parsed[i] then
io.write("parse: In test for '", url, "' expected ", i, " = '",
v, "' but got '", tostring(parsed[i]), "'\n")
for i,v in pairs(parsed) do print(i,v) end
exit()
end
end
for i, v in pairs(parsed) do
if v ~= gaba[i] then
io.write("parse: In test for '", url, "' expected ", i, " = '",
tostring(gaba[i]), "' but got '", v, "'\n")
for i,v in pairs(parsed) do print(i,v) end
exit()
end
end
local url = gaba.url
gaba.url = nil
local parsed = socket.url.parse(url)
for i, v in pairs(gaba) do
if v ~= parsed[i] then
io.write("parse: In test for '", url, "' expected ", i, " = '",
v, "' but got '", tostring(parsed[i]), "'\n")
for i,v in pairs(parsed) do print(i,v) end
exit()
end
end
for i, v in pairs(parsed) do
if v ~= gaba[i] then
io.write("parse: In test for '", url, "' expected ", i, " = '",
tostring(gaba[i]), "' but got '", v, "'\n")
for i,v in pairs(parsed) do print(i,v) end
exit()
end
end
end
print("testing URL parsing")
check_parse_url{
url = "scheme://userinfo@host:port/path;params?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://userinfo@host:port/path;params?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_parse_url{
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
authority = "user:password@host:port",
host = "host",
port = "port",
userinfo = "user:password",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment",
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
authority = "user:password@host:port",
host = "host",
port = "port",
userinfo = "user:password",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment",
}
check_parse_url{
url = "scheme://userinfo@host:port/path;params?query#",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = ""
url = "scheme://userinfo@host:port/path;params?query#",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = ""
}
check_parse_url{
url = "scheme://userinfo@host:port/path;params?#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "",
fragment = "fragment"
url = "scheme://userinfo@host:port/path;params?#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "",
fragment = "fragment"
}
check_parse_url{
url = "scheme://userinfo@host:port/path;params#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
fragment = "fragment"
url = "scheme://userinfo@host:port/path;params#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
fragment = "fragment"
}
check_parse_url{
url = "scheme://userinfo@host:port/path;?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "",
query = "query",
fragment = "fragment"
url = "scheme://userinfo@host:port/path;?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "",
query = "query",
fragment = "fragment"
}
check_parse_url{
url = "scheme://userinfo@host:port/path?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
query = "query",
fragment = "fragment"
url = "scheme://userinfo@host:port/path?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
query = "query",
fragment = "fragment"
}
check_parse_url{
url = "scheme://userinfo@host:port/;params?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://userinfo@host:port/;params?query#fragment",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/",
params = "params",
query = "query",
fragment = "fragment"
}
check_parse_url{
url = "scheme://userinfo@host:port",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
url = "scheme://userinfo@host:port",
scheme = "scheme",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
}
check_parse_url{
url = "//userinfo@host:port/path;params?query#fragment",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "//userinfo@host:port/path;params?query#fragment",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_parse_url{
url = "//userinfo@host:port/path",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
url = "//userinfo@host:port/path",
authority = "userinfo@host:port",
host = "host",
port = "port",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
}
check_parse_url{
url = "//userinfo@host/path",
authority = "userinfo@host",
host = "host",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
url = "//userinfo@host/path",
authority = "userinfo@host",
host = "host",
userinfo = "userinfo",
user = "userinfo",
path = "/path",
}
check_parse_url{
url = "//user:password@host/path",
authority = "user:password@host",
host = "host",
userinfo = "user:password",
password = "password",
user = "user",
path = "/path",
url = "//user:password@host/path",
authority = "user:password@host",
host = "host",
userinfo = "user:password",
password = "password",
user = "user",
path = "/path",
}
check_parse_url{
url = "//user:@host/path",
authority = "user:@host",
host = "host",
userinfo = "user:",
password = "",
user = "user",
path = "/path",
url = "//user:@host/path",
authority = "user:@host",
host = "host",
userinfo = "user:",
password = "",
user = "user",
path = "/path",
}
check_parse_url{
url = "//user@host:port/path",
authority = "user@host:port",
host = "host",
userinfo = "user",
user = "user",
port = "port",
path = "/path",
url = "//user@host:port/path",
authority = "user@host:port",
host = "host",
userinfo = "user",
user = "user",
port = "port",
path = "/path",
}
check_parse_url{
url = "//host:port/path",
authority = "host:port",
port = "port",
host = "host",
path = "/path",
url = "//host:port/path",
authority = "host:port",
port = "port",
host = "host",
path = "/path",
}
check_parse_url{
url = "//host/path",
authority = "host",
host = "host",
path = "/path",
url = "//host/path",
authority = "host",
host = "host",
path = "/path",
}
check_parse_url{
url = "//host",
authority = "host",
host = "host",
url = "//host",
authority = "host",
host = "host",
}
check_parse_url{
url = "/path",
path = "/path",
url = "/path",
path = "/path",
}
check_parse_url{
url = "path",
path = "path",
url = "path",
path = "path",
}
print("testing URL building")
check_build_url {
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://user:password@host/path;params?query#fragment",
scheme = "scheme",
host = "host",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://user:password@host/path;params?query#fragment",
scheme = "scheme",
host = "host",
user = "user",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://user@host/path;params?query#fragment",
scheme = "scheme",
host = "host",
user = "user",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://user@host/path;params?query#fragment",
scheme = "scheme",
host = "host",
user = "user",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://host/path;params?query#fragment",
scheme = "scheme",
host = "host",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
url = "scheme://host/path;params?query#fragment",
scheme = "scheme",
host = "host",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://host/path;params#fragment",
scheme = "scheme",
host = "host",
path = "/path",
params = "params",
fragment = "fragment"
url = "scheme://host/path;params#fragment",
scheme = "scheme",
host = "host",
path = "/path",
params = "params",
fragment = "fragment"
}
check_build_url {
url = "scheme://host/path#fragment",
scheme = "scheme",
host = "host",
path = "/path",
fragment = "fragment"
url = "scheme://host/path#fragment",
scheme = "scheme",
host = "host",
path = "/path",
fragment = "fragment"
}
check_build_url {
url = "scheme://host/path",
scheme = "scheme",
host = "host",
path = "/path",
url = "scheme://host/path",
scheme = "scheme",
host = "host",
path = "/path",
}
check_build_url {
url = "//host/path",
host = "host",
path = "/path",
url = "//host/path",
host = "host",
path = "/path",
}
check_build_url {
url = "/path",
path = "/path",
url = "/path",
path = "/path",
}
check_build_url {
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
userinfo = "not used",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
user = "user",
userinfo = "not used",
authority = "not used",
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
password = "password",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
host = "host",
port = "port",
userinfo = "user:password",
authority = "not used",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
check_build_url {
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
url = "scheme://user:password@host:port/path;params?query#fragment",
scheme = "scheme",
authority = "user:password@host:port",
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
path = "/path",
params = "params",
query = "query",
fragment = "fragment"
}
-- standard RFC tests
@ -488,11 +488,11 @@ print("testing path parsing and composition")
check_parse_path("/eu/tu/ele", { "eu", "tu", "ele"; is_absolute = 1 })
check_parse_path("/eu/", { "eu"; is_absolute = 1, is_directory = 1 })
check_parse_path("eu/tu/ele/nos/vos/eles/",
{ "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1})
{ "eu", "tu", "ele", "nos", "vos", "eles"; is_directory = 1})
check_parse_path("/", { is_absolute = 1, is_directory = 1})
check_parse_path("", { })
check_parse_path("eu%01/%02tu/e%03l%04e/nos/vos%05/e%12les/",
{ "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1})
{ "eu\1", "\2tu", "e\3l\4e", "nos", "vos\5", "e\18les"; is_directory = 1})
check_parse_path("eu/tu", { "eu", "tu" })
print("testing path protection")

View File

@ -298,7 +298,7 @@ function empty_connect()
pass("ok")
data = socket.connect(host, port)
else
pass("gethostbyname returns localhost on empty string...")
pass("gethostbyname returns localhost on empty string...")
end
end