aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-05-28 06:16:43 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-05-28 06:16:43 +0000
commit694edcc3c1ac3041ff8cdd753a2f7894e8783e6c (patch)
treef8797b4c7671fbf9042fc011277d69d4c3549045
parentbf738a03368b8de9c574d9631f131c5a520acf7b (diff)
downloadluasocket-694edcc3c1ac3041ff8cdd753a2f7894e8783e6c.tar.gz
luasocket-694edcc3c1ac3041ff8cdd753a2f7894e8783e6c.tar.bz2
luasocket-694edcc3c1ac3041ff8cdd753a2f7894e8783e6c.zip
Committing with require.
-rw-r--r--etc/b64.lua2
-rw-r--r--etc/dict.lua5
-rw-r--r--samples/cddb.lua4
-rw-r--r--src/ftp.lua89
-rw-r--r--src/http.lua10
-rw-r--r--src/luasocket.c37
-rw-r--r--src/mime.c10
-rw-r--r--src/mime.h9
-rw-r--r--src/mime.lua27
-rw-r--r--src/smtp.lua22
-rw-r--r--src/tp.lua10
-rw-r--r--src/url.lua2
-rw-r--r--test/httptest.lua4
13 files changed, 152 insertions, 79 deletions
diff --git a/etc/b64.lua b/etc/b64.lua
index 3f861b4..1993b01 100644
--- a/etc/b64.lua
+++ b/etc/b64.lua
@@ -1,3 +1,5 @@
1require("ltn12")
2require("mime")
1local source = ltn12.source.file(io.stdin) 3local source = ltn12.source.file(io.stdin)
2local sink = ltn12.sink.file(io.stdout) 4local sink = ltn12.sink.file(io.stdout)
3local convert 5local convert
diff --git a/etc/dict.lua b/etc/dict.lua
index 933c1c8..d11ac93 100644
--- a/etc/dict.lua
+++ b/etc/dict.lua
@@ -8,12 +8,11 @@ function get_status(sock, valid)
8 local line, err = sock:receive() 8 local line, err = sock:receive()
9 local code, par 9 local code, par
10 if not line then sock:close() return err end 10 if not line then sock:close() return err end
11 _, _, code = string.find(line, "^(%d%d%d)") 11 code = socket.skip(2, string.find(line, "^(%d%d%d)"))
12 code = tonumber(code) 12 code = tonumber(code)
13 if code ~= valid then return code end 13 if code ~= valid then return code end
14 if code == 150 then 14 if code == 150 then
15 _,_,_, par = string.find(line, "^(%d%d%d) (%d*)") 15 par = tonumber(socket.skip(2, string.find(line, "^%d%d%d (%d*)"))
16 par = tonumber(par)
17 end 16 end
18 return nil, par 17 return nil, par
19end 18end
diff --git a/samples/cddb.lua b/samples/cddb.lua
index 6ade3c0..0ed7c71 100644
--- a/samples/cddb.lua
+++ b/samples/cddb.lua
@@ -8,7 +8,7 @@ local server = arg[3] or "http://freedb.freedb.org/~cddb/cddb.cgi"
8function parse(body) 8function parse(body)
9 local lines = string.gfind(body, "(.-)\r\n") 9 local lines = string.gfind(body, "(.-)\r\n")
10 local status = lines() 10 local status = lines()
11 local _, _, code, message = string.find(status, "(%d%d%d) (.*)") 11 local code, message = socket.skip(2, string.find(status, "(%d%d%d) (.*)"))
12 if tonumber(code) ~= 210 then 12 if tonumber(code) ~= 210 then
13 return nil, code, message 13 return nil, code, message
14 end 14 end
@@ -16,7 +16,7 @@ function parse(body)
16 for l in lines do 16 for l in lines do
17 local c = string.sub(l, 1, 1) 17 local c = string.sub(l, 1, 1)
18 if c ~= '#' and c ~= '.' then 18 if c ~= '#' and c ~= '.' then
19 local _, _, key, value = string.find(l, "(.-)=(.*)") 19 local key, value = socket.skip(2, string.find(l, "(.-)=(.*)"))
20 value = string.gsub(value, "\\n", "\n") 20 value = string.gsub(value, "\\n", "\n")
21 value = string.gsub(value, "\\\\", "\\") 21 value = string.gsub(value, "\\\\", "\\")
22 value = string.gsub(value, "\\t", "\t") 22 value = string.gsub(value, "\\t", "\t")
diff --git a/src/ftp.lua b/src/ftp.lua
index 306b77f..efb872a 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -10,6 +10,11 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
10-- get LuaSocket namespace 10-- get LuaSocket namespace
11local socket = _G[LUASOCKET_LIBNAME] 11local socket = _G[LUASOCKET_LIBNAME]
12if not socket then error('module requires LuaSocket') end 12if not socket then error('module requires LuaSocket') end
13
14-- require other modules
15require("ltn12")
16require("url")
17
13-- create namespace inside LuaSocket namespace 18-- create namespace inside LuaSocket namespace
14socket.ftp = socket.ftp or {} 19socket.ftp = socket.ftp or {}
15-- make all module globals fall into namespace 20-- make all module globals fall into namespace
@@ -25,6 +30,7 @@ TIMEOUT = 60
25PORT = 21 30PORT = 21
26-- this is the default anonymous password. used when no password is 31-- this is the default anonymous password. used when no password is
27-- provided in url. should be changed to your e-mail. 32-- provided in url. should be changed to your e-mail.
33USER = "ftp"
28EMAIL = "anonymous@anonymous.org" 34EMAIL = "anonymous@anonymous.org"
29-- block size used in transfers 35-- block size used in transfers
30BLOCKSIZE = 2048 36BLOCKSIZE = 2048
@@ -48,21 +54,20 @@ local function pasv(pasvt)
48end 54end
49 55
50function metat.__index:login(user, password) 56function metat.__index:login(user, password)
51 socket.try(self.tp:command("USER", user)) 57 socket.try(self.tp:command("user", user or USER))
52 local code, reply = socket.try(self.tp:check{"2..", 331}) 58 local code, reply = socket.try(self.tp:check{"2..", 331})
53 if code == 331 then 59 if code == 331 then
54 socket.try(password, reply) 60 socket.try(self.tp:command("pass", password or EMAIL))
55 socket.try(self.tp:command("PASS", password))
56 socket.try(self.tp:check("2..")) 61 socket.try(self.tp:check("2.."))
57 end 62 end
58 return 1 63 return 1
59end 64end
60 65
61function metat.__index:pasv() 66function metat.__index:pasv()
62 socket.try(self.tp:command("PASV")) 67 socket.try(self.tp:command("pasv"))
63 local code, reply = socket.try(self.tp:check("2..")) 68 local code, reply = socket.try(self.tp:check("2.."))
64 local _, _, a, b, c, d, p1, p2 = 69 local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
65 string.find(reply, "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)") 70 local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
66 socket.try(a and b and c and d and p1 and p2, reply) 71 socket.try(a and b and c and d and p1 and p2, reply)
67 self.pasvt = { 72 self.pasvt = {
68 ip = string.format("%d.%d.%d.%d", a, b, c, d), 73 ip = string.format("%d.%d.%d.%d", a, b, c, d),
@@ -97,7 +102,7 @@ function metat.__index:send(sendt)
97 local data 102 local data
98 socket.try(self.pasvt or self.portt, "need port or pasv first") 103 socket.try(self.pasvt or self.portt, "need port or pasv first")
99 if self.pasvt then data = socket.try(pasv(self.pasvt)) end 104 if self.pasvt then data = socket.try(pasv(self.pasvt)) end
100 socket.try(self.tp:command(sendt.command, sendt.argument)) 105 socket.try(self.tp:command(sendt.command or "stor", sendt.argument))
101 local code, reply = socket.try(self.tp:check{"2..", "1.."}) 106 local code, reply = socket.try(self.tp:check{"2..", "1.."})
102 if self.portt then data = socket.try(port(self.portt)) end 107 if self.portt then data = socket.try(port(self.portt)) end
103 local step = sendt.step or ltn12.pump.step 108 local step = sendt.step or ltn12.pump.step
@@ -124,7 +129,7 @@ function metat.__index:receive(recvt)
124 local data 129 local data
125 socket.try(self.pasvt or self.portt, "need port or pasv first") 130 socket.try(self.pasvt or self.portt, "need port or pasv first")
126 if self.pasvt then data = socket.try(pasv(self.pasvt)) end 131 if self.pasvt then data = socket.try(pasv(self.pasvt)) end
127 socket.try(self.tp:command(recvt.command, recvt.argument)) 132 socket.try(self.tp:command(recvt.command or "retr", recvt.argument))
128 local code = socket.try(self.tp:check{"1..", "2.."}) 133 local code = socket.try(self.tp:check{"1..", "2.."})
129 if self.portt then data = socket.try(port(self.portt)) end 134 if self.portt then data = socket.try(port(self.portt)) end
130 local source = socket.source("until-closed", data) 135 local source = socket.source("until-closed", data)
@@ -140,13 +145,13 @@ function metat.__index:receive(recvt)
140end 145end
141 146
142function metat.__index:cwd(dir) 147function metat.__index:cwd(dir)
143 socket.try(self.tp:command("CWD", dir)) 148 socket.try(self.tp:command("cwd", dir))
144 socket.try(self.tp:check(250)) 149 socket.try(self.tp:check(250))
145 return 1 150 return 1
146end 151end
147 152
148function metat.__index:type(type) 153function metat.__index:type(type)
149 socket.try(self.tp:command("TYPE", type)) 154 socket.try(self.tp:command("type", type))
150 socket.try(self.tp:check(200)) 155 socket.try(self.tp:check(200))
151 return 1 156 return 1
152end 157end
@@ -158,7 +163,7 @@ function metat.__index:greet()
158end 163end
159 164
160function metat.__index:quit() 165function metat.__index:quit()
161 socket.try(self.tp:command("QUIT")) 166 socket.try(self.tp:command("quit"))
162 socket.try(self.tp:check("2..")) 167 socket.try(self.tp:check("2.."))
163 return 1 168 return 1
164end 169end
@@ -171,11 +176,69 @@ end
171----------------------------------------------------------------------------- 176-----------------------------------------------------------------------------
172-- High level FTP API 177-- High level FTP API
173----------------------------------------------------------------------------- 178-----------------------------------------------------------------------------
179local function tput(putt)
180 local ftp = socket.ftp.open(putt.host, putt.port)
181 ftp:greet()
182 ftp:login(putt.user, putt.password)
183 if putt.type then ftp:type(putt.type) end
184 ftp:pasv()
185 ftp:send(putt)
186 ftp:quit()
187 return ftp:close()
188end
174 189
175function put(putt) 190local default = {
191 path = "/",
192 scheme = "ftp"
193}
194
195local function parse(url)
196 local putt = socket.try(socket.url.parse(url, default))
197 socket.try(putt.scheme == "ftp", "invalid scheme '" .. putt.scheme .. "'")
198 socket.try(putt.host, "invalid host")
199 local pat = "^type=(.)$"
200 if putt.params then
201 putt.type = socket.skip(2, string.find(putt.params, pat))
202 socket.try(putt.type == "a" or putt.type == "i")
203 end
204 -- skip first backslash in path
205 putt.argument = string.sub(putt.path, 2)
206 return putt
176end 207end
177 208
178function get(gett) 209local function sput(url, body)
210 local putt = parse(url)
211 putt.source = ltn12.source.string(body)
212 return tput(putt)
179end 213end
180 214
215put = socket.protect(function(putt, body)
216 if type(putt) == "string" then return sput(putt, body)
217 else return tput(putt) end
218end)
219
220local function tget(gett)
221 local ftp = socket.ftp.open(gett.host, gett.port)
222 ftp:greet()
223 ftp:login(gett.user, gett.password)
224 if gett.type then ftp:type(gett.type) end
225 ftp:pasv()
226 ftp:receive(gett)
227 ftp:quit()
228 return ftp:close()
229end
230
231local function sget(url, body)
232 local gett = parse(url)
233 local t = {}
234 gett.sink = ltn12.sink.table(t)
235 tget(gett)
236 return table.concat(t)
237end
238
239get = socket.protect(function(gett)
240 if type(gett) == "string" then return sget(gett, body)
241 else return tget(gett) end
242end)
243
181return ftp 244return ftp
diff --git a/src/http.lua b/src/http.lua
index f787b9d..e6a0928 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -10,6 +10,12 @@ if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
10-- get LuaSocket namespace 10-- get LuaSocket namespace
11local socket = _G[LUASOCKET_LIBNAME] 11local socket = _G[LUASOCKET_LIBNAME]
12if not socket then error('module requires LuaSocket') end 12if not socket then error('module requires LuaSocket') end
13
14-- require other modules
15require("ltn12")
16require("mime")
17require("url")
18
13-- create namespace inside LuaSocket namespace 19-- create namespace inside LuaSocket namespace
14socket.http = socket.http or {} 20socket.http = socket.http or {}
15-- make all module globals fall into namespace 21-- make all module globals fall into namespace
@@ -41,7 +47,7 @@ end
41 47
42local function receive_headers(reqt, respt, tmp) 48local function receive_headers(reqt, respt, tmp)
43 local sock = tmp.sock 49 local sock = tmp.sock
44 local line, name, value, _ 50 local line, name, value
45 local headers = {} 51 local headers = {}
46 -- store results 52 -- store results
47 respt.headers = headers 53 respt.headers = headers
@@ -50,7 +56,7 @@ local function receive_headers(reqt, respt, tmp)
50 -- headers go until a blank line is found 56 -- headers go until a blank line is found
51 while line ~= "" do 57 while line ~= "" do
52 -- get field-name and value 58 -- get field-name and value
53 _, _, name, value = string.find(line, "^(.-):%s*(.*)") 59 name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
54 socket.try(name and value, "malformed reponse headers") 60 socket.try(name and value, "malformed reponse headers")
55 name = string.lower(name) 61 name = string.lower(name)
56 -- get next line (value might be folded) 62 -- get next line (value might be folded)
diff --git a/src/luasocket.c b/src/luasocket.c
index fe4c96c..8d49be5 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -35,38 +35,6 @@
35#include "udp.h" 35#include "udp.h"
36#include "select.h" 36#include "select.h"
37#include "smtp.h" 37#include "smtp.h"
38#include "mime.h"
39
40/*=========================================================================*\
41* Declarations
42\*=========================================================================*/
43static int mod_open(lua_State *L, const luaL_reg *mod);
44
45
46static int mod_open(lua_State *L, const luaL_reg *mod)
47{
48 for (; mod->name; mod++) mod->func(L);
49#ifdef LUASOCKET_COMPILED
50#include "ltn12.lch"
51#include "auxiliar.lch"
52#include "url.lch"
53#include "mime.lch"
54#include "tp.lch"
55#include "smtp.lch"
56#include "http.lch"
57#include "ftp.lch"
58#else
59 lua_dofile(L, "ltn12.lua");
60 lua_dofile(L, "auxiliar.lua");
61 lua_dofile(L, "url.lua");
62 lua_dofile(L, "mime.lua");
63 lua_dofile(L, "tp.lua");
64 lua_dofile(L, "smtp.lua");
65 lua_dofile(L, "http.lua");
66 lua_dofile(L, "ftp.lua");
67#endif
68 return 0;
69}
70 38
71/*-------------------------------------------------------------------------*\ 39/*-------------------------------------------------------------------------*\
72* Modules 40* Modules
@@ -80,7 +48,6 @@ static const luaL_reg mod[] = {
80 {"tcp", tcp_open}, 48 {"tcp", tcp_open},
81 {"udp", udp_open}, 49 {"udp", udp_open},
82 {"select", select_open}, 50 {"select", select_open},
83 {"mime", mime_open},
84 {"smtp", smtp_open}, 51 {"smtp", smtp_open},
85 {NULL, NULL} 52 {NULL, NULL}
86}; 53};
@@ -90,11 +57,13 @@ static const luaL_reg mod[] = {
90\*-------------------------------------------------------------------------*/ 57\*-------------------------------------------------------------------------*/
91LUASOCKET_API int luaopen_socket(lua_State *L) 58LUASOCKET_API int luaopen_socket(lua_State *L)
92{ 59{
60 int i;
93 if (!sock_open()) { 61 if (!sock_open()) {
94 lua_pushnil(L); 62 lua_pushnil(L);
95 lua_pushstring(L, "unable to initialize library"); 63 lua_pushstring(L, "unable to initialize library");
96 return 2; 64 return 2;
97 } 65 }
98 mod_open(L, mod); 66 for (i = 0; mod[i].name; i++)
67 mod[i].func(L);
99 return 1; 68 return 1;
100} 69}
diff --git a/src/mime.c b/src/mime.c
index fe24f9b..7a2baae 100644
--- a/src/mime.c
+++ b/src/mime.c
@@ -74,15 +74,15 @@ static UC b64unbase[256];
74/*-------------------------------------------------------------------------*\ 74/*-------------------------------------------------------------------------*\
75* Initializes module 75* Initializes module
76\*-------------------------------------------------------------------------*/ 76\*-------------------------------------------------------------------------*/
77int mime_open(lua_State *L) 77int luaopen_mime(lua_State *L)
78{ 78{
79 lua_pushstring(L, "mime"); 79 lua_pushstring(L, MIME_LIBNAME);
80 lua_newtable(L); 80 lua_setglobal(L, "MIME_LIBNAME");
81 luaL_openlib(L, NULL, func, 0); 81 luaL_openlib(L, MIME_LIBNAME, func, 0);
82 lua_settable(L, LUA_GLOBALSINDEX);
83 /* initialize lookup tables */ 82 /* initialize lookup tables */
84 qpsetup(qpclass, qpunbase); 83 qpsetup(qpclass, qpunbase);
85 b64setup(b64unbase); 84 b64setup(b64unbase);
85 lua_pop(L, 1);
86 return 0; 86 return 0;
87} 87}
88 88
diff --git a/src/mime.h b/src/mime.h
index b91f735..fee4e5e 100644
--- a/src/mime.h
+++ b/src/mime.h
@@ -12,6 +12,13 @@
12\*=========================================================================*/ 12\*=========================================================================*/
13#include <lua.h> 13#include <lua.h>
14 14
15int mime_open(lua_State *L); 15int luaopen_mime(lua_State *L);
16
17/*-------------------------------------------------------------------------*\
18* Library's namespace
19\*-------------------------------------------------------------------------*/
20#ifndef MIME_LIBNAME
21#define MIME_LIBNAME "mime"
22#endif
16 23
17#endif /* MIME_H */ 24#endif /* MIME_H */
diff --git a/src/mime.lua b/src/mime.lua
index 37756c7..8f2cfff 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -1,6 +1,27 @@
1if not ltn12 then error('Requires LTN12 module') end 1-----------------------------------------------------------------------------
2-- create mime namespace 2-- MIME support for the Lua language.
3mime = mime or {} 3-- Author: Diego Nehab
4-- Conforming to RFCs 2045-2049
5-- RCS ID: $Id$
6-----------------------------------------------------------------------------
7
8-----------------------------------------------------------------------------
9-- Load MIME from dynamic library
10-- Comment these lines if you are loading static
11-----------------------------------------------------------------------------
12open, err1, err2 = loadlib("mime", "luaopen_mime")
13if not open then error(err1) end
14open()
15if not MIME_LIBNAME then error("MIME init failed") end
16
17-----------------------------------------------------------------------------
18-- Namespace independence
19-----------------------------------------------------------------------------
20local mime = _G[MIME_LIBNAME]
21if not mime then error('MIME init FAILED') end
22
23require("ltn12")
24
4-- make all module globals fall into mime namespace 25-- make all module globals fall into mime namespace
5setmetatable(mime, { __index = _G }) 26setmetatable(mime, { __index = _G })
6setfenv(1, mime) 27setfenv(1, mime)
diff --git a/src/smtp.lua b/src/smtp.lua
index 8e672a0..1d1905e 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -1,8 +1,16 @@
1-----------------------------------------------------------------------------
2-- SMTP client support for the Lua language.
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-- Conforming to RFC 2821
6-- RCS ID: $Id$
7-----------------------------------------------------------------------------
1-- make sure LuaSocket is loaded 8-- make sure LuaSocket is loaded
2if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end 9if not LUASOCKET_LIBNAME then error('module requires LuaSocket') end
3-- get LuaSocket namespace 10-- get LuaSocket namespace
4local socket = _G[LUASOCKET_LIBNAME] 11local socket = _G[LUASOCKET_LIBNAME]
5if not socket then error('module requires LuaSocket') end 12if not socket then error('module requires LuaSocket') end
13
6-- create smtp namespace inside LuaSocket namespace 14-- create smtp namespace inside LuaSocket namespace
7local smtp = socket.smtp or {} 15local smtp = socket.smtp or {}
8socket.smtp = smtp 16socket.smtp = smtp
@@ -20,11 +28,6 @@ DOMAIN = os.getenv("SERVER_NAME") or "localhost"
20-- default time zone (means we don't know) 28-- default time zone (means we don't know)
21ZONE = "-0000" 29ZONE = "-0000"
22 30
23
24local function shift(a, b, c)
25 return b, c
26end
27
28-- high level stuffing filter 31-- high level stuffing filter
29function stuff() 32function stuff()
30 return ltn12.filter.cycle(dot, 2) 33 return ltn12.filter.cycle(dot, 2)
@@ -82,6 +85,7 @@ function metat.__index:send(mailt)
82end 85end
83 86
84function open(server, port) 87function open(server, port)
88 print(server or SERVER, port or PORT)
85 local tp, error = socket.tp.connect(server or SERVER, port or PORT) 89 local tp, error = socket.tp.connect(server or SERVER, port or PORT)
86 if not tp then return nil, error end 90 if not tp then return nil, error end
87 return setmetatable({tp = tp}, metat) 91 return setmetatable({tp = tp}, metat)
@@ -180,17 +184,15 @@ function message(mesgt)
180 adjust_headers(mesgt) 184 adjust_headers(mesgt)
181 -- create and return message source 185 -- create and return message source
182 local co = coroutine.create(function() send_message(mesgt) end) 186 local co = coroutine.create(function() send_message(mesgt) end)
183 return function() return shift(coroutine.resume(co)) end 187 return function() return socket.skip(1, coroutine.resume(co)) end
184end 188end
185 189
186--------------------------------------------------------------------------- 190---------------------------------------------------------------------------
187-- High level SMTP API 191-- High level SMTP API
188----------------------------------------------------------------------------- 192-----------------------------------------------------------------------------
189send = socket.protect(function(mailt) 193send = socket.protect(function(mailt)
190 local server = mailt.server or SERVER 194 local smtp = socket.try(open(mailt.server, mailt.port))
191 local port = mailt.port or PORT 195 smtp:greet(mailt.domain)
192 local smtp = socket.try(open(server, port))
193 smtp:greet(mailt.domain or DOMAIN)
194 smtp:send(mailt) 196 smtp:send(mailt)
195 smtp:quit() 197 smtp:quit()
196 return smtp:close() 198 return smtp:close()
diff --git a/src/tp.lua b/src/tp.lua
index 4f2a615..b671e58 100644
--- a/src/tp.lua
+++ b/src/tp.lua
@@ -20,20 +20,20 @@ TIMEOUT = 60
20 20
21-- gets server reply (works for SMTP and FTP) 21-- gets server reply (works for SMTP and FTP)
22local function get_reply(control) 22local function get_reply(control)
23 local code, current, separator, _ 23 local code, current, sep
24 local line, err = control:receive() 24 local line, err = control:receive()
25 local reply = line 25 local reply = line
26 if err then return nil, err end 26 if err then return nil, err end
27 _, _, code, separator = string.find(line, "^(%d%d%d)(.?)") 27 code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
28 if not code then return nil, "invalid server reply" end 28 if not code then return nil, "invalid server reply" end
29 if separator == "-" then -- reply is multiline 29 if sep == "-" then -- reply is multiline
30 repeat 30 repeat
31 line, err = control:receive() 31 line, err = control:receive()
32 if err then return nil, err end 32 if err then return nil, err end
33 _,_, current, separator = string.find(line, "^(%d%d%d)(.?)") 33 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
34 reply = reply .. "\n" .. line 34 reply = reply .. "\n" .. line
35 -- reply ends with same code 35 -- reply ends with same code
36 until code == current and separator == " " 36 until code == current and sep == " "
37 end 37 end
38 return code, reply 38 return code, reply
39end 39end
diff --git a/src/url.lua b/src/url.lua
index 2b9e4dc..0fba14d 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -125,7 +125,7 @@ function parse(url, default)
125 -- initialize default parameters 125 -- initialize default parameters
126 local parsed = default or {} 126 local parsed = default or {}
127 -- empty url is parsed to nil 127 -- empty url is parsed to nil
128 if not url or url == "" then return nil end 128 if not url or url == "" then return nil, "invalid url" end
129 -- remove whitespace 129 -- remove whitespace
130 -- url = string.gsub(url, "%s", "") 130 -- url = string.gsub(url, "%s", "")
131 -- get fragment 131 -- get fragment
diff --git a/test/httptest.lua b/test/httptest.lua
index c16ef2b..d237547 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -3,6 +3,10 @@
3-- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi 3-- needs ScriptAlias from /home/c/diego/tec/luasocket/test/cgi
4-- to "/luasocket-test-cgi" and "/luasocket-test-cgi/" 4-- to "/luasocket-test-cgi" and "/luasocket-test-cgi/"
5-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth 5-- needs "AllowOverride AuthConfig" on /home/c/diego/tec/luasocket/test/auth
6
7require("luasocket")
8require("http")
9
6dofile("testsupport.lua") 10dofile("testsupport.lua")
7 11
8local host, proxy, request, response, index_file 12local host, proxy, request, response, index_file