mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-26 04:28:20 +01:00
f960b3872a
Documented headers.lua Update copyright date everywhere Remove RCSID from files Move version back to 2.1 rather than 2.1.1 Fixed url package to support ipv6 hosts Changed "domain" to "family" in tcp and udp structures Implemented getfamily methods
152 lines
4.6 KiB
Lua
152 lines
4.6 KiB
Lua
-----------------------------------------------------------------------------
|
|
-- Little program to download DICT word definitions
|
|
-- LuaSocket sample files
|
|
-- Author: Diego Nehab
|
|
-----------------------------------------------------------------------------
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Load required modules
|
|
-----------------------------------------------------------------------------
|
|
local base = _G
|
|
local string = require("string")
|
|
local table = require("table")
|
|
local socket = require("socket")
|
|
local url = require("socket.url")
|
|
local tp = require("socket.tp")
|
|
module("socket.dict")
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Globals
|
|
-----------------------------------------------------------------------------
|
|
HOST = "dict.org"
|
|
PORT = 2628
|
|
TIMEOUT = 10
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Low-level dict API
|
|
-----------------------------------------------------------------------------
|
|
local metat = { __index = {} }
|
|
|
|
function open(host, port)
|
|
local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
|
|
return base.setmetatable({tp = tp}, metat)
|
|
end
|
|
|
|
function metat.__index:greet()
|
|
return socket.try(self.tp:check(220))
|
|
end
|
|
|
|
function metat.__index:check(ok)
|
|
local code, status = socket.try(self.tp:check(ok))
|
|
return code,
|
|
base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
|
|
end
|
|
|
|
function metat.__index:getdef()
|
|
local line = socket.try(self.tp:receive())
|
|
local def = {}
|
|
while line ~= "." do
|
|
table.insert(def, line)
|
|
line = socket.try(self.tp:receive())
|
|
end
|
|
return table.concat(def, "\n")
|
|
end
|
|
|
|
function metat.__index:define(database, word)
|
|
database = database or "!"
|
|
socket.try(self.tp:command("DEFINE", database .. " " .. word))
|
|
local code, count = self:check(150)
|
|
local defs = {}
|
|
for i = 1, count do
|
|
self:check(151)
|
|
table.insert(defs, self:getdef())
|
|
end
|
|
self:check(250)
|
|
return defs
|
|
end
|
|
|
|
function metat.__index:match(database, strat, word)
|
|
database = database or "!"
|
|
strat = strat or "."
|
|
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
|
|
self:check(152)
|
|
local mat = {}
|
|
local line = socket.try(self.tp:receive())
|
|
while line ~= '.' do
|
|
database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
|
|
if not mat[database] then mat[database] = {} end
|
|
table.insert(mat[database], word)
|
|
line = socket.try(self.tp:receive())
|
|
end
|
|
self:check(250)
|
|
return mat
|
|
end
|
|
|
|
function metat.__index:quit()
|
|
self.tp:command("QUIT")
|
|
return self:check(221)
|
|
end
|
|
|
|
function metat.__index:close()
|
|
return self.tp:close()
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- High-level dict API
|
|
-----------------------------------------------------------------------------
|
|
local default = {
|
|
scheme = "dict",
|
|
host = "dict.org"
|
|
}
|
|
|
|
local function there(f)
|
|
if f == "" then return nil
|
|
else return f end
|
|
end
|
|
|
|
local function parse(u)
|
|
local t = socket.try(url.parse(u, default))
|
|
socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'")
|
|
socket.try(t.path, "invalid path in url")
|
|
local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$"))
|
|
socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'")
|
|
socket.try(arg and arg ~= "", "need at least <word> in URL")
|
|
t.command, t.argument = cmd, arg
|
|
arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
|
|
socket.try(t.word, "need at least <word> in URL")
|
|
arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
|
|
if cmd == "m" then
|
|
arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
|
|
end
|
|
string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end)
|
|
return t
|
|
end
|
|
|
|
local function tget(gett)
|
|
local con = open(gett.host, gett.port)
|
|
con:greet()
|
|
if gett.command == "d" then
|
|
local def = con:define(gett.database, gett.word)
|
|
con:quit()
|
|
con:close()
|
|
if gett.n then return def[gett.n]
|
|
else return def end
|
|
elseif gett.command == "m" then
|
|
local mat = con:match(gett.database, gett.strat, gett.word)
|
|
con:quit()
|
|
con:close()
|
|
return mat
|
|
else return nil, "invalid command" end
|
|
end
|
|
|
|
local function sget(u)
|
|
local gett = parse(u)
|
|
return tget(gett)
|
|
end
|
|
|
|
get = socket.protect(function(gett)
|
|
if base.type(gett) == "string" then return sget(gett)
|
|
else return tget(gett) end
|
|
end)
|
|
|