mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 02:15:38 +01:00 
			
		
		
		
	Finish port to Lua 5. Everything is working fine.
Still doesn't work in Windows.
This commit is contained in:
		| @@ -1,13 +1,9 @@ | |||||||
| dofile("../lua/http.lua") | socket.http.TIMEOUT = 10 | ||||||
| HTTP.TIMEOUT = 10 |  | ||||||
| dofile("../lua/code.lua") |  | ||||||
| dofile("../lua/url.lua") |  | ||||||
| dofile("../lua/concat.lua") |  | ||||||
|  |  | ||||||
| cache = {} | cache = {} | ||||||
|  |  | ||||||
| function readfile(path) | function readfile(path) | ||||||
| 	path = Code.unescape(path) | 	path = socket.code.unescape(path) | ||||||
| 	local file, error = openfile(path, "r") | 	local file, error = openfile(path, "r") | ||||||
| 	if file then  | 	if file then  | ||||||
|         local body = read(file, "*a") |         local body = read(file, "*a") | ||||||
| @@ -17,7 +13,7 @@ function readfile(path) | |||||||
| end | end | ||||||
|  |  | ||||||
| function getstatus(url) | function getstatus(url) | ||||||
| 	local parsed = URL.parse_url(url, { scheme = "file" }) | 	local parsed = socket.url.parse(url, { scheme = "file" }) | ||||||
| 	if cache[url] then return cache[url].res end | 	if cache[url] then return cache[url].res end | ||||||
| 	local res | 	local res | ||||||
|     if parsed.scheme == "http" then |     if parsed.scheme == "http" then | ||||||
| @@ -25,10 +21,10 @@ function getstatus(url) | |||||||
|         local response = { body_cb = function(chunk, err)  |         local response = { body_cb = function(chunk, err)  | ||||||
|             return nil |             return nil | ||||||
|         end } |         end } | ||||||
| 		local blocksize = HTTP.BLOCKSIZE | 		local blocksize = socket.http.BLOCKSIZE | ||||||
| 		HTTP.BLOCKSIZE = 1 | 		socket.http.BLOCKSIZE = 1 | ||||||
|         response = HTTP.request_cb(request, response) |         response = socket.http.request_cb(request, response) | ||||||
|         HTTP.BLOCKSIZE = blocksize |         socket.http.BLOCKSIZE = blocksize | ||||||
|         if response.code == 200 then res = nil |         if response.code == 200 then res = nil | ||||||
|         else res = response.status or response.error end |         else res = response.status or response.error end | ||||||
|     elseif parsed.scheme == "file" then |     elseif parsed.scheme == "file" then | ||||||
| @@ -37,17 +33,17 @@ function getstatus(url) | |||||||
|              closefile(file) |              closefile(file) | ||||||
|              res = nil |              res = nil | ||||||
|         else res = error end |         else res = error end | ||||||
|     else res = format("unhandled scheme '%s'", parsed.scheme) end |     else res = string.format("unhandled scheme '%s'", parsed.scheme) end | ||||||
|     cache[url] = { res = res } |     cache[url] = { res = res } | ||||||
| 	return res | 	return res | ||||||
| end | end | ||||||
|  |  | ||||||
| function retrieve(url) | function retrieve(url) | ||||||
| 	local parsed = URL.parse_url(url, { scheme = "file" }) | 	local parsed = socket.url.parse(url, { scheme = "file" }) | ||||||
|     local base, body, error |     local base, body, error | ||||||
|     base = url |     base = url | ||||||
| 	if parsed.scheme == "http" then  | 	if parsed.scheme == "http" then  | ||||||
|         local response = HTTP.request{url = url} |         local response = socket.http.request{url = url} | ||||||
|         if response.code ~= 200 then  |         if response.code ~= 200 then  | ||||||
|             error = response.status or response.error |             error = response.status or response.error | ||||||
|         else |         else | ||||||
| @@ -56,23 +52,23 @@ function retrieve(url) | |||||||
|         end |         end | ||||||
|     elseif parsed.scheme == "file" then  |     elseif parsed.scheme == "file" then  | ||||||
|         body, error = readfile(parsed.path)  |         body, error = readfile(parsed.path)  | ||||||
|     else error = format("unhandled scheme '%s'", parsed.scheme) end |     else error = string.format("unhandled scheme '%s'", parsed.scheme) end | ||||||
|     return base, body, error |     return base, body, error | ||||||
| end | end | ||||||
|  |  | ||||||
| function getlinks(body, base) | function getlinks(body, base) | ||||||
|     -- get rid of comments |     -- get rid of comments | ||||||
|     body = gsub(body, "%<%!%-%-.-%-%-%>", "") |     body = string.gsub(body, "%<%!%-%-.-%-%-%>", "") | ||||||
|     local links = {} |     local links = {} | ||||||
|     -- extract links |     -- extract links | ||||||
| 	gsub(body, '[Hh][Rr][Ee][Ff]%s*=%s*"([^"]*)"', function(href) | 	string.gsub(body, '[Hh][Rr][Ee][Ff]%s*=%s*"([^"]*)"', function(href) | ||||||
|         tinsert(%links, URL.absolute_url(%base, href)) |         table.insert(links, socket.url.absolute(base, href)) | ||||||
|     end) |     end) | ||||||
| 	gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*'([^']*)'", function(href) | 	string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*'([^']*)'", function(href) | ||||||
|         tinsert(%links, URL.absolute_url(%base, href)) |         table.insert(links, socket.url.absolute(base, href)) | ||||||
|     end) |     end) | ||||||
| 	gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*(%a+)", function(href) | 	string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*(%a+)", function(href) | ||||||
|         tinsert(%links, URL.absolute_url(%base, href)) |         table.insert(links, socket.url.absolute(base, href)) | ||||||
|     end) |     end) | ||||||
|     return links |     return links | ||||||
| end | end | ||||||
| @@ -81,19 +77,19 @@ function checklinks(url) | |||||||
| 	local base, body, error = retrieve(url) | 	local base, body, error = retrieve(url) | ||||||
|     if not body then print(error) return end |     if not body then print(error) return end | ||||||
|     local links = getlinks(body, base) |     local links = getlinks(body, base) | ||||||
|     for i = 1, getn(links) do |     for _, l in ipairs(links) do | ||||||
| 		write(_STDERR, "\t", links[i], "\n") | 		io.stderr:write("\t", l, "\n") | ||||||
| 		local err = getstatus(links[i]) | 		local err = getstatus(l) | ||||||
| 		if err then write('\t', links[i], ": ", err, "\n") end | 		if err then io.stderr:write('\t', l, ": ", err, "\n") end | ||||||
|     end |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| arg = arg or {} | arg = arg or {} | ||||||
| if getn(arg) < 1 then | if table.getn(arg) < 1 then | ||||||
| 	write("Usage:\n  luasocket -f check-links.lua {<url>}\n") | 	print("Usage:\n  luasocket check-links.lua {<url>}") | ||||||
| 	exit() | 	exit() | ||||||
| end | end | ||||||
| for i = 1, getn(arg) do | for _, a in ipairs(arg) do | ||||||
| 	write("Checking ", arg[i], "\n") | 	print("Checking ", a) | ||||||
| 	checklinks(URL.absolute_url("file:", arg[i])) | 	checklinks(socket.url.absolute("file:", a)) | ||||||
| end | end | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								etc/get.lua
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								etc/get.lua
									
									
									
									
									
								
							| @@ -13,8 +13,8 @@ function nicetime(s) | |||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	if l == "s" then return format("%2.0f%s", s, l) | 	if l == "s" then return string.format("%2.0f%s", s, l) | ||||||
| 	else return format("%5.2f%s", s, l) end | 	else return string.format("%5.2f%s", s, l) end | ||||||
| end | end | ||||||
|  |  | ||||||
| -- formats a number of bytes into human readable form | -- formats a number of bytes into human readable form | ||||||
| @@ -32,21 +32,21 @@ function nicesize(b) | |||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	return format("%7.2f%2s", b, l) | 	return string.format("%7.2f%2s", b, l) | ||||||
| end | end | ||||||
|  |  | ||||||
| -- returns a string with the current state of the download | -- returns a string with the current state of the download | ||||||
| function gauge(got, dt, size) | function gauge(got, dt, size) | ||||||
| 	local rate = got / dt | 	local rate = got / dt | ||||||
| 	if size and size >= 1 then | 	if size and size >= 1 then | ||||||
| 		return format("%s received, %s/s throughput, " .. | 		return string.format("%s received, %s/s throughput, " .. | ||||||
| 			"%.0f%% done, %s remaining",  | 			"%.0f%% done, %s remaining",  | ||||||
|             nicesize(got),   |             nicesize(got),   | ||||||
| 			nicesize(rate),  | 			nicesize(rate),  | ||||||
| 			100*got/size,  | 			100*got/size,  | ||||||
| 			nicetime((size-got)/rate)) | 			nicetime((size-got)/rate)) | ||||||
| 	else  | 	else  | ||||||
| 		return format("%s received, %s/s throughput, %s elapsed",  | 		return string.format("%s received, %s/s throughput, %s elapsed",  | ||||||
| 			nicesize(got),  | 			nicesize(got),  | ||||||
| 			nicesize(rate), | 			nicesize(rate), | ||||||
| 			nicetime(dt)) | 			nicetime(dt)) | ||||||
| @@ -57,22 +57,22 @@ end | |||||||
| -- kind of copied from luasocket's manual callback examples | -- kind of copied from luasocket's manual callback examples | ||||||
| function receive2disk(file, size) | function receive2disk(file, size) | ||||||
| 	local aux = { | 	local aux = { | ||||||
|         start = _time(), |         start = socket._time(), | ||||||
|         got = 0, |         got = 0, | ||||||
|         file = openfile(file, "wb"), |         file = io.open(file, "wb"), | ||||||
| 		size = size | 		size = size | ||||||
|     } |     } | ||||||
|     local receive_cb = function(chunk, err) |     local receive_cb = function(chunk, err) | ||||||
|         local dt = _time() - %aux.start          -- elapsed time since start |         local dt = socket._time() - %aux.start          -- elapsed time since start | ||||||
|         if not chunk or chunk == "" then |         if not chunk or chunk == "" then | ||||||
| 			write("\n") | 			io.write("\n") | ||||||
|             closefile(%aux.file) |             aux.file:close() | ||||||
|             return |             return | ||||||
|         end |         end | ||||||
|         write(%aux.file, chunk) |         aux.file:write(chunk) | ||||||
|         %aux.got = %aux.got + strlen(chunk)      -- total bytes received |         aux.got = aux.got + string.len(chunk)      -- total bytes received | ||||||
|         if dt < 0.1 then return 1 end            -- not enough time for estimate |         if dt < 0.1 then return 1 end            -- not enough time for estimate | ||||||
| 		write("\r", gauge(%aux.got, dt, %aux.size)) | 		io.write("\r", gauge(aux.got, dt, aux.size)) | ||||||
|         return 1 |         return 1 | ||||||
|     end |     end | ||||||
| 	return receive_cb | 	return receive_cb | ||||||
| @@ -80,7 +80,7 @@ end | |||||||
|  |  | ||||||
| -- downloads a file using the ftp protocol | -- downloads a file using the ftp protocol | ||||||
| function getbyftp(url, file) | function getbyftp(url, file) | ||||||
|     local err = FTP.get_cb { |     local err = socket.ftp.get_cb { | ||||||
|         url = url, |         url = url, | ||||||
|         content_cb = receive2disk(file), |         content_cb = receive2disk(file), | ||||||
|         type = "i" |         type = "i" | ||||||
| @@ -91,7 +91,7 @@ end | |||||||
|  |  | ||||||
| -- downloads a file using the http protocol | -- downloads a file using the http protocol | ||||||
| function getbyhttp(url, file, size) | function getbyhttp(url, file, size) | ||||||
|     local response = HTTP.request_cb( |     local response = socket.http.request_cb( | ||||||
|         {url = url}, |         {url = url}, | ||||||
| 		{body_cb = receive2disk(file, size)}  | 		{body_cb = receive2disk(file, size)}  | ||||||
|     ) |     ) | ||||||
| @@ -101,7 +101,7 @@ end | |||||||
|  |  | ||||||
| -- determines the size of a http file | -- determines the size of a http file | ||||||
| function gethttpsize(url) | function gethttpsize(url) | ||||||
| 	local response = HTTP.request { | 	local response = socket.http.request { | ||||||
| 		method = "HEAD", | 		method = "HEAD", | ||||||
|  		url = url |  		url = url | ||||||
| 	} | 	} | ||||||
| @@ -113,11 +113,11 @@ end | |||||||
| -- determines the scheme and the file name of a given url | -- determines the scheme and the file name of a given url | ||||||
| function getschemeandname(url, name) | function getschemeandname(url, name) | ||||||
| 	-- this is an heuristic to solve a common invalid url poblem | 	-- this is an heuristic to solve a common invalid url poblem | ||||||
| 	if not strfind(url, "//") then url = "//" .. url end | 	if not string.find(url, "//") then url = "//" .. url end | ||||||
| 	local parsed = URL.parse_url(url, {scheme = "http"}) | 	local parsed = socket.url.parse(url, {scheme = "http"}) | ||||||
| 	if name then return parsed.scheme, name end | 	if name then return parsed.scheme, name end | ||||||
| 	local segment = URL.parse_path(parsed.path) | 	local segment = socket.url.parse_path(parsed.path) | ||||||
| 	name = segment[getn(segment)] | 	name = segment[table.getn(segment)] | ||||||
| 	if segment.is_directory then name = nil end | 	if segment.is_directory then name = nil end | ||||||
| 	return parsed.scheme, name | 	return parsed.scheme, name | ||||||
| end | end | ||||||
| @@ -134,7 +134,7 @@ end | |||||||
|  |  | ||||||
| -- main program | -- main program | ||||||
| arg = arg or {} | arg = arg or {} | ||||||
| if getn(arg) < 1 then  | if table.getn(arg) < 1 then  | ||||||
| 	write("Usage:\n  luasocket -f get.lua <remote-url> [<local-file>]\n") | 	io.write("Usage:\n  luasocket get.lua <remote-url> [<local-file>]\n") | ||||||
| 	exit(1) | 	os.exit(1) | ||||||
| else get(arg[1], arg[2]) end | else get(arg[1], arg[2]) end | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								src/ftp.lua
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								src/ftp.lua
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| local Public, Private = {}, {} | local Public, Private = {}, {} | ||||||
| FTP = Public | socket.ftp = Public | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| -- Program constants | -- Program constants | ||||||
| @@ -47,7 +47,7 @@ end | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.try_receive(...) | function Private.try_receive(...) | ||||||
|     local sock = arg[1] |     local sock = arg[1] | ||||||
|     local data, err = call(sock.receive, arg) |     local data, err = sock.receive(unpack(arg)) | ||||||
|     if err then sock:close() end |     if err then sock:close() end | ||||||
|     return data, err |     return data, err | ||||||
| end | end | ||||||
| @@ -64,9 +64,9 @@ function Private.get_pasv(pasv) | |||||||
| 	local a, b, c, d, p1, p2, _ | 	local a, b, c, d, p1, p2, _ | ||||||
| 	local ip, port | 	local ip, port | ||||||
| 	_,_, a, b, c, d, p1, p2 = | 	_,_, a, b, c, d, p1, p2 = | ||||||
| 		strfind(pasv, "(%d*),(%d*),(%d*),(%d*),(%d*),(%d*)") | 		string.find(pasv, "(%d*),(%d*),(%d*),(%d*),(%d*),(%d*)") | ||||||
| 	if not (a and b and c and d and p1 and p2) then return nil, nil end | 	if not (a and b and c and d and p1 and p2) then return nil, nil end | ||||||
| 	ip = format("%d.%d.%d.%d", a, b, c, d) | 	ip = string.format("%d.%d.%d.%d", a, b, c, d) | ||||||
| 	port = tonumber(p1)*256 + tonumber(p2) | 	port = tonumber(p1)*256 + tonumber(p2) | ||||||
| 	return ip, port | 	return ip, port | ||||||
| end | end | ||||||
| @@ -100,13 +100,13 @@ function Private.get_answer(control) | |||||||
| 	local line, err = Private.try_receive(control) | 	local line, err = Private.try_receive(control) | ||||||
| 	local answer = line | 	local answer = line | ||||||
| 	if err then return nil, err end | 	if err then return nil, err end | ||||||
| 	_,_, code, sep = strfind(line, "^(%d%d%d)(.)") | 	_,_, code, sep = string.find(line, "^(%d%d%d)(.)") | ||||||
| 	if not code or not sep then return nil, answer end | 	if not code or not sep then return nil, answer end | ||||||
| 	if sep == "-" then -- answer is multiline | 	if sep == "-" then -- answer is multiline | ||||||
| 		repeat  | 		repeat  | ||||||
| 			line, err = Private.try_receive(control) | 			line, err = Private.try_receive(control) | ||||||
| 			if err then return nil, err end | 			if err then return nil, err end | ||||||
| 			_,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)") | 			_,_, lastcode, sep = string.find(line, "^(%d%d%d)(.)") | ||||||
| 			answer = answer .. "\n" .. line | 			answer = answer .. "\n" .. line | ||||||
| 		until code == lastcode and sep == " " -- answer ends with same code | 		until code == lastcode and sep == " " -- answer ends with same code | ||||||
| 	end | 	end | ||||||
| @@ -126,8 +126,8 @@ function Private.check_answer(control, success) | |||||||
| 	local answer, code = Private.get_answer(control) | 	local answer, code = Private.get_answer(control) | ||||||
| 	if not answer then return nil, code end | 	if not answer then return nil, code end | ||||||
| 	if type(success) ~= "table" then success = {success} end | 	if type(success) ~= "table" then success = {success} end | ||||||
| 	for i = 1, getn(success) do | 	for _, s in ipairs(success) do | ||||||
| 		if code == success[i] then | 		if code == s then | ||||||
| 			return code, answer | 			return code, answer | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| @@ -213,13 +213,13 @@ function Private.port(control) | |||||||
| 	local code, answer | 	local code, answer | ||||||
| 	local server, ctl_ip | 	local server, ctl_ip | ||||||
| 	ctl_ip, answer = control:getsockname() | 	ctl_ip, answer = control:getsockname() | ||||||
| 	server, answer = bind(ctl_ip, 0) | 	server, answer = socket.bind(ctl_ip, 0) | ||||||
| 	server:timeout(Public.TIMEOUT) | 	server:timeout(Public.TIMEOUT) | ||||||
| 	local ip, p, ph, pl | 	local ip, p, ph, pl | ||||||
| 	ip, p = server:getsockname() | 	ip, p = server:getsockname() | ||||||
| 	pl = mod(p, 256) | 	pl = math.mod(p, 256) | ||||||
| 	ph = (p - pl)/256 | 	ph = (p - pl)/256 | ||||||
|     local arg = gsub(format("%s,%d,%d", ip, ph, pl), "%.", ",") |     local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",") | ||||||
| 	code, answer = Private.command(control, "port", arg, {200}) | 	code, answer = Private.command(control, "port", arg, {200}) | ||||||
| 	if not code then  | 	if not code then  | ||||||
| 		server:close() | 		server:close() | ||||||
| @@ -321,7 +321,7 @@ function Private.send_indirect(data, send_cb, chunk, size) | |||||||
|             data:close() |             data:close() | ||||||
|             return err |             return err | ||||||
|         end |         end | ||||||
|         sent = sent + strlen(chunk) |         sent = sent + string.len(chunk) | ||||||
|         if sent >= size then break end |         if sent >= size then break end | ||||||
|         chunk, size = send_cb() |         chunk, size = send_cb() | ||||||
|     end |     end | ||||||
| @@ -374,7 +374,7 @@ end | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.change_type(control, params) | function Private.change_type(control, params) | ||||||
| 	local type, _ | 	local type, _ | ||||||
| 	_, _, type = strfind(params or "", "type=(.)") | 	_, _, type = string.find(params or "", "type=(.)") | ||||||
| 	if type == "a" or type == "i" then  | 	if type == "a" or type == "i" then  | ||||||
| 		local code, err = Private.command(control, "type", type, {200}) | 		local code, err = Private.command(control, "type", type, {200}) | ||||||
| 		if not code then return err end | 		if not code then return err end | ||||||
| @@ -391,7 +391,7 @@ end | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.open(parsed) | function Private.open(parsed) | ||||||
| 	-- start control connection | 	-- start control connection | ||||||
| 	local control, err = connect(parsed.host, parsed.port) | 	local control, err = socket.connect(parsed.host, parsed.port) | ||||||
| 	if not control then return nil, err end | 	if not control then return nil, err end | ||||||
| 	-- make sure we don't block forever | 	-- make sure we don't block forever | ||||||
| 	control:timeout(Public.TIMEOUT) | 	control:timeout(Public.TIMEOUT) | ||||||
| @@ -423,7 +423,7 @@ end | |||||||
| --   err: error message if any | --   err: error message if any | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.change_dir(control, segment) | function Private.change_dir(control, segment) | ||||||
| 	local n = getn(segment) |     local n = table.getn(segment) | ||||||
| 	for i = 1, n-1 do | 	for i = 1, n-1 do | ||||||
| 		local code, answer = Private.cwd(control, segment[i]) | 		local code, answer = Private.cwd(control, segment[i]) | ||||||
| 		if not code then return answer end | 		if not code then return answer end | ||||||
| @@ -443,7 +443,7 @@ end | |||||||
| function Private.upload(control, request, segment) | function Private.upload(control, request, segment) | ||||||
| 	local code, name, content_cb | 	local code, name, content_cb | ||||||
| 	-- get remote file name | 	-- get remote file name | ||||||
| 	name = segment[getn(segment)] | 	name = segment[table.getn(segment)] | ||||||
| 	if not name then  | 	if not name then  | ||||||
| 		control:close() | 		control:close() | ||||||
| 		return "Invalid file path"  | 		return "Invalid file path"  | ||||||
| @@ -472,7 +472,7 @@ function Private.download(control, request, segment) | |||||||
| 	is_directory = segment.is_directory | 	is_directory = segment.is_directory | ||||||
| 	content_cb = request.content_cb | 	content_cb = request.content_cb | ||||||
| 	-- get remote file name | 	-- get remote file name | ||||||
| 	name = segment[getn(segment)] | 	name = segment[table.getn(segment)] | ||||||
| 	if not name and not is_directory then  | 	if not name and not is_directory then  | ||||||
| 		control:close() | 		control:close() | ||||||
| 		return "Invalid file path"  | 		return "Invalid file path"  | ||||||
| @@ -498,7 +498,7 @@ end | |||||||
| --   parsed: a table with parsed components | --   parsed: a table with parsed components | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.parse_url(request) | function Private.parse_url(request) | ||||||
| 	local parsed = URL.parse_url(request.url, { | 	local parsed = socket.url.parse(request.url, { | ||||||
| 		host = "", | 		host = "", | ||||||
| 		user = "anonymous",  | 		user = "anonymous",  | ||||||
| 		port = 21,  | 		port = 21,  | ||||||
| @@ -521,9 +521,10 @@ end | |||||||
| -- Returns | -- Returns | ||||||
| --   dirs: a table with parsed directory components | --   dirs: a table with parsed directory components | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.parse_path(parsed) | function Private.parse_path(parsed_url) | ||||||
| 	local segment = URL.parse_path(parsed.path) | 	local segment = socket.url.parse_path(parsed_url.path) | ||||||
| 	segment.is_directory = segment.is_directory or (parsed.params == "type=d") | 	segment.is_directory = segment.is_directory or  | ||||||
|  |         (parsed_url.params == "type=d") | ||||||
| 	return segment | 	return segment | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -560,7 +561,7 @@ end | |||||||
| function Public.get_cb(request) | function Public.get_cb(request) | ||||||
| 	local parsed = Private.parse_url(request) | 	local parsed = Private.parse_url(request) | ||||||
| 	if parsed.scheme ~= "ftp" then  | 	if parsed.scheme ~= "ftp" then  | ||||||
| 		return format("unknown scheme '%s'", parsed.scheme) | 		return string.format("unknown scheme '%s'", parsed.scheme) | ||||||
| 	end | 	end | ||||||
| 	local control, err = Private.open(parsed) | 	local control, err = Private.open(parsed) | ||||||
| 	if not control then return err end | 	if not control then return err end | ||||||
| @@ -586,7 +587,7 @@ end | |||||||
| function Public.put_cb(request) | function Public.put_cb(request) | ||||||
| 	local parsed = Private.parse_url(request) | 	local parsed = Private.parse_url(request) | ||||||
| 	if parsed.scheme ~= "ftp" then  | 	if parsed.scheme ~= "ftp" then  | ||||||
| 		return format("unknown scheme '%s'", parsed.scheme) | 		return string.format("unknown scheme '%s'", parsed.scheme) | ||||||
| 	end | 	end | ||||||
| 	local control, err = Private.open(parsed) | 	local control, err = Private.open(parsed) | ||||||
| 	if not control then return err end | 	if not control then return err end | ||||||
| @@ -612,7 +613,7 @@ end | |||||||
| function Public.put(url_or_request, content) | function Public.put(url_or_request, content) | ||||||
| 	local request = Private.build_request(url_or_request) | 	local request = Private.build_request(url_or_request) | ||||||
| 	request.content_cb = function() | 	request.content_cb = function() | ||||||
| 		return content, strlen(content) | 		return content, string.len(content) | ||||||
| 	end | 	end | ||||||
| 	return Public.put_cb(request) | 	return Public.put_cb(request) | ||||||
| end | end | ||||||
| @@ -630,7 +631,7 @@ end | |||||||
| --   err: error message in case of error, nil otherwise | --   err: error message in case of error, nil otherwise | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Public.get(url_or_request) | function Public.get(url_or_request) | ||||||
| 	local cat = Concat.create() | 	local cat = socket.concat.create() | ||||||
| 	local request = Private.build_request(url_or_request) | 	local request = Private.build_request(url_or_request) | ||||||
| 	request.content_cb = function(chunk, err) | 	request.content_cb = function(chunk, err) | ||||||
| 		if chunk then cat:addstring(chunk) end | 		if chunk then cat:addstring(chunk) end | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/http.lua
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/http.lua
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| local Public, Private = {}, {} | local Public, Private = {}, {} | ||||||
| http = Public | socket.http = Public | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| -- Program constants | -- Program constants | ||||||
| @@ -427,7 +427,7 @@ end | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.authorize(request, parsed, response) | function Private.authorize(request, parsed, response) | ||||||
|     request.headers["authorization"] = "Basic " ..  |     request.headers["authorization"] = "Basic " ..  | ||||||
|         Code.base64(parsed.user .. ":" .. parsed.password) |         socket.code.base64(parsed.user .. ":" .. parsed.password) | ||||||
|     local authorize = { |     local authorize = { | ||||||
|         redirects = request.redirects, |         redirects = request.redirects, | ||||||
|         method = request.method, |         method = request.method, | ||||||
| @@ -471,7 +471,7 @@ function Private.redirect(request, response) | |||||||
|         method = request.method, |         method = request.method, | ||||||
|         -- the RFC says the redirect URL has to be absolute, but some |         -- the RFC says the redirect URL has to be absolute, but some | ||||||
|         -- servers do not respect that  |         -- servers do not respect that  | ||||||
|         url = URL.absolute_url(request.url, response.headers["location"]), |         url = socket.url.absolute(request.url, response.headers["location"]), | ||||||
|         body_cb = request.body_cb, |         body_cb = request.body_cb, | ||||||
|         headers = request.headers |         headers = request.headers | ||||||
|     } |     } | ||||||
| @@ -535,7 +535,7 @@ end | |||||||
| --     error: error message, or nil if successfull | --     error: error message, or nil if successfull | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Public.request_cb(request, response) | function Public.request_cb(request, response) | ||||||
|     local parsed = URL.parse_url(request.url, { |     local parsed = socket.url.parse(request.url, { | ||||||
|         host = "", |         host = "", | ||||||
|         port = Public.PORT,  |         port = Public.PORT,  | ||||||
|         path ="/", |         path ="/", | ||||||
| @@ -622,7 +622,7 @@ function Public.request(request) | |||||||
|             return request.body, string.len(request.body)  |             return request.body, string.len(request.body)  | ||||||
|         end |         end | ||||||
|     end |     end | ||||||
|     local cat = Concat.create() |     local cat = socket.concat.create() | ||||||
|     response.body_cb = function(chunk, err) |     response.body_cb = function(chunk, err) | ||||||
|         if chunk then cat:addstring(chunk) end |         if chunk then cat:addstring(chunk) end | ||||||
|         return 1 |         return 1 | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								src/mbox.lua
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/mbox.lua
									
									
									
									
									
								
							| @@ -4,11 +4,11 @@ mbox = Public | |||||||
|  |  | ||||||
| function Public.split_message(message_s) | function Public.split_message(message_s) | ||||||
|     local message = {} |     local message = {} | ||||||
|     message_s = gsub(message_s, "\r\n", "\n") |     message_s = string.gsub(message_s, "\r\n", "\n") | ||||||
| 	gsub(message_s, "^(.-\n)\n", function (h) %message.headers = h end) | 	string.gsub(message_s, "^(.-\n)\n", function (h) %message.headers = h end) | ||||||
| 	gsub(message_s, "^.-\n\n(.*)", function (b) %message.body = b end) | 	string.gsub(message_s, "^.-\n\n(.*)", function (b) %message.body = b end) | ||||||
|     if not message.body then |     if not message.body then | ||||||
| 	    gsub(message_s, "^\n(.*)", function (b) %message.body = b end) | 	    string.gsub(message_s, "^\n(.*)", function (b) %message.body = b end) | ||||||
|     end |     end | ||||||
|     if not message.headers and not message.body then  |     if not message.headers and not message.body then  | ||||||
|         message.headers = message_s |         message.headers = message_s | ||||||
| @@ -18,26 +18,26 @@ end | |||||||
|  |  | ||||||
| function Public.split_headers(headers_s) | function Public.split_headers(headers_s) | ||||||
|     local headers = {} |     local headers = {} | ||||||
|     headers_s = gsub(headers_s, "\r\n", "\n") |     headers_s = string.gsub(headers_s, "\r\n", "\n") | ||||||
|     headers_s = gsub(headers_s, "\n[ ]+", " ") |     headers_s = string.gsub(headers_s, "\n[ ]+", " ") | ||||||
|     gsub("\n" .. headers_s, "\n([^\n]+)", function (h) tinsert(%headers, h) end) |     string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(%headers, h) end) | ||||||
|     return headers |     return headers | ||||||
| end | end | ||||||
|  |  | ||||||
| function Public.parse_header(header_s) | function Public.parse_header(header_s) | ||||||
|     header_s = gsub(header_s, "\n[ ]+", " ") |     header_s = string.gsub(header_s, "\n[ ]+", " ") | ||||||
|     header_s = gsub(header_s, "\n+", "") |     header_s = string.gsub(header_s, "\n+", "") | ||||||
|     local _, __, name, value = strfind(header_s, "([^%s:]-):%s*(.*)") |     local _, __, name, value = string.find(header_s, "([^%s:]-):%s*(.*)") | ||||||
|     return name, value |     return name, value | ||||||
| end | end | ||||||
|  |  | ||||||
| function Public.parse_headers(headers_s) | function Public.parse_headers(headers_s) | ||||||
|     local headers_t = %Public.split_headers(headers_s) |     local headers_t = %Public.split_headers(headers_s) | ||||||
|     local headers = {} |     local headers = {} | ||||||
|     for i = 1, getn(headers_t) do |     for i = 1, table.getn(headers_t) do | ||||||
|         local name, value = %Public.parse_header(headers_t[i]) |         local name, value = %Public.parse_header(headers_t[i]) | ||||||
|         if name then |         if name then | ||||||
|             name = strlower(name) |             name = string.lower(name) | ||||||
|             if headers[name] then |             if headers[name] then | ||||||
|                 headers[name] = headers[name] .. ", " .. value |                 headers[name] = headers[name] .. ", " .. value | ||||||
|             else headers[name] = value end |             else headers[name] = value end | ||||||
| @@ -47,34 +47,34 @@ function Public.parse_headers(headers_s) | |||||||
| end | end | ||||||
|  |  | ||||||
| function Public.parse_from(from) | function Public.parse_from(from) | ||||||
|     local _, __, name, address = strfind(from, "^%s*(.-)%s*%<(.-)%>") |     local _, __, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>") | ||||||
|     if not address then |     if not address then | ||||||
|         _, __, address = strfind(from, "%s*(.+)%s*") |         _, __, address = string.find(from, "%s*(.+)%s*") | ||||||
|     end |     end | ||||||
|     name = name or "" |     name = name or "" | ||||||
|     address = address or "" |     address = address or "" | ||||||
|     if name == "" then name = address end |     if name == "" then name = address end | ||||||
| 	name = gsub(name, '"', "") | 	name = string.gsub(name, '"', "") | ||||||
|     return name, address |     return name, address | ||||||
| end | end | ||||||
|  |  | ||||||
| function Public.split_mbox(mbox_s) | function Public.split_mbox(mbox_s) | ||||||
| 	mbox = {} | 	mbox = {} | ||||||
| 	mbox_s = gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" | 	mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n" | ||||||
| 	local nj, i, j = 1, 1, 1 | 	local nj, i, j = 1, 1, 1 | ||||||
| 	while 1 do | 	while 1 do | ||||||
| 		i, nj = strfind(mbox_s, "\n\nFrom .-\n", j) | 		i, nj = string.find(mbox_s, "\n\nFrom .-\n", j) | ||||||
| 		if not i then break end | 		if not i then break end | ||||||
| 		local message = strsub(mbox_s, j, i-1) | 		local message = string.sub(mbox_s, j, i-1) | ||||||
| 		tinsert(mbox, message) | 		table.insert(mbox, message) | ||||||
| 		j = nj+1 | 		j = nj+1 | ||||||
| 	end | 	end | ||||||
| 	return mbox | 	return mbox | ||||||
| end | end | ||||||
|  |  | ||||||
| function Public.parse_mbox(mbox_s) | function Public.parse(mbox_s) | ||||||
| 	local mbox = %Public.split_mbox(mbox_s) | 	local mbox = %Public.split_mbox(mbox_s) | ||||||
| 	for i = 1, getn(mbox) do | 	for i = 1, table.getn(mbox) do | ||||||
| 		mbox[i] = %Public.parse_message(mbox[i]) | 		mbox[i] = %Public.parse_message(mbox[i]) | ||||||
| 	end | 	end | ||||||
| 	return mbox | 	return mbox | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								src/smtp.lua
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/smtp.lua
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| local Public, Private = {}, {} | local Public, Private = {}, {} | ||||||
| SMTP = Public | socket.smtp = Public | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| -- Program constants | -- Program constants | ||||||
| @@ -47,7 +47,7 @@ end | |||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.try_receive(...) | function Private.try_receive(...) | ||||||
|     local sock = arg[1] |     local sock = arg[1] | ||||||
|     local data, err = call(sock.receive, arg) |     local data, err = sock.receive(unpack(arg)) | ||||||
|     if err then sock:close() end |     if err then sock:close() end | ||||||
|     return data, err |     return data, err | ||||||
| end | end | ||||||
| @@ -81,13 +81,13 @@ function Private.get_answer(control) | |||||||
|     local line, err = Private.try_receive(control) |     local line, err = Private.try_receive(control) | ||||||
|     local answer = line |     local answer = line | ||||||
|     if err then return nil, err end |     if err then return nil, err end | ||||||
|     _,_, code, sep = strfind(line, "^(%d%d%d)(.)") |     _,_, code, sep = string.find(line, "^(%d%d%d)(.)") | ||||||
|     if not code or not sep then return nil, answer end |     if not code or not sep then return nil, answer end | ||||||
|     if sep == "-" then -- answer is multiline |     if sep == "-" then -- answer is multiline | ||||||
|         repeat  |         repeat  | ||||||
|             line, err = Private.try_receive(control) |             line, err = Private.try_receive(control) | ||||||
|             if err then return nil, err end |             if err then return nil, err end | ||||||
|             _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)") |             _,_, lastcode, sep = string.find(line, "^(%d%d%d)(.)") | ||||||
|             answer = answer .. "\n" .. line |             answer = answer .. "\n" .. line | ||||||
|         until code == lastcode and sep == " " -- answer ends with same code |         until code == lastcode and sep == " " -- answer ends with same code | ||||||
|     end |     end | ||||||
| @@ -108,7 +108,7 @@ function Private.check_answer(control, success) | |||||||
|     local answer, code = Private.get_answer(control) |     local answer, code = Private.get_answer(control) | ||||||
|     if not answer then return nil, code end |     if not answer then return nil, code end | ||||||
|     if type(success) ~= "table" then success = {success} end |     if type(success) ~= "table" then success = {success} end | ||||||
|     for i = 1, getn(success) do |     for i = 1, table.getn(success) do | ||||||
|         if code == success[i] then |         if code == success[i] then | ||||||
|             return code, answer |             return code, answer | ||||||
|         end |         end | ||||||
| @@ -157,7 +157,7 @@ end | |||||||
| --   answer: complete server reply or error message | --   answer: complete server reply or error message | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Private.send_mail(sock, sender) | function Private.send_mail(sock, sender) | ||||||
|     local param = format("FROM:<%s>", sender or "") |     local param = string.format("FROM:<%s>", sender or "") | ||||||
|     local err = Private.send_command(sock, "MAIL", param) |     local err = Private.send_command(sock, "MAIL", param) | ||||||
|     if err then return nil, err end |     if err then return nil, err end | ||||||
|     return Private.check_answer(sock, 250) |     return Private.check_answer(sock, 250) | ||||||
| @@ -198,7 +198,7 @@ function Private.send_data(sock, headers, body) | |||||||
|     local code, answer = Private.check_answer(sock, 354) |     local code, answer = Private.check_answer(sock, 354) | ||||||
|     if not code then return nil, answer end |     if not code then return nil, answer end | ||||||
|     -- avoid premature end in message body |     -- avoid premature end in message body | ||||||
|     body = gsub(body or "", "\n%.", "\n%.%.") |     body = string.gsub(body or "", "\n%.", "\n%.%.") | ||||||
|     -- mark end of message body |     -- mark end of message body | ||||||
|     body = body .. "\r\n.\r\n" |     body = body .. "\r\n.\r\n" | ||||||
|     err = Private.send_headers(sock, headers) |     err = Private.send_headers(sock, headers) | ||||||
| @@ -220,8 +220,9 @@ function Private.send_rcpt(sock, rcpt) | |||||||
|     local err |     local err | ||||||
| 	local code, answer = nil, "No recipient specified" | 	local code, answer = nil, "No recipient specified" | ||||||
|     if type(rcpt) ~= "table" then rcpt = {rcpt} end |     if type(rcpt) ~= "table" then rcpt = {rcpt} end | ||||||
|     for i = 1, getn(rcpt) do |     for i = 1, table.getn(rcpt) do | ||||||
|         err = Private.send_command(sock, "RCPT", format("TO:<%s>", rcpt[i])) |         err = Private.send_command(sock, "RCPT",  | ||||||
|  |             string.format("TO:<%s>", rcpt[i])) | ||||||
|         if err then return nil, err end |         if err then return nil, err end | ||||||
|         code, answer = Private.check_answer(sock, {250, 251}) |         code, answer = Private.check_answer(sock, {250, 251}) | ||||||
|         if not code then return code, answer end |         if not code then return code, answer end | ||||||
| @@ -242,7 +243,7 @@ function Private.open(server) | |||||||
| 	-- default server | 	-- default server | ||||||
| 	server = server or Public.SERVER | 	server = server or Public.SERVER | ||||||
| 	-- connect to server and make sure we won't hang | 	-- connect to server and make sure we won't hang | ||||||
|     local sock, err = connect(server, Public.PORT) |     local sock, err = socket.connect(server, Public.PORT) | ||||||
|     if not sock then return nil, err end |     if not sock then return nil, err end | ||||||
|     sock:timeout(Public.TIMEOUT) |     sock:timeout(Public.TIMEOUT) | ||||||
|     -- initial server greeting |     -- initial server greeting | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								src/url.lua
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/url.lua
									
									
									
									
									
								
							| @@ -8,7 +8,7 @@ | |||||||
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| local Public, Private = {}, {} | local Public, Private = {}, {} | ||||||
| URL = Public | socket.url = Public | ||||||
|  |  | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| -- Parses a url and returns a table with all its parts according to RFC 2396 | -- Parses a url and returns a table with all its parts according to RFC 2396 | ||||||
| @@ -28,7 +28,7 @@ URL = Public | |||||||
| -- Obs: | -- Obs: | ||||||
| --   the leading '/' in {/<path>} is considered part of <path> | --   the leading '/' in {/<path>} is considered part of <path> | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Public.parse_url(url, default) | function Public.parse(url, default) | ||||||
|     -- initialize default parameters |     -- initialize default parameters | ||||||
|     local parsed = default or {} |     local parsed = default or {} | ||||||
|     -- empty url is parsed to nil |     -- empty url is parsed to nil | ||||||
| @@ -70,7 +70,7 @@ end | |||||||
| -- Returns | -- Returns | ||||||
| --   a stringing with the corresponding URL | --   a stringing with the corresponding URL | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Public.build_url(parsed) | function Public.build(parsed) | ||||||
|     local url = parsed.path or "" |     local url = parsed.path or "" | ||||||
|     if parsed.params then url = url .. ";" .. parsed.params end |     if parsed.params then url = url .. ";" .. parsed.params end | ||||||
|     if parsed.query then url = url .. "?" .. parsed.query end |     if parsed.query then url = url .. "?" .. parsed.query end | ||||||
| @@ -102,9 +102,9 @@ end | |||||||
| -- Returns | -- Returns | ||||||
| --   corresponding absolute url | --   corresponding absolute url | ||||||
| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ||||||
| function Public.absolute_url(base_url, relative_url) | function Public.absolute(base_url, relative_url) | ||||||
|     local base = Public.parse_url(base_url) |     local base = Public.parse(base_url) | ||||||
|     local relative = Public.parse_url(relative_url) |     local relative = Public.parse(relative_url) | ||||||
|     if not base then return relative_url |     if not base then return relative_url | ||||||
|     elseif not relative then return base_url |     elseif not relative then return base_url | ||||||
|     elseif relative.scheme then return relative_url |     elseif relative.scheme then return relative_url | ||||||
| @@ -124,7 +124,7 @@ function Public.absolute_url(base_url, relative_url) | |||||||
|                 relative.path = Private.absolute_path(base.path,relative.path) |                 relative.path = Private.absolute_path(base.path,relative.path) | ||||||
|             end |             end | ||||||
|         end |         end | ||||||
|         return Public.build_url(relative) |         return Public.build(relative) | ||||||
|     end |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -141,7 +141,7 @@ function Public.parse_path(path) | |||||||
| 	path = string.gsub(path, "%s", "") | 	path = string.gsub(path, "%s", "") | ||||||
| 	string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) | 	string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end) | ||||||
| 	for i = 1, table.getn(parsed) do | 	for i = 1, table.getn(parsed) do | ||||||
| 		parsed[i] = Code.unescape(parsed[i]) | 		parsed[i] = socket.code.unescape(parsed[i]) | ||||||
| 	end | 	end | ||||||
| 	if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 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 | 	if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end | ||||||
| @@ -201,7 +201,7 @@ function Private.protect_segment(s) | |||||||
| 	local segment_set = Private.segment_set | 	local segment_set = Private.segment_set | ||||||
| 	return string.gsub(s, "(%W)", function (c)  | 	return string.gsub(s, "(%W)", function (c)  | ||||||
| 		if segment_set[c] then return c | 		if segment_set[c] then return c | ||||||
| 		else return Code.escape(c) end | 		else return socket.code.escape(c) end | ||||||
| 	end) | 	end) | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										118
									
								
								test/ftptest.lua
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								test/ftptest.lua
									
									
									
									
									
								
							| @@ -1,21 +1,24 @@ | |||||||
| dofile("noglobals.lua") | dofile("noglobals.lua") | ||||||
|  |  | ||||||
| local similar = function(s1, s2) | local similar = function(s1, s2) | ||||||
|     return strlower(gsub(s1, "%s", "")) == strlower(gsub(s2, "%s", "")) |     return  | ||||||
| end |     string.lower(string.gsub(s1, "%s", "")) ==  | ||||||
|  |     string.lower(string.gsub(s2, "%s", "")) | ||||||
| local capture = function(cmd) |  | ||||||
| 	readfrom("| " .. cmd) |  | ||||||
| 	local s = read("*a") |  | ||||||
| 	readfrom() |  | ||||||
| 	return s |  | ||||||
| end | end | ||||||
|  |  | ||||||
| local readfile = function(name) | local readfile = function(name) | ||||||
|     local f = readfrom(name) | 	local f = io.open(name, "r") | ||||||
| 	if not f then return nil end | 	if not f then return nil end | ||||||
|     local s = read("*a") | 	local s = f:read("*a") | ||||||
|     readfrom() | 	f:close() | ||||||
|  | 	return s | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local capture = function(cmd) | ||||||
|  | 	local f = io.popen(cmd) | ||||||
|  | 	if not f then return nil end | ||||||
|  | 	local s = f:read("*a") | ||||||
|  | 	f:close() | ||||||
| 	return s | 	return s | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -23,7 +26,7 @@ local check = function(v, e, o) | |||||||
| 	e = e or "failed!" | 	e = e or "failed!" | ||||||
| 	o = o or "ok" | 	o = o or "ok" | ||||||
| 	if v then print(o) | 	if v then print(o) | ||||||
| 	else print(e) exit() end | 	else print(e) os.exit() end | ||||||
| end | end | ||||||
|  |  | ||||||
| -- needs an account luasocket:password | -- needs an account luasocket:password | ||||||
| @@ -31,81 +34,82 @@ end | |||||||
|  |  | ||||||
| local index, err, saved, back, expected | local index, err, saved, back, expected | ||||||
|  |  | ||||||
| local t = _time() | local t = socket._time() | ||||||
|  |  | ||||||
| index = readfile("index.html") | index = readfile("test/index.html") | ||||||
|  |  | ||||||
| write("testing file upload: ") | io.write("testing wrong scheme: ") | ||||||
| remove("/var/ftp/dir1/index.up.html") | back, err = socket.ftp.get("wrong://banana.com/lixo") | ||||||
| err = FTP.put("ftp://localhost/dir1/index.up.html;type=i", index) | check(not back and err == "unknown scheme 'wrong'", err) | ||||||
| saved = readfile("/var/ftp/dir1/index.up.html") |  | ||||||
|  | io.write("testing invalid url: ") | ||||||
|  | back, err = socket.ftp.get("localhost/dir1/index.html;type=i") | ||||||
|  | local c, e = socket.connect("", 21) | ||||||
|  | check(not back and err == e, err) | ||||||
|  |  | ||||||
|  | io.write("testing anonymous file upload: ") | ||||||
|  | os.remove("/var/ftp/pub/index.up.html") | ||||||
|  | err = socket.ftp.put("ftp://localhost/pub/index.up.html;type=i", index) | ||||||
|  | saved = readfile("/var/ftp/pub/index.up.html") | ||||||
| check(not err and saved == index, err) | check(not err and saved == index, err) | ||||||
|  |  | ||||||
| write("testing file download: ") | io.write("testing anonymous file download: ") | ||||||
| back, err = FTP.get("ftp://localhost/dir1/index.up.html;type=i") | back, err = socket.ftp.get("ftp://localhost/pub/index.up.html;type=i") | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing no directory changes: ") | io.write("testing no directory changes: ") | ||||||
| back, err = FTP.get("ftp://localhost/index.html;type=i") | back, err = socket.ftp.get("ftp://localhost/index.html;type=i") | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing multiple directory changes: ") | io.write("testing multiple directory changes: ") | ||||||
| back, err = FTP.get("ftp://localhost/dir1/dir2/dir3/dir4/dir5/dir6/index.html;type=i") | back, err = socket.ftp.get("ftp://localhost/pub/dir1/dir2/dir3/dir4/dir5/index.html;type=i") | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing authenticated upload: ") | io.write("testing authenticated upload: ") | ||||||
| remove("/home/luasocket/index.up.html") | os.remove("/home/luasocket/index.up.html") | ||||||
| err = FTP.put("ftp://luasocket:password@localhost/index.up.html;type=i", index) | err = socket.ftp.put("ftp://luasocket:password@localhost/index.up.html;type=i", index) | ||||||
| saved = readfile("/home/luasocket/index.up.html") | saved = readfile("/home/luasocket/index.up.html") | ||||||
| check(not err and saved == index, err) | check(not err and saved == index, err) | ||||||
|  |  | ||||||
| write("testing authenticated download: ") | io.write("testing authenticated download: ") | ||||||
| back, err = FTP.get("ftp://luasocket:password@localhost/index.up.html;type=i") | back, err = socket.ftp.get("ftp://luasocket:password@localhost/index.up.html;type=i") | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing weird-character translation: ") | io.write("testing weird-character translation: ") | ||||||
| back, err = FTP.get("ftp://luasocket:password@localhost/%2fvar/ftp/dir1/index.html;type=i") | back, err = socket.ftp.get("ftp://luasocket:password@localhost/%2fvar/ftp/pub/index.html;type=i") | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing parameter overriding: ") | io.write("testing parameter overriding: ") | ||||||
| back, err = FTP.get { | back, err = socket.ftp.get { | ||||||
| 	url = "//stupid:mistake@localhost/dir1/index.html", | 	url = "//stupid:mistake@localhost/index.html", | ||||||
| 	user = "luasocket", | 	user = "luasocket", | ||||||
| 	password = "password", | 	password = "password", | ||||||
| 	type = "i" | 	type = "i" | ||||||
| } | } | ||||||
| check(not err and back == index, err) | check(not err and back == index, err) | ||||||
|  |  | ||||||
| write("testing wrong scheme: ") | io.write("testing home directory listing: ") | ||||||
| back, err = FTP.get("wrong://banana.com/lixo") |  | ||||||
| check(not back and err == "unknown scheme 'wrong'", err) |  | ||||||
|  |  | ||||||
| write("testing invalid url: ") |  | ||||||
| back, err = FTP.get("localhost/dir1/index.html;type=i") |  | ||||||
| local c, e = connect("", 21) |  | ||||||
| check(not back and err == e, err) |  | ||||||
|  |  | ||||||
| write("testing directory listing: ") |  | ||||||
| expected = capture("ls -F /var/ftp/dir1 | grep -v /") |  | ||||||
| back, err = FTP.get("ftp://localhost/dir1;type=d") |  | ||||||
| check(similar(back, expected)) |  | ||||||
|  |  | ||||||
| write("testing home directory listing: ") |  | ||||||
| expected = capture("ls -F /var/ftp | grep -v /") | expected = capture("ls -F /var/ftp | grep -v /") | ||||||
| back, err = FTP.get("ftp://localhost/") | back, err = socket.ftp.get("ftp://localhost/") | ||||||
| check(back and similar(back, expected), nil, err) | check(back and similar(back, expected), nil, err) | ||||||
|  |  | ||||||
| write("testing upload denial: ") | io.write("testing directory listing: ") | ||||||
| err = FTP.put("ftp://localhost/index.up.html;type=a", index) | expected = capture("ls -F /var/ftp/pub | grep -v /") | ||||||
|  | back, err = socket.ftp.get("ftp://localhost/pub;type=d") | ||||||
|  | check(similar(back, expected)) | ||||||
|  |  | ||||||
|  | io.write("testing upload denial: ") | ||||||
|  | err = socket.ftp.put("ftp://localhost/index.up.html;type=a", index) | ||||||
| check(err, err) | check(err, err) | ||||||
|  |  | ||||||
| write("testing authentication failure: ") | io.write("testing authentication failure: ") | ||||||
| err = FTP.put("ftp://luasocket:wrong@localhost/index.html;type=a", index) | err = socket.ftp.put("ftp://luasocket:wrong@localhost/index.html;type=a", index) | ||||||
|  | print(err) | ||||||
| check(err, err) | check(err, err) | ||||||
|  |  | ||||||
| write("testing wrong file: ") | io.write("testing wrong file: ") | ||||||
| back, err = FTP.get("ftp://localhost/index.wrong.html;type=a") | back, err = socket.ftp.get("ftp://localhost/index.wrong.html;type=a") | ||||||
| check(err, err) | check(err, err) | ||||||
|  |  | ||||||
| print("passed all tests") | print("passed all tests") | ||||||
| print(format("done in %.2fs", _time() - t)) | print(string.format("done in %.2fs", socket._time() - t)) | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ local check = function (v, e) | |||||||
| end | end | ||||||
| 	 | 	 | ||||||
| local check_request = function(request, expect, ignore) | local check_request = function(request, expect, ignore) | ||||||
| 	local response = http.request(request) | 	local response = socket.http.request(request) | ||||||
| 	for i,v in response do | 	for i,v in response do | ||||||
| 		if not ignore[i] then | 		if not ignore[i] then | ||||||
| 			if v ~= expect[i] then %fail(i .. " differs!") end | 			if v ~= expect[i] then %fail(i .. " differs!") end | ||||||
| @@ -56,13 +56,13 @@ index = readfile("test/index.html") | |||||||
|  |  | ||||||
| io.write("testing request uri correctness: ") | io.write("testing request uri correctness: ") | ||||||
| local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string" | local forth = cgiprefix .. "/request-uri?" .. "this+is+the+query+string" | ||||||
| local back = http.get("http://" .. HOST .. forth) | local back = socket.http.get("http://" .. HOST .. forth) | ||||||
| if similar(back, forth) then print("ok") | if similar(back, forth) then print("ok") | ||||||
| else fail("failed!") end | else fail("failed!") end | ||||||
|  |  | ||||||
| io.write("testing query string correctness: ") | io.write("testing query string correctness: ") | ||||||
| forth = "this+is+the+query+string" | forth = "this+is+the+query+string" | ||||||
| back = 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") | if similar(back, forth) then print("ok") | ||||||
| else fail("failed!") end | else fail("failed!") end | ||||||
|  |  | ||||||
| @@ -178,7 +178,7 @@ io.write("testing manual basic auth: ") | |||||||
| request = { | request = { | ||||||
| 	url = "http://" .. HOST .. prefix .. "/auth/index.html", | 	url = "http://" .. HOST .. prefix .. "/auth/index.html", | ||||||
| 	headers = { | 	headers = { | ||||||
| 		authorization = "Basic " .. Code.base64("luasocket:password") | 		authorization = "Basic " .. socket.code.base64("luasocket:password") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| expect = { | expect = { | ||||||
| @@ -279,11 +279,11 @@ check_request(request, expect, ignore) | |||||||
|  |  | ||||||
| local body | local body | ||||||
| io.write("testing simple get function: ") | io.write("testing simple get function: ") | ||||||
| body = http.get("http://" .. HOST .. prefix .. "/index.html") | body = socket.http.get("http://" .. HOST .. prefix .. "/index.html") | ||||||
| check(body == index) | check(body == index) | ||||||
|  |  | ||||||
| io.write("testing simple get function with table args: ") | io.write("testing simple get function with table args: ") | ||||||
| body = http.get { | body = socket.http.get { | ||||||
| 	url = "http://really:wrong@" .. HOST .. prefix .. "/auth/index.html", | 	url = "http://really:wrong@" .. HOST .. prefix .. "/auth/index.html", | ||||||
| 	user = "luasocket", | 	user = "luasocket", | ||||||
| 	password = "password" | 	password = "password" | ||||||
| @@ -291,18 +291,18 @@ body = http.get { | |||||||
| check(body == index) | check(body == index) | ||||||
|  |  | ||||||
| io.write("testing simple post function: ") | io.write("testing simple post function: ") | ||||||
| body = http.post("http://" .. HOST .. cgiprefix .. "/cat", index) | body = socket.http.post("http://" .. HOST .. cgiprefix .. "/cat", index) | ||||||
| check(body == index) | check(body == index) | ||||||
|  |  | ||||||
| io.write("testing simple post function with table args: ") | io.write("testing simple post function with table args: ") | ||||||
| body = http.post { | body = socket.http.post { | ||||||
| 	url = "http://" .. HOST .. cgiprefix .. "/cat", | 	url = "http://" .. HOST .. cgiprefix .. "/cat", | ||||||
| 	body = index | 	body = index | ||||||
| } | } | ||||||
| check(body == index) | check(body == index) | ||||||
|  |  | ||||||
| io.write("testing HEAD method: ") | io.write("testing HEAD method: ") | ||||||
| response = http.request { | response = socket.http.request { | ||||||
|   method = "HEAD", |   method = "HEAD", | ||||||
|   url = "http://www.tecgraf.puc-rio.br/~diego/" |   url = "http://www.tecgraf.puc-rio.br/~diego/" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,122 +1,130 @@ | |||||||
| local sent = {} | local sent = {} | ||||||
|  |  | ||||||
| local from = "luasock@tecgraf.puc-rio.br" | local from = "diego@localhost" | ||||||
| local server = "mail.tecgraf.puc-rio.br" | local server = "localhost" | ||||||
| local rcpt = "luasock@tecgraf.puc-rio.br" | local rcpt = "luasocket@localhost" | ||||||
|  |  | ||||||
| local name = "/var/spool/mail/luasock" | local files = { | ||||||
|  |     "/var/spool/mail/luasocket", | ||||||
|  |     "/var/spool/mail/luasock1", | ||||||
|  |     "/var/spool/mail/luasock2", | ||||||
|  |     "/var/spool/mail/luasock3", | ||||||
|  | } | ||||||
|  |  | ||||||
| local t = _time() | local t = socket._time() | ||||||
| local err | local err | ||||||
|  |  | ||||||
| dofile("parsembox.lua") | dofile("mbox.lua") | ||||||
| local parse = parse | local parse = mbox.parse | ||||||
| dofile("noglobals.lua") | dofile("noglobals.lua") | ||||||
|  |  | ||||||
| local total = function() | local total = function() | ||||||
| 	local t = 0 | 	local t = 0 | ||||||
| 	for i = 1, getn(%sent) do | 	for i = 1, table.getn(sent) do | ||||||
| 		t = t + %sent[i].count | 		t = t + sent[i].count | ||||||
| 	end | 	end | ||||||
| 	return t | 	return t | ||||||
| end | end | ||||||
|  |  | ||||||
| local similar = function(s1, s2) | local similar = function(s1, s2) | ||||||
|     return strlower(gsub(s1, "%s", "")) == strlower(gsub(s2, "%s", "")) |     return  | ||||||
| end |     string.lower(string.gsub(s1, "%s", "")) ==  | ||||||
|  |     string.lower(string.gsub(s2, "%s", "")) | ||||||
| local readfile = function(name) |  | ||||||
|     local f = readfrom(name) |  | ||||||
|     if not f then return nil end |  | ||||||
|     local s = read("*a") |  | ||||||
|     readfrom() |  | ||||||
|     return s |  | ||||||
| end |  | ||||||
|  |  | ||||||
| local capture = function(cmd) |  | ||||||
|     readfrom("| " .. cmd) |  | ||||||
|     local s = read("*a") |  | ||||||
|     readfrom() |  | ||||||
|     return s |  | ||||||
| end | end | ||||||
|  |  | ||||||
| local fail = function(s) | local fail = function(s) | ||||||
|     s = s or "failed!" |     s = s or "failed!" | ||||||
|     print(s) |     print(s) | ||||||
|     exit() |     os.exit() | ||||||
|  | end | ||||||
|  |  | ||||||
|  | local readfile = function(name) | ||||||
|  | 	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 | ||||||
| end | end | ||||||
|  |  | ||||||
| local empty = function() | local empty = function() | ||||||
|     local f = openfile(%name, "w") |     for i,v in ipairs(files) do | ||||||
|     closefile(f) |         local f = io.open(v, "w") | ||||||
|  |         if not f then  | ||||||
|  |             fail("unable to open file!") | ||||||
|  |         end | ||||||
|  |         f:close() | ||||||
|  |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| local get = function() | local get = function() | ||||||
| 	return %readfile(%name) |     s = "" | ||||||
| end |     for i,v in ipairs(files) do | ||||||
|  | 	    s = s .. "\n" .. readfile(v) | ||||||
| local list = function() |     end | ||||||
|     return %capture("ls -l " .. %name) |     return s | ||||||
| end | end | ||||||
|  |  | ||||||
| local check_headers = function(sent, got) | local check_headers = function(sent, got) | ||||||
|     sent = sent or {} |     sent = sent or {} | ||||||
|     got = got or {} |     got = got or {} | ||||||
|     for i,v in sent do |     for i,v in sent do | ||||||
|         if not %similar(v, got[i]) then %fail("header " .. v .. "failed!") end |         if not similar(v, got[i]) then fail("header " .. v .. "failed!") end | ||||||
|     end |     end | ||||||
| end | end | ||||||
|  |  | ||||||
| local check_body = function(sent, got) | local check_body = function(sent, got) | ||||||
|     sent = sent or "" |     sent = sent or "" | ||||||
|     got = got or "" |     got = got or "" | ||||||
|     if not %similar(sent, got) then %fail("bodies differ!") end |     if not similar(sent, got) then fail("bodies differ!") end | ||||||
| end | end | ||||||
|  |  | ||||||
| local check = function(sent, m) | local check = function(sent, m) | ||||||
| 	write("checking ", m.headers.title, ": ") | 	io.write("checking ", m.headers.title, ": ") | ||||||
| 	for i = 1, getn(sent) do | 	for i = 1, table.getn(sent) do | ||||||
| 		local s = sent[i] | 		local s = sent[i] | ||||||
| 		if s.title == m.headers.title and s.count > 0 then | 		if s.title == m.headers.title and s.count > 0 then | ||||||
| 			%check_headers(s.headers, m.headers) | 			check_headers(s.headers, m.headers) | ||||||
| 			%check_body(s.body, m.body) | 			check_body(s.body, m.body) | ||||||
| 			s.count = s.count - 1 | 			s.count = s.count - 1 | ||||||
| 			print("ok") | 			print("ok") | ||||||
| 			return | 			return | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 	%fail("not found") | 	fail("not found") | ||||||
| end | end | ||||||
|  |  | ||||||
| local insert = function(sent, message) | local insert = function(sent, message) | ||||||
| 	if type(message.rcpt) == "table" then | 	if type(message.rcpt) == "table" then | ||||||
| 		message.count = getn(message.rcpt) | 		message.count = table.getn(message.rcpt) | ||||||
| 	else message.count = 1 end | 	else message.count = 1 end | ||||||
| 	message.headers = message.headers or {} | 	message.headers = message.headers or {} | ||||||
| 	message.headers.title = message.title | 	message.headers.title = message.title | ||||||
| 	tinsert(sent, message) | 	table.insert(sent, message) | ||||||
| end | end | ||||||
|  |  | ||||||
| local mark = function() | local mark = function() | ||||||
| 	local time = _time() | 	local time = socket._time() | ||||||
|     return { time = time } |     return { time = time } | ||||||
| end | end | ||||||
|  |  | ||||||
| local wait = function(sentinel, n) | local wait = function(sentinel, n) | ||||||
|     local to |     local to | ||||||
| 	write("waiting for ", n, " messages: ") | 	io.write("waiting for ", n, " messages: ") | ||||||
|     while 1 do |     while 1 do | ||||||
| 		local mbox = %parse.mbox(%get()) | 		local mbox = parse(get()) | ||||||
| 		if n == getn(mbox) then break end | 		if n == table.getn(mbox) then break end | ||||||
|         if _time() - sentinel.time > 50 then  |         if socket._time() - sentinel.time > 50 then  | ||||||
|             to = 1  |             to = 1  | ||||||
|             break |             break | ||||||
|         end |         end | ||||||
|         _sleep(1) |         socket._sleep(1) | ||||||
|         write(".") |         io.write(".") | ||||||
|         flush(_STDOUT) |         io.stdout:flush() | ||||||
|     end |     end | ||||||
| 	if to then %fail("timeout") | 	if to then fail("timeout") | ||||||
| 	else print("ok") end | 	else print("ok") end | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -129,16 +137,16 @@ Otherwise the mailer would | |||||||
| think that the dot | think that the dot | ||||||
| . | . | ||||||
| is the end of the message | is the end of the message | ||||||
| and the remaining will cause | and the remaining text would cause | ||||||
| a lot of trouble. | a lot of trouble. | ||||||
| ]] | ]] | ||||||
|  |  | ||||||
| insert(sent, { | insert(sent, { | ||||||
|     from = from, |     from = from, | ||||||
|     rcpt = { |     rcpt = { | ||||||
| 		"luasock2@tecgraf.puc-rio.br", | 		"luasocket@localhost", | ||||||
| 		"luasock", | 		"luasock3@dell-diego.cs.princeton.edu", | ||||||
| 		"luasock1" | 		"luasock1@dell-diego.cs.princeton.edu" | ||||||
| 	}, | 	}, | ||||||
| 	body = "multiple rcpt body", | 	body = "multiple rcpt body", | ||||||
| 	title = "multiple rcpt", | 	title = "multiple rcpt", | ||||||
| @@ -147,8 +155,8 @@ insert(sent, { | |||||||
| insert(sent, { | insert(sent, { | ||||||
|     from = from, |     from = from, | ||||||
|     rcpt = { |     rcpt = { | ||||||
| 		"luasock2@tecgraf.puc-rio.br", | 		"luasock2@localhost", | ||||||
| 		"luasock", | 		"luasock3", | ||||||
| 		"luasock1" | 		"luasock1" | ||||||
| 	}, | 	}, | ||||||
|     headers = { |     headers = { | ||||||
| @@ -199,9 +207,9 @@ insert(sent, { | |||||||
|     title = "minimum message" |     title = "minimum message" | ||||||
| }) | }) | ||||||
|  |  | ||||||
| write("testing host not found: ") | io.write("testing host not found: ") | ||||||
| local c, e = connect("wrong.host", 25) | local c, e = socket.connect("wrong.host", 25) | ||||||
| local err = SMTP.mail{ | local err = socket.smtp.mail{ | ||||||
| 	from = from, | 	from = from, | ||||||
| 	rcpt = rcpt, | 	rcpt = rcpt, | ||||||
| 	server = "wrong.host" | 	server = "wrong.host" | ||||||
| @@ -209,44 +217,43 @@ local err = SMTP.mail{ | |||||||
| if e ~= err then fail("wrong error message") | if e ~= err then fail("wrong error message") | ||||||
| else print("ok") end | else print("ok") end | ||||||
|  |  | ||||||
| write("testing invalid from: ") | io.write("testing invalid from: ") | ||||||
| local err = SMTP.mail{ | local err = socket.smtp.mail{ | ||||||
| 	from = ' " " (( _ * ',  | 	from = ' " " (( _ * ',  | ||||||
| 	rcpt = rcpt, | 	rcpt = rcpt, | ||||||
| } | } | ||||||
| if not err then fail("wrong error message") | if not err then fail("wrong error message") | ||||||
| else print(err) end | else print(err) end | ||||||
|  |  | ||||||
| write("testing no rcpt: ") | io.write("testing no rcpt: ") | ||||||
| local err = SMTP.mail{ | local err = socket.smtp.mail{ | ||||||
| 	from = from,  | 	from = from,  | ||||||
| } | } | ||||||
| if not err then fail("wrong error message") | if not err then fail("wrong error message") | ||||||
| else print(err) end | else print(err) end | ||||||
|  |  | ||||||
| write("clearing mailbox: ") | io.write("clearing mailbox: ") | ||||||
| empty() | empty() | ||||||
| print("ok") | print("ok") | ||||||
|  |  | ||||||
| write("sending messages: ") | io.write("sending messages: ") | ||||||
| for i = 1, getn(sent) do | for i = 1, table.getn(sent) do | ||||||
|     err = SMTP.mail(sent[i]) |     err = socket.smtp.mail(sent[i]) | ||||||
|     if err then fail(err) end |     if err then fail(err) end | ||||||
|     write("+") |     io.write("+") | ||||||
|     flush(_STDOUT) |     io.stdout:flush() | ||||||
| end | end | ||||||
| print("ok") | print("ok") | ||||||
|  |  | ||||||
| wait(mark(), total()) | wait(mark(), total()) | ||||||
|  |  | ||||||
| write("parsing mailbox: ") | io.write("parsing mailbox: ") | ||||||
| local mbox = parse.mbox(get()) | local mbox = parse(get()) | ||||||
| print(getn(mbox) .. " messages found!") | print(table.getn(mbox) .. " messages found!") | ||||||
|  |  | ||||||
| for i = 1, getn(mbox) do | for i = 1, table.getn(mbox) do | ||||||
| 	check(sent, mbox[i]) | 	check(sent, mbox[i]) | ||||||
| end | end | ||||||
|  |  | ||||||
|  |  | ||||||
| print("passed all tests") | print("passed all tests") | ||||||
| print(format("done in %.2fs", _time() - t)) | print(string.format("done in %.2fs", socket._time() - t)) | ||||||
|   | |||||||
| @@ -1,5 +1,8 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| local check_build_url = function(parsed) | local check_build_url = function(parsed) | ||||||
| 	local built = URL.build_url(parsed) | 	local built = socket.url.build(parsed) | ||||||
|     if built ~= parsed.url then |     if built ~= parsed.url then | ||||||
| 	    print("built is different from expected") | 	    print("built is different from expected") | ||||||
| 		print(built) | 		print(built) | ||||||
| @@ -9,7 +12,7 @@ local check_build_url = function(parsed) | |||||||
| end | end | ||||||
|  |  | ||||||
| local check_protect = function(parsed, path, unsafe) | local check_protect = function(parsed, path, unsafe) | ||||||
| 	local built = URL.build_path(parsed, unsafe) | 	local built = socket.url.build_path(parsed, unsafe) | ||||||
| 	if built ~= path then | 	if built ~= path then | ||||||
| 		print(built, path) | 		print(built, path) | ||||||
| 	    print("path composition failed.") | 	    print("path composition failed.") | ||||||
| @@ -18,9 +21,9 @@ local check_protect = function(parsed, path, unsafe) | |||||||
| end | end | ||||||
|  |  | ||||||
| local check_invert = function(url) | local check_invert = function(url) | ||||||
| 	local parsed = URL.parse_url(url) | 	local parsed = socket.url.parse(url) | ||||||
| 	parsed.path = URL.build_path(URL.parse_path(parsed.path)) | 	parsed.path = socket.url.build_path(socket.url.parse_path(parsed.path)) | ||||||
| 	local rebuilt = URL.build_url(parsed) | 	local rebuilt = socket.url.build(parsed) | ||||||
| 	if rebuilt ~= url then | 	if rebuilt ~= url then | ||||||
| 		print(url, rebuilt) | 		print(url, rebuilt) | ||||||
| 	    print("original and rebuilt are different") | 	    print("original and rebuilt are different") | ||||||
| @@ -29,7 +32,7 @@ local check_invert = function(url) | |||||||
| end | end | ||||||
|  |  | ||||||
| local check_parse_path = function(path, expect) | local check_parse_path = function(path, expect) | ||||||
| 	local parsed = URL.parse_path(path) | 	local parsed = socket.url.parse_path(path) | ||||||
| 	for i = 1, math.max(table.getn(parsed), table.getn(expect)) do | 	for i = 1, math.max(table.getn(parsed), table.getn(expect)) do | ||||||
| 		if parsed[i] ~= expect[i] then | 		if parsed[i] ~= expect[i] then | ||||||
| 			print(path) | 			print(path) | ||||||
| @@ -48,7 +51,7 @@ local check_parse_path = function(path, expect) | |||||||
| 	    print("is_absolute mismatch") | 	    print("is_absolute mismatch") | ||||||
| 		exit() | 		exit() | ||||||
| 	end | 	end | ||||||
| 	local built = URL.build_path(expect) | 	local built = socket.url.build_path(expect) | ||||||
| 	if built ~= path then | 	if built ~= path then | ||||||
| 		print(built, path) | 		print(built, path) | ||||||
| 	    print("path composition failed.") | 	    print("path composition failed.") | ||||||
| @@ -57,7 +60,7 @@ local check_parse_path = function(path, expect) | |||||||
| end | end | ||||||
|  |  | ||||||
| local check_absolute_url = function(base, relative, absolute) | local check_absolute_url = function(base, relative, absolute) | ||||||
| 	local res = URL.absolute_url(base, relative) | 	local res = socket.url.absolute(base, relative) | ||||||
| 	if res ~= absolute then  | 	if res ~= absolute then  | ||||||
| 		write("absolute: In test for '", relative, "' expected '",  | 		write("absolute: In test for '", relative, "' expected '",  | ||||||
|             absolute, "' but got '", res, "'\n") |             absolute, "' but got '", res, "'\n") | ||||||
| @@ -68,7 +71,7 @@ end | |||||||
| local check_parse_url = function(gaba) | local check_parse_url = function(gaba) | ||||||
| 	local url = gaba.url | 	local url = gaba.url | ||||||
| 	gaba.url = nil | 	gaba.url = nil | ||||||
| 	local parsed = URL.parse_url(url) | 	local parsed = socket.url.parse(url) | ||||||
| 	for i, v in gaba do | 	for i, v in gaba do | ||||||
| 		if v ~= parsed[i] then | 		if v ~= parsed[i] then | ||||||
| 			write("parse: In test for '", url, "' expected ", i, " = '",  | 			write("parse: In test for '", url, "' expected ", i, " = '",  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user