mirror of
https://github.com/minetest-mods/irc.git
synced 2024-12-26 17:00:17 +01:00
Rewrite
This commit is contained in:
parent
3aede000b7
commit
c7f989dd85
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,9 +1,3 @@
|
||||
Build*
|
||||
dists
|
||||
irc-*
|
||||
Build
|
||||
irc
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.tar.bz2
|
||||
*.marks
|
||||
screenshot_*.png
|
||||
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "src/LuaIRC"]
|
||||
path = src/LuaIRC
|
||||
url = https://github.com/ShadowNinja/LuaIRC.git
|
@ -1,11 +1,11 @@
|
||||
|
||||
# :mode=cmake:noTabs=true:tabSize=4:
|
||||
# :mode=cmake:
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(MINETEST_IRC C)
|
||||
|
||||
set(MINETEST_IRC_VERSION 0.1.0)
|
||||
set(MINETEST_IRC_VERSION 0.2.0)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
@ -105,14 +105,12 @@ else()
|
||||
set(lib "${CMAKE_CURRENT_BINARY_DIR}/libluasocket.so")
|
||||
endif()
|
||||
|
||||
add_custom_target(pack_mod
|
||||
add_custom_target(pack_mod ALL
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
|
||||
# LuaIRC
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/luairc/irc.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory src/luairc/irc ${dir}/irc
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/LICENSE-LuaIRC.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory src/LuaIRC ${dir}/irc
|
||||
|
||||
# luasocket
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}
|
||||
@ -124,20 +122,22 @@ add_custom_target(pack_mod
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/luasocket/socket.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/luasocket/tp.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/luasocket/url.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/LICENSE-luasocket.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/luasocket/LICENSE.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${lib} ${dir}
|
||||
|
||||
# IRC mod
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/init.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/hooks.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/messages.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/config.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/callback.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/friends.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/chatcmds.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/botcmds.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/player_part.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/util.lua ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy README.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/API.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/LICENSE.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/CHANGES.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy doc/TODO.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/API.txt ${dir}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy src/LICENSE.txt ${dir}
|
||||
)
|
||||
|
||||
|
125
README.txt
125
README.txt
@ -17,75 +17,78 @@ Make sure you have CMake (http://cmake.org/), and of course, a C compiler,
|
||||
For Windows, try MinGW32 (http://mingw.org/).
|
||||
For Unix-based systems, you should not have any problems with the C compiler
|
||||
since there's one (almost) always available. Puppy Linux users of course
|
||||
need a separate `devx.sfs' (from the same place where you got the Puppy
|
||||
ISO), since vanilla Puppy does not come with `gcc'. See your Puppy docs for
|
||||
need a separate 'devx.sfs' (from the same place where you got the Puppy
|
||||
ISO), since vanilla Puppy does not come with 'gcc'. See your Puppy docs for
|
||||
more info about how to install additional SFS files.
|
||||
|
||||
Quick one line build for linux.
|
||||
|
||||
git clone https://github.com/kaeza/minetest-irc.git && cd minetest-irc && mkdir build && cd build && cmake .. && make && make pack_mod && cp -R irc <your mod directory>
|
||||
Please change the "cp -R irc" to fit your install of minetest.
|
||||
git clone https://github.com/kaeza/minetest-irc.git && cd minetest-irc && git submodule update --init && ./quick_install.sh <mod directory>
|
||||
Please change <mod directory> to fit your install of minetest.
|
||||
|
||||
To compile and "pack" the mod:
|
||||
To compile and pack the mod:
|
||||
|
||||
- Open a command prompt/terminal and CD to the minetest-irc directory.
|
||||
- Create a directory named "Build", and CD into it:
|
||||
- (optional) Create a directory named "Build", and CD into it:
|
||||
mkdir Build
|
||||
cd Build
|
||||
- Run CMake to generate the build system (see your CMake docs for more
|
||||
information about command line options, in particular the `-G' option).
|
||||
cmake ..
|
||||
information about command line options, in particular the '-G' option).
|
||||
cmake . (cmake .. if you made a seperate build directory)
|
||||
- Use the build tool for the generated build system to compile the
|
||||
native library. For example, if using Microsoft Visual Studio, open
|
||||
the generated workspace and build from there. If using make, just run
|
||||
"make" from within the Build directory.
|
||||
- Again use the build tool to invoke the `pack_mod' target. For example,
|
||||
if using `make', run "make pack_mod" from within the build directory.
|
||||
This will create an `irc' directory inside the build directory.
|
||||
This `irc' directory will be ready to be deployed to your Minetest mods
|
||||
directory.
|
||||
- After building you will have a folder named 'irc' in your build folder.
|
||||
Move that to your mod folder.
|
||||
|
||||
|
||||
INSTALLING
|
||||
----------
|
||||
Just put the created `irc' directory in any of the directories where
|
||||
Just put the created 'irc' directory in any of the directories where
|
||||
Minetest looks for mods. For more information, see:
|
||||
http://wiki.minetest.com/wiki/Installing_mods
|
||||
|
||||
|
||||
SETTINGS
|
||||
--------
|
||||
All settings are changed in the `config.lua' file. If any of these settings
|
||||
are either nil or false, the default value is used.
|
||||
All settings are changed in 'minetest.conf'. If any of these settings
|
||||
are either not set or false, the default value is used.
|
||||
|
||||
mt_irc.server (string, default "irc.freenode.net")
|
||||
irc.server (string, default "irc.freenode.net")
|
||||
This is the IRC server the mod connects to.
|
||||
|
||||
mt_irc.channel (string, default "##mt-irc-mod")
|
||||
irc.channel (string, default "##mt-irc-mod")
|
||||
The IRC channel to join.
|
||||
|
||||
mt_irc.dtime (number, default 0.2)
|
||||
This is the time in seconds between updates in the connection.
|
||||
In order not to block the game, the mod must periodically "poll"
|
||||
the connection to both send messages to, and receive messages
|
||||
from the channel. A high value means slower connection to IRC,
|
||||
but possibly better response from the game. A low value means
|
||||
the mod "polls" the connection more often, but can make the
|
||||
game hang. It allows fractional values.
|
||||
irc.interval (number, default 2.0)
|
||||
This prevents the server from flooding. It should be at
|
||||
least 2.0 but can be higher. After four messages this much
|
||||
time must pass between folowing messages.
|
||||
|
||||
mt_irc.timeout (number, default 60.0)
|
||||
irc.timeout (number, default 60.0)
|
||||
Underlying socket timeout in seconds. This is the time before
|
||||
the system drops an idle connection.
|
||||
|
||||
mt_irc.server_nick (string, default "minetest-"..<server-id>)
|
||||
irc.nick (string, default "minetest-"..<server-id>)
|
||||
Nickname used as "proxy" for the in-game chat.
|
||||
"<server-id>" is the server IP address packed as a 32 bit integer.
|
||||
(Currently, it's just a random 32 bit number).
|
||||
"<server-id>" is a random 32 bit number.
|
||||
|
||||
mt_irc.password (string, default "")
|
||||
irc.password (string, default "")
|
||||
Password to use when connecting to the server.
|
||||
|
||||
mt_irc.message_format_out (string, default "<$(name)> $(message)")
|
||||
irc.NSPass (string, default nil)
|
||||
NickServ password. Don't use this if you use SASL authentication.
|
||||
|
||||
irc.SASLPass (string, default nil)
|
||||
SASL password, same as nickserv password.
|
||||
You should use this instead of NickServ authentication
|
||||
if the server supports it.
|
||||
|
||||
irc.SASLUser (string, default irc.nick)
|
||||
The SASL username. This should normaly be set to your main NickServ account name.
|
||||
|
||||
irc.format_out (string, default "<$(name)> $(message)")
|
||||
This specifies how to send the messages from in-game to IRC.
|
||||
The strings can contain "macros" (or variable substitutions), which
|
||||
are specified as "$(macro_name)".
|
||||
@ -102,7 +105,7 @@ All settings are changed in the `config.lua' file. If any of these settings
|
||||
...will yield...
|
||||
"mtuser: Hello! $(xyz)"
|
||||
|
||||
mt_irc.message_format_in (string,
|
||||
irc.format_in (string,
|
||||
default "<$(name)@IRC> $(message)")
|
||||
This specifies how the messages gotten from the IRC channel are
|
||||
displayed in-game.
|
||||
@ -115,19 +118,19 @@ All settings are changed in the `config.lua' file. If any of these settings
|
||||
$(port) The IRC server port.
|
||||
$(channel) The IRC channel.
|
||||
In the default configuration, this will yield:
|
||||
<mtuser@IRC[#minetest-irc-testing]> Hello!
|
||||
<IRCUser@IRC> Hello!
|
||||
|
||||
mt_irc.debug (boolean, default false)
|
||||
irc.debug (boolean, default false)
|
||||
Whether to output debug information.
|
||||
|
||||
mt_irc.auto_connect (boolean, default false)
|
||||
If true, the bot is connected by default. If false, a player with
|
||||
`irc_admin' privilege has to use the /irc_connect command to
|
||||
irc.disable_auto_connect (boolean, default false)
|
||||
If false, the bot is connected by default. If true, a player with
|
||||
the 'irc_admin' privilege has to use the /irc_connect command to
|
||||
connect to the server.
|
||||
|
||||
mt_irc.auto_join (boolean, default false)
|
||||
If true, players join the channel automatically upon entering the
|
||||
game. If false, each user must manually use the /join command to
|
||||
irc.disable_auto_join (boolean, default false)
|
||||
If false, players join the channel automatically upon entering the
|
||||
game. If true, each user must manually use the /join command to
|
||||
join the channel. In any case, the players may use the /part
|
||||
command to opt-out of being in the channel.
|
||||
|
||||
@ -140,8 +143,8 @@ Once the game is connected to the IRC channel, chatting using the 'T' or
|
||||
|
||||
This mod also adds a few chat commands:
|
||||
|
||||
/msg <nick> <message>
|
||||
Sends a private message to the IRC user whose nickname is `nick'.
|
||||
/irc_msg <nick> <message>
|
||||
Sends a private message to a IRC user.
|
||||
|
||||
/join
|
||||
Join the IRC channel.
|
||||
@ -153,21 +156,21 @@ This mod also adds a few chat commands:
|
||||
Connect the bot manually to the IRC network.
|
||||
|
||||
/irc_disconnect
|
||||
Disconnect the bot manually to the IRC network (this does not
|
||||
Disconnect the bot manually from the IRC network (this does not
|
||||
shutdown the game).
|
||||
|
||||
/irc_reconnect
|
||||
A combination of /irc_disconnect and /irc_connect.
|
||||
Equivilant to /irc_disconnect followed by /irc_connect.
|
||||
|
||||
You can also send private messages from IRC to in-game players, though
|
||||
it's a bit tricky.
|
||||
|
||||
To do it, you must send a private message to the bot (set with
|
||||
the `mt_irc.server_nick' option above), in the following format:
|
||||
>playername message
|
||||
For example, if there's a player named `mtuser', you can send him/her
|
||||
a private message with:
|
||||
/msg server_nick >mtuser Hello!
|
||||
the 'irc.nick' option above), in the following format:
|
||||
@playername message
|
||||
For example, if there's a player named 'mtuser', you can send him/her
|
||||
a private message from IRC with:
|
||||
/msg server_nick @mtuser Hello!
|
||||
|
||||
To avoid possible misunderstandings (since all in-game players use the
|
||||
same IRC user to converse with you), the "proxy" user will reject any
|
||||
@ -175,8 +178,8 @@ To avoid possible misunderstandings (since all in-game players use the
|
||||
nice reminder as a private message.
|
||||
|
||||
The bot also supports some basic commands, which are invoked by sending
|
||||
a private message to it. Use `!help' to get a list of commands, and
|
||||
`!help <command>' to get help about a specific command.
|
||||
a private message to it. Use '!help' to get a list of commands, and
|
||||
'!help <command>' to get help about a specific command.
|
||||
|
||||
|
||||
THANKS
|
||||
@ -184,10 +187,11 @@ THANKS
|
||||
I'd like to thank the users who supported this mod both on the Minetest
|
||||
Forums and on the #minetest channel. In no particular order:
|
||||
|
||||
Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, vortexlabs/mrtux,
|
||||
marveidemanis, marktraceur, jmf/john_minetest, sdzen/Muadtralk,
|
||||
VanessaE, PilzAdam, sfan5, celeron55, KikaRz, OldCoder, RealBadAngel,
|
||||
and all the people who commented in the forum topic. Thanks to you all!
|
||||
0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio,
|
||||
vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john_minetest,
|
||||
sdzen/Muadtralk, VanessaE, PilzAdam, sfan5, celeron55, KikaRz,
|
||||
OldCoder, RealBadAngel, and all the people who commented in the
|
||||
forum topic. Thanks to you all!
|
||||
|
||||
|
||||
LICENSE
|
||||
@ -206,11 +210,8 @@ LICENSE
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
The files `http.lua', `ltn12.lua', `mime.lua', `smtp.lua', `socket.lua',
|
||||
and `url.lua' are part of the luasocket project
|
||||
(http://luasocket.luaforge.org/). See `LICENSE-luasocket.txt' for
|
||||
The files 'http.lua', 'ltn12.lua', 'mime.lua', 'smtp.lua', 'socket.lua',
|
||||
and 'url.lua' are part of the luasocket project
|
||||
(http://luasocket.luaforge.org/). See 'src/luasocket/LICENSE.txt' for
|
||||
licensing information.
|
||||
|
||||
The `irc.lua' file and the entire contents of the `irc' directory are part
|
||||
of the LuaIRC project (http://luairc.luaforge.org/). See
|
||||
`LICENSE-LuaIRC.txt' for licensing information.
|
||||
|
141
doc/API.txt
141
doc/API.txt
@ -1,141 +0,0 @@
|
||||
|
||||
IRC Mod API
|
||||
-----------
|
||||
This file documents the API exported by the IRC mod.
|
||||
|
||||
|
||||
BASICS
|
||||
------
|
||||
In order to allow your mod to interface with this mod, you must add `irc'
|
||||
(without the quotes) to your mod's `depends.txt' file.
|
||||
|
||||
|
||||
REFERENCE
|
||||
---------
|
||||
|
||||
mt_irc.say ( [name ,] message )
|
||||
Sends <message> to either the channel (if <name> is nil or not specified),
|
||||
or to the given user (if <name> is specified).
|
||||
Example:
|
||||
mt_irc.say("Hello, Channel!")
|
||||
mt_irc.say("john1234", "How are you?")
|
||||
|
||||
mt_irc.register_bot_command ( name, cmddef )
|
||||
Registers a new bot command named <name>.
|
||||
When an user sends a private message to the bot starting with `!name', the
|
||||
command's function is called.
|
||||
Here's the command definition (<cmddef>):
|
||||
cmddef = {
|
||||
params = "<param1> ...", -- A short help text for !help
|
||||
description = "My command", -- What does the command? (one-liner)
|
||||
func = function ( from, param )
|
||||
-- This function gets called when the command is invoked.
|
||||
-- <from> is the name of the user that invoked the command.
|
||||
-- <param> is the rest of the input (after removing !command)
|
||||
end,
|
||||
};
|
||||
Example:
|
||||
mt_irc.register_bot_command("hello", {
|
||||
params = nil, -- No params
|
||||
description = "Greet user",
|
||||
func = function ( from, param )
|
||||
mt_irc.say(from, "Hello!")
|
||||
end,
|
||||
});
|
||||
|
||||
mt_irc.connected_players [ name ]
|
||||
This table holds the players who are currently on the channel (may be less
|
||||
than the players in the game). It is modified by the /part and /join chat
|
||||
commands.
|
||||
Example:
|
||||
if (mt_irc.connected_players["joe"]) then
|
||||
-- Joe is talking on IRC
|
||||
end
|
||||
|
||||
mt_irc.register_callback ( name, func )
|
||||
Registers a function to be called when an event happens. <name> is the name
|
||||
of the event, and <func> is the function to be called. See CALLBACKS below
|
||||
for more information
|
||||
Example:
|
||||
mt_irc.register_callback("channel_msg", function ( from, msg )
|
||||
if (from == "joe") then
|
||||
mt_irc.say("joe", "You are not allowed to do that!")
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
This mod also supplies some utility functions:
|
||||
|
||||
string.expandvars ( string, vars )
|
||||
Expands all occurrences of the pattern "$(varname)" with the value of
|
||||
`varname' in the <vars> table. Variable names not found on the table
|
||||
are left verbatim in the string.
|
||||
Example:
|
||||
local tpl = "$(foo) $(bar) $(baz)"
|
||||
local s = tpl:expandvars({ foo=1, bar="Hello" })
|
||||
-- `s' now contains "1 Hello $(baz)"
|
||||
|
||||
In addition, all the configuration options decribed in `README.txt' are
|
||||
available to other mods, though they should be considered "read only". Do
|
||||
not modify these settings at runtime or you will most likely crash the
|
||||
server!
|
||||
|
||||
|
||||
CALLBACKS
|
||||
---------
|
||||
The `mt_irc.register_callback' function can register functions to be called
|
||||
when some events happen. These are the events supported:
|
||||
|
||||
msg_out ( from, message )
|
||||
Called right before the bot sends a message to the channel.
|
||||
<from> is the name of the user sending the message. <message> is the
|
||||
unmodified message sent by the user.
|
||||
Return values:
|
||||
"string" New message to be sent.
|
||||
false Filter out the message (do not send anything).
|
||||
nil Use original message
|
||||
other Use a string repr of the value as message.
|
||||
Example:
|
||||
mt_irc.register_callback("msg_out", function ( from, msg )
|
||||
if (from == "joe") then
|
||||
mt_irc.say("joe", "You are not allowed to do that!")
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
msg_in ( from, to, message )
|
||||
Called right before the bot sends a private message to an user.
|
||||
<from> is the name of the user sending the message. <to> is the recipient
|
||||
of the message. <message> is the unmodified message sent by the user.
|
||||
Return values:
|
||||
"string" New message to be sent.
|
||||
false Filter out the message (do not send anything).
|
||||
nil Use original message
|
||||
other Use a string repr of the value as message.
|
||||
Example:
|
||||
mt_irc.register_callback("msg_in", function ( from, to, msg )
|
||||
if (to == "admin") then
|
||||
mt_irc.say(from, "You are not allowed to do that!")
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
nick_change ( old_nick, new_nick )
|
||||
Called when an user in IRC changes nickname.
|
||||
<old_nick> and <new_nick> are self-explanatory.
|
||||
Return value:
|
||||
none
|
||||
Example:
|
||||
mt_irc.register_callback("nick_change", function ( old_nick, new_nick )
|
||||
mt_irc.say(from, "Hello "..new_nick.."! You were "..old_nick.."?")
|
||||
end)
|
||||
|
||||
part ( nick, part_msg )
|
||||
Called when an user leaves the IRC channel.
|
||||
<nick> is the user leaving; <part_msg> is the "parting message".
|
||||
Return value:
|
||||
none
|
||||
Example:
|
||||
mt_irc.register_callback("part", function ( nick, part_msg )
|
||||
mt_irc.say(from, nick.." has left the building!")
|
||||
end)
|
@ -1,37 +0,0 @@
|
||||
|
||||
Version 0.1.2:
|
||||
- Fixed the Quit: Excess Flood bug.
|
||||
- Removed the `packmod' scripts in favor of a dedicated CMake target.
|
||||
- Fixed packaging of mod under MinGW32.
|
||||
- Export some basic API so other mods may use the connection to send
|
||||
messages, etc.
|
||||
- Added /irc_disconnect and /irc_reconnect chat commands.
|
||||
- Added some basic documentation about the API exported by this mod.
|
||||
More coming soon.
|
||||
- Added automatic reconnection in case the bot is kicked from the
|
||||
channel.
|
||||
- Fixed delay while the bot waits for the Message Of The Day (or topic)
|
||||
- Fixed bug where players were able to send messages to the channel
|
||||
even if they had no `shout' priv.
|
||||
|
||||
Version 0.1.1:
|
||||
- Moved all user configuration to `config.lua'.
|
||||
- Added formatted messages for sent and received messages and options
|
||||
to change them.
|
||||
- Added options to change port, password.
|
||||
- Added support for sending/receiving private messages.
|
||||
- Removed need for separate packmod.{sh|bat} scripts. Now everything
|
||||
is (almost) nicely handled by CMake.
|
||||
- Now all sources (including Lua itself) are added to a single
|
||||
luasocket lib. This will hopefully fix some cases where the linker
|
||||
b0rk3d with undefined references under Linux.
|
||||
- Added option to enable/disable connecting when starting the game, and
|
||||
the /irc_connect chat command to connect manually to the server (as
|
||||
suggested by OldCoder). The /irc_connect chat command requires the
|
||||
`irc_admin' privilege.
|
||||
- Added option to enable/disable joining the channel when a player joins,
|
||||
and the /join and /part chat commands to join and part the channel
|
||||
manually if desired (as suggested by OldCoder).
|
||||
|
||||
Version 0.1.0:
|
||||
- At least it's working :)
|
@ -1,7 +0,0 @@
|
||||
Copyright (c) 2007 Jesse Luehrs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,15 +0,0 @@
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
20
doc/TODO.txt
20
doc/TODO.txt
@ -1,20 +0,0 @@
|
||||
|
||||
TODO List
|
||||
---------
|
||||
|
||||
- Check for availability of nickname on join, and select a different one
|
||||
until one is available.
|
||||
- Implement more callbacks for `mt_irc.register_callback'.
|
||||
|
||||
Not TODO List
|
||||
-------------
|
||||
* These things either WON'T BE SUPPORTED, or have VERY LOW priority.
|
||||
|
||||
- Support for sending CTCP queries (LuaIRC seems to handle incoming
|
||||
queries internally by default).
|
||||
|
||||
Known Bugs
|
||||
----------
|
||||
|
||||
- Apparently, some users have to install `luasocket' separately, since
|
||||
the provided one won't compile/work (reported by leo_rockway).
|
@ -1,405 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua 5.1 reference manual - contents</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<HR>
|
||||
<H1>
|
||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A>
|
||||
Lua 5.1 Reference Manual
|
||||
</H1>
|
||||
|
||||
<SMALL>
|
||||
<A HREF="http://www.lua.org/copyright.html">Copyright</A>
|
||||
© 2006 Lua.org, PUC-Rio. All rights reserved.
|
||||
</SMALL>
|
||||
<HR>
|
||||
|
||||
<H2>Contents</H2>
|
||||
<UL>
|
||||
<LI><A HREF="#quick">Quick index</A>
|
||||
<P>
|
||||
<LI><A HREF="manual.html">Top</A>
|
||||
<LI><A HREF="manual.html#1">1 - Introduction</A>
|
||||
<LI><A HREF="manual.html#2">2 - The Language</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.1">2.1 - Lexical Conventions</A>
|
||||
<LI><A HREF="manual.html#2.2">2.2 - Values and Types</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.2.1">2.2.1 - Coercion</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.3">2.3 - Variables</A>
|
||||
<LI><A HREF="manual.html#2.4">2.4 - Statements</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.4.1">2.4.1 - Chunks</A>
|
||||
<LI><A HREF="manual.html#2.4.2">2.4.2 - Blocks</A>
|
||||
<LI><A HREF="manual.html#2.4.3">2.4.3 - Assignment</A>
|
||||
<LI><A HREF="manual.html#2.4.4">2.4.4 - Control Structures</A>
|
||||
<LI><A HREF="manual.html#2.4.5">2.4.5 - For Statement</A>
|
||||
<LI><A HREF="manual.html#2.4.6">2.4.6 - Function Calls as Statements</A>
|
||||
<LI><A HREF="manual.html#2.4.7">2.4.7 - Local Declarations</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.5">2.5 - Expressions</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.5.1">2.5.1 - Arithmetic Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.2">2.5.2 - Relational Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.3">2.5.3 - Logical Operators</A>
|
||||
<LI><A HREF="manual.html#2.5.4">2.5.4 - Concatenation</A>
|
||||
<LI><A HREF="manual.html#2.5.5">2.5.5 - The Length Operator</A>
|
||||
<LI><A HREF="manual.html#2.5.6">2.5.6 - Precedence</A>
|
||||
<LI><A HREF="manual.html#2.5.7">2.5.7 - Table Constructors</A>
|
||||
<LI><A HREF="manual.html#2.5.8">2.5.8 - Function Calls</A>
|
||||
<LI><A HREF="manual.html#2.5.9">2.5.9 - Function Definitions</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.6">2.6 - Visibility Rules</A>
|
||||
<LI><A HREF="manual.html#2.7">2.7 - Error Handling</A>
|
||||
<LI><A HREF="manual.html#2.8">2.8 - Metatables</A>
|
||||
<LI><A HREF="manual.html#2.9">2.9 - Environments</A>
|
||||
<LI><A HREF="manual.html#2.10">2.10 - Garbage Collection</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#2.10.1">2.10.1 - Garbage-Collection Metamethods</A>
|
||||
<LI><A HREF="manual.html#2.10.2">2.10.2 - Weak Tables</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#2.11">2.11 - Coroutines</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#3">3 - The Application Program Interface</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#3.1">3.1 - The Stack</A>
|
||||
<LI><A HREF="manual.html#3.2">3.2 - Stack Size</A>
|
||||
<LI><A HREF="manual.html#3.3">3.3 - Pseudo-Indices</A>
|
||||
<LI><A HREF="manual.html#3.4">3.4 - C Closures</A>
|
||||
<LI><A HREF="manual.html#3.5">3.5 - Registry</A>
|
||||
<LI><A HREF="manual.html#3.6">3.6 - Error Handling in C</A>
|
||||
<LI><A HREF="manual.html#3.7">3.7 - Functions and Types</A>
|
||||
<LI><A HREF="manual.html#3.8">3.8 - The Debug Interface</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#4">4 - The Auxiliary Library</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#4.1">4.1 - Functions and Types</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#5">5 - Standard Libraries</A>
|
||||
<UL>
|
||||
<LI><A HREF="manual.html#5.1">5.1 - Basic Functions</A>
|
||||
<LI><A HREF="manual.html#5.2">5.2 - Coroutine Manipulation</A>
|
||||
<LI><A HREF="manual.html#5.3">5.3 - Modules</A>
|
||||
<LI><A HREF="manual.html#5.4">5.4 - String Manipulation</A>
|
||||
<LI><A HREF="manual.html#5.5">5.5 - Table Manipulation</A>
|
||||
<LI><A HREF="manual.html#5.6">5.6 - Mathematical Functions</A>
|
||||
<LI><A HREF="manual.html#5.7">5.7 - Input and Output Facilities</A>
|
||||
<LI><A HREF="manual.html#5.8">5.8 - Operating System Facilities</A>
|
||||
<LI><A HREF="manual.html#5.9">5.9 - The Debug Library</A>
|
||||
</UL>
|
||||
<LI><A HREF="manual.html#6">6 - Lua Stand-alone</A>
|
||||
<LI><A HREF="manual.html#incompat">Incompatibilities with the Previous Version</A>
|
||||
<LI><A HREF="manual.html#BNF">The Complete Syntax of Lua</A>
|
||||
|
||||
</UL>
|
||||
|
||||
<H2><A NAME="quick">Quick index</A></H2>
|
||||
<TABLE>
|
||||
<TR VALIGN="top">
|
||||
<TD WIDTH="35%">
|
||||
<H3><A NAME="functions">Functions</A></H3>
|
||||
<A HREF="manual.html#pdf-_G">_G</A><BR>
|
||||
<A HREF="manual.html#pdf-_VERSION">_VERSION</A><BR>
|
||||
<A HREF="manual.html#pdf-assert">assert</A><BR>
|
||||
<A HREF="manual.html#pdf-collectgarbage">collectgarbage</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.create">coroutine.create</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.resume">coroutine.resume</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.running">coroutine.running</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.status">coroutine.status</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.wrap">coroutine.wrap</A><BR>
|
||||
<A HREF="manual.html#pdf-coroutine.yield">coroutine.yield</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.debug">debug.debug</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getfenv">debug.getfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.gethook">debug.gethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getinfo">debug.getinfo</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getlocal">debug.getlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getmetatable">debug.getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setfenv">debug.setfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.setupvalue">debug.setupvalue</A><BR>
|
||||
<A HREF="manual.html#pdf-debug.traceback">debug.traceback</A><BR>
|
||||
<A HREF="manual.html#pdf-dofile">dofile</A><BR>
|
||||
<A HREF="manual.html#pdf-error">error</A><BR>
|
||||
<A HREF="manual.html#pdf-file:close">file:close</A><BR>
|
||||
<A HREF="manual.html#pdf-file:flush">file:flush</A><BR>
|
||||
<A HREF="manual.html#pdf-file:lines">file:lines</A><BR>
|
||||
<A HREF="manual.html#pdf-file:read">file:read</A><BR>
|
||||
<A HREF="manual.html#pdf-file:seek">file:seek</A><BR>
|
||||
<A HREF="manual.html#pdf-file:setvbuf">file:setvbuf</A><BR>
|
||||
<A HREF="manual.html#pdf-file:write">file:write</A><BR>
|
||||
<A HREF="manual.html#pdf-getfenv">getfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-io.close">io.close</A><BR>
|
||||
<A HREF="manual.html#pdf-io.flush">io.flush</A><BR>
|
||||
<A HREF="manual.html#pdf-io.input">io.input</A><BR>
|
||||
<A HREF="manual.html#pdf-io.lines">io.lines</A><BR>
|
||||
<A HREF="manual.html#pdf-io.open">io.open</A><BR>
|
||||
<A HREF="manual.html#pdf-io.output">io.output</A><BR>
|
||||
<A HREF="manual.html#pdf-io.popen">io.popen</A><BR>
|
||||
<A HREF="manual.html#pdf-io.read">io.read</A><BR>
|
||||
<A HREF="manual.html#pdf-io.tmpfile">io.tmpfile</A><BR>
|
||||
<A HREF="manual.html#pdf-io.type">io.type</A><BR>
|
||||
<A HREF="manual.html#pdf-io.write">io.write</A><BR>
|
||||
<A HREF="manual.html#pdf-ipairs">ipairs</A><BR>
|
||||
<A HREF="manual.html#pdf-load">load</A><BR>
|
||||
<A HREF="manual.html#pdf-loadfile">loadfile</A><BR>
|
||||
<A HREF="manual.html#pdf-loadstring">loadstring</A><BR>
|
||||
<A HREF="manual.html#pdf-math.abs">math.abs</A><BR>
|
||||
<A HREF="manual.html#pdf-math.acos">math.acos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.asin">math.asin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.atan2">math.atan2</A><BR>
|
||||
<A HREF="manual.html#pdf-math.atan">math.atan</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ceil">math.ceil</A><BR>
|
||||
<A HREF="manual.html#pdf-math.cosh">math.cosh</A><BR>
|
||||
<A HREF="manual.html#pdf-math.cos">math.cos</A><BR>
|
||||
<A HREF="manual.html#pdf-math.deg">math.deg</A><BR>
|
||||
<A HREF="manual.html#pdf-math.exp">math.exp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.floor">math.floor</A><BR>
|
||||
<A HREF="manual.html#pdf-math.fmod">math.fmod</A><BR>
|
||||
<A HREF="manual.html#pdf-math.frexp">math.frexp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.ldexp">math.ldexp</A><BR>
|
||||
<A HREF="manual.html#pdf-math.log10">math.log10</A><BR>
|
||||
<A HREF="manual.html#pdf-math.log">math.log</A><BR>
|
||||
<A HREF="manual.html#pdf-math.max">math.max</A><BR>
|
||||
<A HREF="manual.html#pdf-math.min">math.min</A><BR>
|
||||
<A HREF="manual.html#pdf-math.modf">math.modf</A><BR>
|
||||
<A HREF="manual.html#pdf-math.pow">math.pow</A><BR>
|
||||
<A HREF="manual.html#pdf-math.rad">math.rad</A><BR>
|
||||
<A HREF="manual.html#pdf-math.random">math.random</A><BR>
|
||||
<A HREF="manual.html#pdf-math.randomseed">math.randomseed</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sinh">math.sinh</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sin">math.sin</A><BR>
|
||||
<A HREF="manual.html#pdf-math.sqrt">math.sqrt</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tanh">math.tanh</A><BR>
|
||||
<A HREF="manual.html#pdf-math.tan">math.tan</A><BR>
|
||||
<A HREF="manual.html#pdf-module">module</A><BR>
|
||||
<A HREF="manual.html#pdf-next">next</A><BR>
|
||||
<A HREF="manual.html#pdf-os.clock">os.clock</A><BR>
|
||||
<A HREF="manual.html#pdf-os.date">os.date</A><BR>
|
||||
<A HREF="manual.html#pdf-os.difftime">os.difftime</A><BR>
|
||||
<A HREF="manual.html#pdf-os.execute">os.execute</A><BR>
|
||||
<A HREF="manual.html#pdf-os.exit">os.exit</A><BR>
|
||||
<A HREF="manual.html#pdf-os.getenv">os.getenv</A><BR>
|
||||
<A HREF="manual.html#pdf-os.remove">os.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-os.rename">os.rename</A><BR>
|
||||
<A HREF="manual.html#pdf-os.setlocale">os.setlocale</A><BR>
|
||||
<A HREF="manual.html#pdf-os.time">os.time</A><BR>
|
||||
<A HREF="manual.html#pdf-os.tmpname">os.tmpname</A><BR>
|
||||
<A HREF="manual.html#pdf-package.cpath">package.cpath</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loaded">package.loaded</A><BR>
|
||||
<A HREF="manual.html#pdf-package.loadlib">package.loadlib</A><BR>
|
||||
<A HREF="manual.html#pdf-package.path">package.path</A><BR>
|
||||
<A HREF="manual.html#pdf-package.preload">package.preload</A><BR>
|
||||
<A HREF="manual.html#pdf-package.seeall">package.seeall</A><BR>
|
||||
<A HREF="manual.html#pdf-pairs">pairs</A><BR>
|
||||
<A HREF="manual.html#pdf-pcall">pcall</A><BR>
|
||||
<A HREF="manual.html#pdf-print">print</A><BR>
|
||||
<A HREF="manual.html#pdf-rawequal">rawequal</A><BR>
|
||||
<A HREF="manual.html#pdf-rawget">rawget</A><BR>
|
||||
<A HREF="manual.html#pdf-rawset">rawset</A><BR>
|
||||
<A HREF="manual.html#pdf-require">require</A><BR>
|
||||
<A HREF="manual.html#pdf-select">select</A><BR>
|
||||
<A HREF="manual.html#pdf-setfenv">setfenv</A><BR>
|
||||
<A HREF="manual.html#pdf-setmetatable">setmetatable</A><BR>
|
||||
<A HREF="manual.html#pdf-string.byte">string.byte</A><BR>
|
||||
<A HREF="manual.html#pdf-string.char">string.char</A><BR>
|
||||
<A HREF="manual.html#pdf-string.dump">string.dump</A><BR>
|
||||
<A HREF="manual.html#pdf-string.find">string.find</A><BR>
|
||||
<A HREF="manual.html#pdf-string.format">string.format</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gmatch">string.gmatch</A><BR>
|
||||
<A HREF="manual.html#pdf-string.gsub">string.gsub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.len">string.len</A><BR>
|
||||
<A HREF="manual.html#pdf-string.lower">string.lower</A><BR>
|
||||
<A HREF="manual.html#pdf-string.match">string.match</A><BR>
|
||||
<A HREF="manual.html#pdf-string.rep">string.rep</A><BR>
|
||||
<A HREF="manual.html#pdf-string.reverse">string.reverse</A><BR>
|
||||
<A HREF="manual.html#pdf-string.sub">string.sub</A><BR>
|
||||
<A HREF="manual.html#pdf-string.upper">string.upper</A><BR>
|
||||
<A HREF="manual.html#pdf-table.concat">table.concat</A><BR>
|
||||
<A HREF="manual.html#pdf-table.insert">table.insert</A><BR>
|
||||
<A HREF="manual.html#pdf-table.maxn">table.maxn</A><BR>
|
||||
<A HREF="manual.html#pdf-table.remove">table.remove</A><BR>
|
||||
<A HREF="manual.html#pdf-table.sort">table.sort</A><BR>
|
||||
<A HREF="manual.html#pdf-tonumber">tonumber</A><BR>
|
||||
<A HREF="manual.html#pdf-tostring">tostring</A><BR>
|
||||
<A HREF="manual.html#pdf-type">type</A><BR>
|
||||
<A HREF="manual.html#pdf-unpack">unpack</A><BR>
|
||||
<A HREF="manual.html#pdf-xpcall">xpcall</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3>API</H3>
|
||||
<A HREF="manual.html#lua_Alloc">lua_Alloc</A><BR>
|
||||
<A HREF="manual.html#lua_CFunction">lua_CFunction</A><BR>
|
||||
<A HREF="manual.html#lua_Debug">lua_Debug</A><BR>
|
||||
<A HREF="manual.html#lua_Hook">lua_Hook</A><BR>
|
||||
<A HREF="manual.html#lua_Integer">lua_Integer</A><BR>
|
||||
<A HREF="manual.html#lua_Number">lua_Number</A><BR>
|
||||
<A HREF="manual.html#lua_Reader">lua_Reader</A><BR>
|
||||
<A HREF="manual.html#lua_State">lua_State</A><BR>
|
||||
<A HREF="manual.html#lua_Writer">lua_Writer</A><BR>
|
||||
<A HREF="manual.html#lua_atpanic">lua_atpanic</A><BR>
|
||||
<A HREF="manual.html#lua_call">lua_call</A><BR>
|
||||
<A HREF="manual.html#lua_checkstack">lua_checkstack</A><BR>
|
||||
<A HREF="manual.html#lua_close">lua_close</A><BR>
|
||||
<A HREF="manual.html#lua_concat">lua_concat</A><BR>
|
||||
<A HREF="manual.html#lua_cpcall">lua_cpcall</A><BR>
|
||||
<A HREF="manual.html#lua_createtable">lua_createtable</A><BR>
|
||||
<A HREF="manual.html#lua_dump">lua_dump</A><BR>
|
||||
<A HREF="manual.html#lua_equal">lua_equal</A><BR>
|
||||
<A HREF="manual.html#lua_error">lua_error</A><BR>
|
||||
<A HREF="manual.html#lua_gc">lua_gc</A><BR>
|
||||
<A HREF="manual.html#lua_getallocf">lua_getallocf</A><BR>
|
||||
<A HREF="manual.html#lua_getfenv">lua_getfenv</A><BR>
|
||||
<A HREF="manual.html#lua_getfield">lua_getfield</A><BR>
|
||||
<A HREF="manual.html#lua_getglobal">lua_getglobal</A><BR>
|
||||
<A HREF="manual.html#lua_gethook">lua_gethook</A><BR>
|
||||
<A HREF="manual.html#lua_gethookcount">lua_gethookcount</A><BR>
|
||||
<A HREF="manual.html#lua_gethookmask">lua_gethookmask</A><BR>
|
||||
<A HREF="manual.html#lua_getinfo">lua_getinfo</A><BR>
|
||||
<A HREF="manual.html#lua_getlocal">lua_getlocal</A><BR>
|
||||
<A HREF="manual.html#lua_getmetatable">lua_getmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_getstack">lua_getstack</A><BR>
|
||||
<A HREF="manual.html#lua_gettable">lua_gettable</A><BR>
|
||||
<A HREF="manual.html#lua_gettop">lua_gettop</A><BR>
|
||||
<A HREF="manual.html#lua_getupvalue">lua_getupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_insert">lua_insert</A><BR>
|
||||
<A HREF="manual.html#lua_isboolean">lua_isboolean</A><BR>
|
||||
<A HREF="manual.html#lua_iscfunction">lua_iscfunction</A><BR>
|
||||
<A HREF="manual.html#lua_isfunction">lua_isfunction</A><BR>
|
||||
<A HREF="manual.html#lua_islightuserdata">lua_islightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_isnil">lua_isnil</A><BR>
|
||||
<A HREF="manual.html#lua_isnumber">lua_isnumber</A><BR>
|
||||
<A HREF="manual.html#lua_isstring">lua_isstring</A><BR>
|
||||
<A HREF="manual.html#lua_istable">lua_istable</A><BR>
|
||||
<A HREF="manual.html#lua_isthread">lua_isthread</A><BR>
|
||||
<A HREF="manual.html#lua_isuserdata">lua_isuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_lessthan">lua_lessthan</A><BR>
|
||||
<A HREF="manual.html#lua_load">lua_load</A><BR>
|
||||
<A HREF="manual.html#lua_newstate">lua_newstate</A><BR>
|
||||
<A HREF="manual.html#lua_newtable">lua_newtable</A><BR>
|
||||
<A HREF="manual.html#lua_newthread">lua_newthread</A><BR>
|
||||
<A HREF="manual.html#lua_newuserdata">lua_newuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_next">lua_next</A><BR>
|
||||
<A HREF="manual.html#lua_objlen">lua_objlen</A><BR>
|
||||
<A HREF="manual.html#lua_pcall">lua_pcall</A><BR>
|
||||
<A HREF="manual.html#lua_pop">lua_pop</A><BR>
|
||||
<A HREF="manual.html#lua_pushboolean">lua_pushboolean</A><BR>
|
||||
<A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR>
|
||||
<A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR>
|
||||
<A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR>
|
||||
<A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR>
|
||||
<A HREF="manual.html#lua_pushlstring">lua_pushlstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushnil">lua_pushnil</A><BR>
|
||||
<A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR>
|
||||
<A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR>
|
||||
<A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR>
|
||||
<A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR>
|
||||
<A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR>
|
||||
<A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR>
|
||||
<A HREF="manual.html#lua_rawget">lua_rawget</A><BR>
|
||||
<A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR>
|
||||
<A HREF="manual.html#lua_rawset">lua_rawset</A><BR>
|
||||
<A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR>
|
||||
<A HREF="manual.html#lua_register">lua_register</A><BR>
|
||||
<A HREF="manual.html#lua_remove">lua_remove</A><BR>
|
||||
<A HREF="manual.html#lua_replace">lua_replace</A><BR>
|
||||
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
|
||||
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
|
||||
<A HREF="manual.html#lua_setfenv">lua_setfenv</A><BR>
|
||||
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
|
||||
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
|
||||
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
|
||||
<A HREF="manual.html#lua_setlocal">lua_setlocal</A><BR>
|
||||
<A HREF="manual.html#lua_setmetatable">lua_setmetatable</A><BR>
|
||||
<A HREF="manual.html#lua_settable">lua_settable</A><BR>
|
||||
<A HREF="manual.html#lua_settop">lua_settop</A><BR>
|
||||
<A HREF="manual.html#lua_setupvalue">lua_setupvalue</A><BR>
|
||||
<A HREF="manual.html#lua_status">lua_status</A><BR>
|
||||
<A HREF="manual.html#lua_toboolean">lua_toboolean</A><BR>
|
||||
<A HREF="manual.html#lua_tocfunction">lua_tocfunction</A><BR>
|
||||
<A HREF="manual.html#lua_tointeger">lua_tointeger</A><BR>
|
||||
<A HREF="manual.html#lua_tolstring">lua_tolstring</A><BR>
|
||||
<A HREF="manual.html#lua_tonumber">lua_tonumber</A><BR>
|
||||
<A HREF="manual.html#lua_topointer">lua_topointer</A><BR>
|
||||
<A HREF="manual.html#lua_tostring">lua_tostring</A><BR>
|
||||
<A HREF="manual.html#lua_tothread">lua_tothread</A><BR>
|
||||
<A HREF="manual.html#lua_touserdata">lua_touserdata</A><BR>
|
||||
<A HREF="manual.html#lua_type">lua_type</A><BR>
|
||||
<A HREF="manual.html#lua_typename">lua_typename</A><BR>
|
||||
<A HREF="manual.html#lua_xmove">lua_xmove</A><BR>
|
||||
<A HREF="manual.html#lua_yield">lua_yield</A><BR>
|
||||
|
||||
</TD>
|
||||
<TD>
|
||||
<H3>Auxiliary library</H3>
|
||||
<A HREF="manual.html#luaL_Buffer">luaL_Buffer</A><BR>
|
||||
<A HREF="manual.html#luaL_Reg">luaL_Reg</A><BR>
|
||||
<A HREF="manual.html#luaL_addchar">luaL_addchar</A><BR>
|
||||
<A HREF="manual.html#luaL_addlstring">luaL_addlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addsize">luaL_addsize</A><BR>
|
||||
<A HREF="manual.html#luaL_addstring">luaL_addstring</A><BR>
|
||||
<A HREF="manual.html#luaL_addvalue">luaL_addvalue</A><BR>
|
||||
<A HREF="manual.html#luaL_argcheck">luaL_argcheck</A><BR>
|
||||
<A HREF="manual.html#luaL_argerror">luaL_argerror</A><BR>
|
||||
<A HREF="manual.html#luaL_buffinit">luaL_buffinit</A><BR>
|
||||
<A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR>
|
||||
<A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR>
|
||||
<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR>
|
||||
<A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR>
|
||||
<A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR>
|
||||
<A HREF="manual.html#luaL_checkoption">luaL_checkoption</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstack">luaL_checkstack</A><BR>
|
||||
<A HREF="manual.html#luaL_checkstring">luaL_checkstring</A><BR>
|
||||
<A HREF="manual.html#luaL_checktype">luaL_checktype</A><BR>
|
||||
<A HREF="manual.html#luaL_checkudata">luaL_checkudata</A><BR>
|
||||
<A HREF="manual.html#luaL_error">luaL_error</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetafield">luaL_getmetafield</A><BR>
|
||||
<A HREF="manual.html#luaL_getmetatable">luaL_getmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_gsub">luaL_gsub</A><BR>
|
||||
<A HREF="manual.html#luaL_loadbuffer">luaL_loadbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_loadfile">luaL_loadfile</A><BR>
|
||||
<A HREF="manual.html#luaL_loadstring">luaL_loadstring</A><BR>
|
||||
<A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR>
|
||||
<A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR>
|
||||
<A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR>
|
||||
<A HREF="manual.html#luaL_optint">luaL_optint</A><BR>
|
||||
<A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR>
|
||||
<A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR>
|
||||
<A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR>
|
||||
<A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR>
|
||||
<A HREF="manual.html#luaL_optstring">luaL_optstring</A><BR>
|
||||
<A HREF="manual.html#luaL_prepbuffer">luaL_prepbuffer</A><BR>
|
||||
<A HREF="manual.html#luaL_pushresult">luaL_pushresult</A><BR>
|
||||
<A HREF="manual.html#luaL_ref">luaL_ref</A><BR>
|
||||
<A HREF="manual.html#luaL_register">luaL_register</A><BR>
|
||||
<A HREF="manual.html#luaL_typename">luaL_typename</A><BR>
|
||||
<A HREF="manual.html#luaL_typerror">luaL_typerror</A><BR>
|
||||
<A HREF="manual.html#luaL_unref">luaL_unref</A><BR>
|
||||
<A HREF="manual.html#luaL_where">luaL_where</A><BR>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<SMALL>
|
||||
Last update:
|
||||
Fri Feb 10 17:15:37 BRST 2006
|
||||
</SMALL>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
BIN
doc/lua/logo.gif
BIN
doc/lua/logo.gif
Binary file not shown.
Before Width: | Height: | Size: 4.1 KiB |
163
doc/lua/lua.1
163
doc/lua/lua.1
@ -1,163 +0,0 @@
|
||||
.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
|
||||
.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
|
||||
.SH NAME
|
||||
lua \- Lua interpreter
|
||||
.SH SYNOPSIS
|
||||
.B lua
|
||||
[
|
||||
.I options
|
||||
]
|
||||
[
|
||||
.I script
|
||||
[
|
||||
.I args
|
||||
]
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B lua
|
||||
is the stand-alone Lua interpreter.
|
||||
It loads and executes Lua programs,
|
||||
either in textual source form or
|
||||
in precompiled binary form.
|
||||
(Precompiled binaries are output by
|
||||
.BR luac ,
|
||||
the Lua compiler.)
|
||||
.B lua
|
||||
can be used as a batch interpreter and also interactively.
|
||||
.LP
|
||||
The given
|
||||
.I options
|
||||
(see below)
|
||||
are executed and then
|
||||
the Lua program in file
|
||||
.I script
|
||||
is loaded and executed.
|
||||
The given
|
||||
.I args
|
||||
are available to
|
||||
.I script
|
||||
as strings in a global table named
|
||||
.BR arg .
|
||||
If these arguments contain spaces or other characters special to the shell,
|
||||
then they should be quoted
|
||||
(but note that the quotes will be removed by the shell).
|
||||
The arguments in
|
||||
.B arg
|
||||
start at 0,
|
||||
which contains the string
|
||||
.RI ' script '.
|
||||
The index of the last argument is stored in
|
||||
.BR arg.n .
|
||||
The arguments given in the command line before
|
||||
.IR script ,
|
||||
including the name of the interpreter,
|
||||
are available in negative indices in
|
||||
.BR arg .
|
||||
.LP
|
||||
At the very start,
|
||||
before even handling the command line,
|
||||
.B lua
|
||||
executes the contents of the environment variable
|
||||
.BR LUA_INIT ,
|
||||
if it is defined.
|
||||
If the value of
|
||||
.B LUA_INIT
|
||||
is of the form
|
||||
.RI '@ filename ',
|
||||
then
|
||||
.I filename
|
||||
is executed.
|
||||
Otherwise, the string is assumed to be a Lua statement and is executed.
|
||||
.LP
|
||||
Options start with
|
||||
.B '\-'
|
||||
and are described below.
|
||||
You can use
|
||||
.B "'\--'"
|
||||
to signal the end of options.
|
||||
.LP
|
||||
If no arguments are given,
|
||||
then
|
||||
.B "\-v \-i"
|
||||
is assumed when the standard input is a terminal;
|
||||
otherwise,
|
||||
.B "\-"
|
||||
is assumed.
|
||||
.LP
|
||||
In interactive mode,
|
||||
.B lua
|
||||
prompts the user,
|
||||
reads lines from the standard input,
|
||||
and executes them as they are read.
|
||||
If a line does not contain a complete statement,
|
||||
then a secondary prompt is displayed and
|
||||
lines are read until a complete statement is formed or
|
||||
a syntax error is found.
|
||||
So, one way to interrupt the reading of an incomplete statement is
|
||||
to force a syntax error:
|
||||
adding a
|
||||
.B ';'
|
||||
in the middle of a statement is a sure way of forcing a syntax error
|
||||
(except inside multiline strings and comments; these must be closed explicitly).
|
||||
If a line starts with
|
||||
.BR '=' ,
|
||||
then
|
||||
.B lua
|
||||
displays the values of all the expressions in the remainder of the
|
||||
line. The expressions must be separated by commas.
|
||||
The primary prompt is the value of the global variable
|
||||
.BR _PROMPT ,
|
||||
if this value is a string;
|
||||
otherwise, the default prompt is used.
|
||||
Similarly, the secondary prompt is the value of the global variable
|
||||
.BR _PROMPT2 .
|
||||
So,
|
||||
to change the prompts,
|
||||
set the corresponding variable to a string of your choice.
|
||||
You can do that after calling the interpreter
|
||||
or on the command line
|
||||
(but in this case you have to be careful with quotes
|
||||
if the prompt string contains a space; otherwise you may confuse the shell.)
|
||||
The default prompts are "> " and ">> ".
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-
|
||||
load and execute the standard input as a file,
|
||||
that is,
|
||||
not interactively,
|
||||
even when the standard input is a terminal.
|
||||
.TP
|
||||
.BI \-e " stat"
|
||||
execute statement
|
||||
.IR stat .
|
||||
You need to quote
|
||||
.I stat
|
||||
if it contains spaces, quotes,
|
||||
or other characters special to the shell.
|
||||
.TP
|
||||
.B \-i
|
||||
enter interactive mode after
|
||||
.I script
|
||||
is executed.
|
||||
.TP
|
||||
.BI \-l " name"
|
||||
call
|
||||
.BI require(' name ')
|
||||
before executing
|
||||
.IR script .
|
||||
Typically used to load libraries.
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.SH "SEE ALSO"
|
||||
.BR luac (1)
|
||||
.br
|
||||
http://www.lua.org/
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH AUTHORS
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
and
|
||||
W. Celes
|
||||
.\" EOF
|
@ -1,15 +0,0 @@
|
||||
body {
|
||||
color: #000000 ;
|
||||
background-color: #FFFFFF ;
|
||||
font-family: sans-serif ;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #000080 ;
|
||||
}
|
||||
|
||||
a:link:hover, a:visited:hover {
|
||||
color: #000080 ;
|
||||
background-color: #E0E0FF ;
|
||||
}
|
||||
|
172
doc/lua/lua.html
172
doc/lua/lua.html
@ -1,172 +0,0 @@
|
||||
<!-- $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $ -->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>LUA man page</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<H2>NAME</H2>
|
||||
lua - Lua interpreter
|
||||
<H2>SYNOPSIS</H2>
|
||||
<B>lua</B>
|
||||
[
|
||||
<I>options</I>
|
||||
]
|
||||
[
|
||||
<I>script</I>
|
||||
[
|
||||
<I>args</I>
|
||||
]
|
||||
]
|
||||
<H2>DESCRIPTION</H2>
|
||||
<B>lua</B>
|
||||
is the stand-alone Lua interpreter.
|
||||
It loads and executes Lua programs,
|
||||
either in textual source form or
|
||||
in precompiled binary form.
|
||||
(Precompiled binaries are output by
|
||||
<B>luac</B>,
|
||||
the Lua compiler.)
|
||||
<B>lua</B>
|
||||
can be used as a batch interpreter and also interactively.
|
||||
<P>
|
||||
The given
|
||||
<I>options</I>
|
||||
(see below)
|
||||
are executed and then
|
||||
the Lua program in file
|
||||
<I>script</I>
|
||||
is loaded and executed.
|
||||
The given
|
||||
<I>args</I>
|
||||
are available to
|
||||
<I>script</I>
|
||||
as strings in a global table named
|
||||
<B>arg</B>.
|
||||
If these arguments contain spaces or other characters special to the shell,
|
||||
then they should be quoted
|
||||
(but note that the quotes will be removed by the shell).
|
||||
The arguments in
|
||||
<B>arg</B>
|
||||
start at 0,
|
||||
which contains the string
|
||||
'<I>script</I>'.
|
||||
The index of the last argument is stored in
|
||||
<B>arg.n</B>.
|
||||
The arguments given in the command line before
|
||||
<I>script</I>,
|
||||
including the name of the interpreter,
|
||||
are available in negative indices in
|
||||
<B>arg</B>.
|
||||
<P>
|
||||
At the very start,
|
||||
before even handling the command line,
|
||||
<B>lua</B>
|
||||
executes the contents of the environment variable
|
||||
<B>LUA_INIT</B>,
|
||||
if it is defined.
|
||||
If the value of
|
||||
<B>LUA_INIT</B>
|
||||
is of the form
|
||||
'@<I>filename</I>',
|
||||
then
|
||||
<I>filename</I>
|
||||
is executed.
|
||||
Otherwise, the string is assumed to be a Lua statement and is executed.
|
||||
<P>
|
||||
Options start with
|
||||
<B>'-'</B>
|
||||
and are described below.
|
||||
You can use
|
||||
<B>'--'</B>
|
||||
to signal the end of options.
|
||||
<P>
|
||||
If no arguments are given,
|
||||
then
|
||||
<B>"-v -i"</B>
|
||||
is assumed when the standard input is a terminal;
|
||||
otherwise,
|
||||
<B>"-"</B>
|
||||
is assumed.
|
||||
<P>
|
||||
In interactive mode,
|
||||
<B>lua</B>
|
||||
prompts the user,
|
||||
reads lines from the standard input,
|
||||
and executes them as they are read.
|
||||
If a line does not contain a complete statement,
|
||||
then a secondary prompt is displayed and
|
||||
lines are read until a complete statement is formed or
|
||||
a syntax error is found.
|
||||
So, one way to interrupt the reading of an incomplete statement is
|
||||
to force a syntax error:
|
||||
adding a
|
||||
<B>';'</B>
|
||||
in the middle of a statement is a sure way of forcing a syntax error
|
||||
(except inside multiline strings and comments; these must be closed explicitly).
|
||||
If a line starts with
|
||||
<B>'='</B>,
|
||||
then
|
||||
<B>lua</B>
|
||||
displays the values of all the expressions in the remainder of the
|
||||
line. The expressions must be separated by commas.
|
||||
The primary prompt is the value of the global variable
|
||||
<B>_PROMPT</B>,
|
||||
if this value is a string;
|
||||
otherwise, the default prompt is used.
|
||||
Similarly, the secondary prompt is the value of the global variable
|
||||
<B>_PROMPT2</B>.
|
||||
So,
|
||||
to change the prompts,
|
||||
set the corresponding variable to a string of your choice.
|
||||
You can do that after calling the interpreter
|
||||
or on the command line
|
||||
(but in this case you have to be careful with quotes
|
||||
if the prompt string contains a space; otherwise you may confuse the shell.)
|
||||
The default prompts are "> " and ">> ".
|
||||
<H2>OPTIONS</H2>
|
||||
<P>
|
||||
<B>-</B>
|
||||
load and execute the standard input as a file,
|
||||
that is,
|
||||
not interactively,
|
||||
even when the standard input is a terminal.
|
||||
<P>
|
||||
<B>-e </B><I>stat</I>
|
||||
execute statement
|
||||
<I>stat</I>.
|
||||
You need to quote
|
||||
<I>stat </I>
|
||||
if it contains spaces, quotes,
|
||||
or other characters special to the shell.
|
||||
<P>
|
||||
<B>-i</B>
|
||||
enter interactive mode after
|
||||
<I>script</I>
|
||||
is executed.
|
||||
<P>
|
||||
<B>-l </B><I>name</I>
|
||||
call
|
||||
<B>require</B>('<I>name</I>')
|
||||
before executing
|
||||
<I>script</I>.
|
||||
Typically used to load libraries.
|
||||
<P>
|
||||
<B>-v</B>
|
||||
show version information.
|
||||
<H2>SEE ALSO</H2>
|
||||
<B>luac</B>(1)
|
||||
<BR>
|
||||
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
|
||||
<H2>DIAGNOSTICS</H2>
|
||||
Error messages should be self explanatory.
|
||||
<H2>AUTHORS</H2>
|
||||
R. Ierusalimschy,
|
||||
L. H. de Figueiredo,
|
||||
and
|
||||
W. Celes
|
||||
<!-- EOF -->
|
||||
</BODY>
|
||||
</HTML>
|
136
doc/lua/luac.1
136
doc/lua/luac.1
@ -1,136 +0,0 @@
|
||||
.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
|
||||
.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
|
||||
.SH NAME
|
||||
luac \- Lua compiler
|
||||
.SH SYNOPSIS
|
||||
.B luac
|
||||
[
|
||||
.I options
|
||||
] [
|
||||
.I filenames
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B luac
|
||||
is the Lua compiler.
|
||||
It translates programs written in the Lua programming language
|
||||
into binary files that can be later loaded and executed.
|
||||
.LP
|
||||
The main advantages of precompiling chunks are:
|
||||
faster loading,
|
||||
protecting source code from accidental user changes,
|
||||
and
|
||||
off-line syntax checking.
|
||||
.LP
|
||||
Pre-compiling does not imply faster execution
|
||||
because in Lua chunks are always compiled into bytecodes before being executed.
|
||||
.B luac
|
||||
simply allows those bytecodes to be saved in a file for later execution.
|
||||
.LP
|
||||
Pre-compiled chunks are not necessarily smaller than the corresponding source.
|
||||
The main goal in pre-compiling is faster loading.
|
||||
.LP
|
||||
The binary files created by
|
||||
.B luac
|
||||
are portable only among architectures with the same word size and byte order.
|
||||
.LP
|
||||
.B luac
|
||||
produces a single output file containing the bytecodes
|
||||
for all source files given.
|
||||
By default,
|
||||
the output file is named
|
||||
.BR luac.out ,
|
||||
but you can change this with the
|
||||
.B \-o
|
||||
option.
|
||||
.LP
|
||||
In the command line,
|
||||
you can mix
|
||||
text files containing Lua source and
|
||||
binary files containing precompiled chunks.
|
||||
This is useful to combine several precompiled chunks,
|
||||
even from different (but compatible) platforms,
|
||||
into a single precompiled chunk.
|
||||
.LP
|
||||
You can use
|
||||
.B "'\-'"
|
||||
to indicate the standard input as a source file
|
||||
and
|
||||
.B "'\--'"
|
||||
to signal the end of options
|
||||
(that is,
|
||||
all remaining arguments will be treated as files even if they start with
|
||||
.BR "'\-'" ).
|
||||
.LP
|
||||
The internal format of the binary files produced by
|
||||
.B luac
|
||||
is likely to change when a new version of Lua is released.
|
||||
So,
|
||||
save the source files of all Lua programs that you precompile.
|
||||
.LP
|
||||
.SH OPTIONS
|
||||
Options must be separate.
|
||||
.TP
|
||||
.B \-l
|
||||
produce a listing of the compiled bytecode for Lua's virtual machine.
|
||||
Listing bytecodes is useful to learn about Lua's virtual machine.
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and lists its contents.
|
||||
.TP
|
||||
.BI \-o " file"
|
||||
output to
|
||||
.IR file ,
|
||||
instead of the default
|
||||
.BR luac.out .
|
||||
(You can use
|
||||
.B "'\-'"
|
||||
for standard output,
|
||||
but not on platforms that open standard output in text mode.)
|
||||
The output file may be a source file because
|
||||
all files are loaded before the output file is written.
|
||||
Be careful not to overwrite precious files.
|
||||
.TP
|
||||
.B \-p
|
||||
load files but do not generate any output file.
|
||||
Used mainly for syntax checking and for testing precompiled chunks:
|
||||
corrupted files will probably generate errors when loaded.
|
||||
Lua always performs a thorough integrity test on precompiled chunks.
|
||||
Bytecode that passes this test is completely safe,
|
||||
in the sense that it will not break the interpreter.
|
||||
However,
|
||||
there is no guarantee that such code does anything sensible.
|
||||
(None can be given, because the halting problem is unsolvable.)
|
||||
If no files are given, then
|
||||
.B luac
|
||||
loads
|
||||
.B luac.out
|
||||
and tests its contents.
|
||||
No messages are displayed if the file passes the integrity test.
|
||||
.TP
|
||||
.B \-s
|
||||
strip debug information before writing the output file.
|
||||
This saves some space in very large chunks,
|
||||
but if errors occur when running a stripped chunk,
|
||||
then the error messages may not contain the full information they usually do.
|
||||
For instance,
|
||||
line numbers and names of local variables are lost.
|
||||
.TP
|
||||
.B \-v
|
||||
show version information.
|
||||
.SH FILES
|
||||
.TP 15
|
||||
.B luac.out
|
||||
default output file
|
||||
.SH "SEE ALSO"
|
||||
.BR lua (1)
|
||||
.br
|
||||
http://www.lua.org/
|
||||
.SH DIAGNOSTICS
|
||||
Error messages should be self explanatory.
|
||||
.SH AUTHORS
|
||||
L. H. de Figueiredo,
|
||||
R. Ierusalimschy and
|
||||
W. Celes
|
||||
.\" EOF
|
@ -1,145 +0,0 @@
|
||||
<!-- $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $ -->
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>LUAC man page</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<H2>NAME</H2>
|
||||
luac - Lua compiler
|
||||
<H2>SYNOPSIS</H2>
|
||||
<B>luac</B>
|
||||
[
|
||||
<I>options</I>
|
||||
] [
|
||||
<I>filenames</I>
|
||||
]
|
||||
<H2>DESCRIPTION</H2>
|
||||
<B>luac</B>
|
||||
is the Lua compiler.
|
||||
It translates programs written in the Lua programming language
|
||||
into binary files that can be later loaded and executed.
|
||||
<P>
|
||||
The main advantages of precompiling chunks are:
|
||||
faster loading,
|
||||
protecting source code from accidental user changes,
|
||||
and
|
||||
off-line syntax checking.
|
||||
<P>
|
||||
Precompiling does not imply faster execution
|
||||
because in Lua chunks are always compiled into bytecodes before being executed.
|
||||
<B>luac</B>
|
||||
simply allows those bytecodes to be saved in a file for later execution.
|
||||
<P>
|
||||
Precompiled chunks are not necessarily smaller than the corresponding source.
|
||||
The main goal in precompiling is faster loading.
|
||||
<P>
|
||||
The binary files created by
|
||||
<B>luac</B>
|
||||
are portable only among architectures with the same word size and byte order.
|
||||
<P>
|
||||
<B>luac</B>
|
||||
produces a single output file containing the bytecodes
|
||||
for all source files given.
|
||||
By default,
|
||||
the output file is named
|
||||
<B>luac.out</B>,
|
||||
but you can change this with the
|
||||
<B>-o</B>
|
||||
option.
|
||||
<P>
|
||||
In the command line,
|
||||
you can mix
|
||||
text files containing Lua source and
|
||||
binary files containing precompiled chunks.
|
||||
This is useful because several precompiled chunks,
|
||||
even from different (but compatible) platforms,
|
||||
can be combined into a single precompiled chunk.
|
||||
<P>
|
||||
You can use
|
||||
<B>'-'</B>
|
||||
to indicate the standard input as a source file
|
||||
and
|
||||
<B>'--'</B>
|
||||
to signal the end of options
|
||||
(that is,
|
||||
all remaining arguments will be treated as files even if they start with
|
||||
<B>'-'</B>).
|
||||
<P>
|
||||
The internal format of the binary files produced by
|
||||
<B>luac</B>
|
||||
is likely to change when a new version of Lua is released.
|
||||
So,
|
||||
save the source files of all Lua programs that you precompile.
|
||||
<P>
|
||||
<H2>OPTIONS</H2>
|
||||
Options must be separate.
|
||||
<P>
|
||||
<B>-l</B>
|
||||
produce a listing of the compiled bytecode for Lua's virtual machine.
|
||||
Listing bytecodes is useful to learn about Lua's virtual machine.
|
||||
If no files are given, then
|
||||
<B>luac</B>
|
||||
loads
|
||||
<B>luac.out</B>
|
||||
and lists its contents.
|
||||
<P>
|
||||
<B>-o </B><I>file</I>
|
||||
output to
|
||||
<I>file</I>,
|
||||
instead of the default
|
||||
<B>luac.out</B>.
|
||||
(You can use
|
||||
<B>'-'</B>
|
||||
for standard output,
|
||||
but not on platforms that open standard output in text mode.)
|
||||
The output file may be a source file because
|
||||
all files are loaded before the output file is written.
|
||||
Be careful not to overwrite precious files.
|
||||
<P>
|
||||
<B>-p</B>
|
||||
load files but do not generate any output file.
|
||||
Used mainly for syntax checking and for testing precompiled chunks:
|
||||
corrupted files will probably generate errors when loaded.
|
||||
Lua always performs a thorough integrity test on precompiled chunks.
|
||||
Bytecode that passes this test is completely safe,
|
||||
in the sense that it will not break the interpreter.
|
||||
However,
|
||||
there is no guarantee that such code does anything sensible.
|
||||
(None can be given, because the halting problem is unsolvable.)
|
||||
If no files are given, then
|
||||
<B>luac</B>
|
||||
loads
|
||||
<B>luac.out</B>
|
||||
and tests its contents.
|
||||
No messages are displayed if the file passes the integrity test.
|
||||
<P>
|
||||
<B>-s</B>
|
||||
strip debug information before writing the output file.
|
||||
This saves some space in very large chunks,
|
||||
but if errors occur when running a stripped chunk,
|
||||
then the error messages may not contain the full information they usually do.
|
||||
For instance,
|
||||
line numbers and names of local variables are lost.
|
||||
<P>
|
||||
<B>-v</B>
|
||||
show version information.
|
||||
<H2>FILES</H2>
|
||||
<P>
|
||||
<B>luac.out</B>
|
||||
default output file
|
||||
<H2>SEE ALSO</H2>
|
||||
<B>lua</B>(1)
|
||||
<BR>
|
||||
<A HREF="http://www.lua.org/">http://www.lua.org/</A>
|
||||
<H2>DIAGNOSTICS</H2>
|
||||
Error messages should be self explanatory.
|
||||
<H2>AUTHORS</H2>
|
||||
L. H. de Figueiredo,
|
||||
R. Ierusalimschy and
|
||||
W. Celes
|
||||
<!-- EOF -->
|
||||
</BODY>
|
||||
</HTML>
|
6247
doc/lua/manual.html
6247
doc/lua/manual.html
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lua documentation</TITLE>
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="lua.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#FFFFFF">
|
||||
|
||||
<HR>
|
||||
<H1>
|
||||
<A HREF="http://www.lua.org/"><IMG SRC="logo.gif" ALT="Lua" BORDER=0></A>
|
||||
Documentation
|
||||
</H1>
|
||||
|
||||
<UL>
|
||||
<LI><A HREF="http://www.lua.org/">Official web site</A>
|
||||
<LI><A HREF="contents.html">Reference manual</A>
|
||||
<LI><A HREF="lua.html">lua man page</A>
|
||||
<LI><A HREF="luac.html">luac man page</A>
|
||||
<LI><A HREF="../README">lua/README</A>
|
||||
<LI><A HREF="../etc/README">lua/etc/README</A>
|
||||
<LI><A HREF="../test/README">lua/test/README</A>
|
||||
</UL>
|
||||
|
||||
<HR>
|
||||
<SMALL>
|
||||
Last update:
|
||||
Wed Sep 7 12:57:50 BRST 2005
|
||||
</SMALL>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
@ -1,7 +0,0 @@
|
||||
Copyright (c) 2007 Jesse Luehrs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -1,31 +0,0 @@
|
||||
LuaIRC v0.3
|
||||
Jesse Luehrs (jluehrs2@uiuc.edu)
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
LuaIRC is a fully featured IRC framework written entirely in Lua. It provides an event driven system for connecting to IRC servers and responding to actions such as messages, joins/parts, and channel mode changes, among other things. DCC SEND is also fully implemented, both for sending and receiving files.
|
||||
|
||||
INSTALL
|
||||
=======
|
||||
This module requires LuaSocket (http://www.cs.princeton.edu/~diego/professional/luasocket/) and Lua 5.1. To install, modify the Make.config file with paths appropriate to your system and run 'make install'.
|
||||
|
||||
DOCUMENTATION
|
||||
=============
|
||||
Documentation of the API can be found in the doc/ directory. It was autogenerated from the source files by LuaDoc (http://luadoc.luaforge.net/).
|
||||
|
||||
LuaIRC has only been tested on Freenode so far, but I plan to expand this to other servers in the future. It's quite possible that it works on other servers anyway, however, so feel free to try it out, and send in bug reports for things that break.
|
||||
|
||||
CHANGES
|
||||
=======
|
||||
0.3
|
||||
- Major cleanup and restructuring again, documentation added, first public release
|
||||
0.2
|
||||
- Major cleanup and restructuring
|
||||
0.1
|
||||
- Initial implementation, enough to get it talking to the IRC server
|
||||
|
||||
COPYRIGHT AND LICENSE
|
||||
=====================
|
||||
Copyright (C) 2007 Jesse Luehrs
|
||||
|
||||
This code is distributed under the MIT license; a copy is in the LICENSE file distributed with the source.
|
@ -1,20 +0,0 @@
|
||||
- Reorganize the modules a bit more... we should have a src/irc/dcc/send.lua, src/irc/ctcp/base.lua, src/irc/ctcp/dcc.lua, etc. also, most (all?) of the handlers should be moved out of irc.lua into, say, src/irc/base.lua
|
||||
- Separate out the DCC module some more so that the callbacks aren't registered unless the module is loaded
|
||||
- Also separate out all of the CTCP commands/callbacks into the CTCP module
|
||||
- Rework the way irc.lua uses things from modules - the whole underscore but public thing... do i want to keep that? i suppose it's not horrible... look into this more
|
||||
- Implement callbacks for user mode changes (need to figure out how to represent users in the callback info)
|
||||
- Allow a server parameter in whois() so that the returned data can include the user's idle time
|
||||
- chan:ban()/chan:unban() should take a usermask, not a nick, or be able to generate a usermask from a nick, or something like that
|
||||
- Clean up misc.split
|
||||
- Implement DCC CHAT
|
||||
- Implement DCC XMIT/OFFER
|
||||
- Implement some more of the newer CTCP commands
|
||||
- Implement more information requests
|
||||
- who
|
||||
- whowas
|
||||
- info
|
||||
- stats
|
||||
- links
|
||||
- trace (not freenode supported)
|
||||
- Implement XDCC (?)
|
||||
- Handle endianness in the IP address conversion functions
|
@ -1,156 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><strong>Index</strong></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
|
||||
|
||||
<h2>Modules</h2>
|
||||
<table class="module_list">
|
||||
<!--<tr><td colspan="2">Modules</td></tr>-->
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/callbacks.html">callbacks</a></td>
|
||||
<td class="summary">These are the callbacks that are available to register.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.html">irc</a></td>
|
||||
<td class="summary">LuaIRC - IRC framework written in Lua </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.channel.html">irc.channel</a></td>
|
||||
<td class="summary">This module implements a channel object representing a single channel we have joined.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.constants.html">irc.constants</a></td>
|
||||
<td class="summary">This module holds various constants used by the IRC protocol.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.ctcp.html">irc.ctcp</a></td>
|
||||
<td class="summary">This module implements the various quoting and escaping requirements of the CTCP protocol.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.dcc.html">irc.dcc</a></td>
|
||||
<td class="summary">This module implements the DCC protocol.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.debug.html">irc.debug</a></td>
|
||||
<td class="summary">This module implements a few useful debug functions for use throughout the rest of the code.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.message.html">irc.message</a></td>
|
||||
<td class="summary">This module contains parsing functions for IRC server messages.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name"><a href="modules/irc.misc.html">irc.misc</a></td>
|
||||
<td class="summary">This module contains various useful functions which didn't fit in any of the other modules.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,286 +0,0 @@
|
||||
body {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-family: arial, helvetica, geneva, sans-serif;
|
||||
background-color:#ffffff; margin:0px;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
tt {
|
||||
font-family: "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
body, td, th { font-size: 11pt; }
|
||||
|
||||
h1, h2, h3, h4 { margin-left: 0em; }
|
||||
|
||||
textarea, pre, tt { font-size:10pt; }
|
||||
body, td, th { color:#000000; }
|
||||
small { font-size:0.85em; }
|
||||
h1 { font-size:1.5em; }
|
||||
h2 { font-size:1.25em; }
|
||||
h3 { font-size:1.15em; }
|
||||
h4 { font-size:1.06em; }
|
||||
|
||||
a:link { font-weight:bold; color: #004080; text-decoration: none; }
|
||||
a:visited { font-weight:bold; color: #006699; text-decoration: none; }
|
||||
a:link:hover { text-decoration:underline; }
|
||||
hr { color:#cccccc }
|
||||
img { border-width: 0px; }
|
||||
|
||||
|
||||
h3 { padding-top: 1em; }
|
||||
|
||||
p { margin-left: 1em; }
|
||||
|
||||
p.name {
|
||||
font-family: "Andale Mono", monospace;
|
||||
padding-top: 1em;
|
||||
margin-left: 0em;
|
||||
}
|
||||
|
||||
blockquote { margin-left: 3em; }
|
||||
|
||||
pre.example {
|
||||
background-color: rgb(245, 245, 245);
|
||||
border-top-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-top-style: solid;
|
||||
border-right-style: solid;
|
||||
border-bottom-style: solid;
|
||||
border-left-style: solid;
|
||||
border-top-color: silver;
|
||||
border-right-color: silver;
|
||||
border-bottom-color: silver;
|
||||
border-left-color: silver;
|
||||
padding: 1em;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-family: "Andale Mono", monospace;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
|
||||
hr {
|
||||
margin-left: 0em;
|
||||
background: #00007f;
|
||||
border: 0px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
ul { list-style-type: disc; }
|
||||
|
||||
table.index { border: 1px #00007f; }
|
||||
table.index td { text-align: left; vertical-align: top; }
|
||||
table.index ul { padding-top: 0em; margin-top: 0em; }
|
||||
|
||||
table {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
th {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
}
|
||||
td {
|
||||
border: 1px solid black;
|
||||
padding: 0.5em;
|
||||
}
|
||||
div.header, div.footer { margin-left: 0em; }
|
||||
|
||||
#container
|
||||
{
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
#product
|
||||
{
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#product big {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#product_logo
|
||||
{
|
||||
}
|
||||
|
||||
#product_name
|
||||
{
|
||||
}
|
||||
|
||||
#product_description
|
||||
{
|
||||
}
|
||||
|
||||
#main
|
||||
{
|
||||
background-color: #f0f0f0;
|
||||
border-left: 2px solid #cccccc;
|
||||
}
|
||||
|
||||
#navigation
|
||||
{
|
||||
float: left;
|
||||
width: 18em;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
background-color: #f0f0f0;
|
||||
overflow:visible;
|
||||
}
|
||||
|
||||
#navigation h1 {
|
||||
background-color:#e7e7e7;
|
||||
font-size:1.1em;
|
||||
color:#000000;
|
||||
text-align:left;
|
||||
margin:0px;
|
||||
padding:0.2em;
|
||||
border-top:1px solid #dddddd;
|
||||
border-bottom:1px solid #dddddd;
|
||||
}
|
||||
|
||||
#navigation ul
|
||||
{
|
||||
font-size:1em;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
#navigation li
|
||||
{
|
||||
text-indent: -1em;
|
||||
margin: 0em 0em 0em 0.5em;
|
||||
display: block;
|
||||
padding: 3px 0px 0px 12px;
|
||||
}
|
||||
|
||||
#navigation li li a
|
||||
{
|
||||
padding: 0px 3px 0px -1em;
|
||||
}
|
||||
|
||||
#content
|
||||
{
|
||||
margin-left: 18em;
|
||||
padding: 1em;
|
||||
border-left: 2px solid #cccccc;
|
||||
border-right: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#about
|
||||
{
|
||||
clear: both;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
border-top: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font: 12pt "Times New Roman", "TimeNR", Times, serif;
|
||||
}
|
||||
a { font-weight:bold; color: #004080; text-decoration: underline; }
|
||||
|
||||
#main
{
background-color: #ffffff;
border-left: 0px;
}
|
||||
#container
{
margin-left: 2%;
margin-right: 2%;
background-color: #ffffff;
}
|
||||
|
||||
#content
{
margin-left: 0px;
padding: 1em;
border-left: 0px;
border-right: 0px;
background-color: #ffffff;
}
|
||||
|
||||
#navigation
{
display: none;
|
||||
}
|
||||
pre.example {
|
||||
font-family: "Andale Mono", monospace;
|
||||
font-size: 10pt;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
table.module_list td
|
||||
{
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.module_list td.name { background-color: #f0f0f0; }
|
||||
table.module_list td.summary { width: 100%; }
|
||||
|
||||
table.file_list
|
||||
{
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.file_list td
|
||||
{
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.file_list td.name { background-color: #f0f0f0; }
|
||||
table.file_list td.summary { width: 100%; }
|
||||
|
||||
|
||||
table.function_list
|
||||
{
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.function_list td
|
||||
{
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.function_list td.name { background-color: #f0f0f0; }
|
||||
table.function_list td.summary { width: 100%; }
|
||||
|
||||
|
||||
table.table_list
|
||||
{
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.table_list td
|
||||
{
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.table_list td.name { background-color: #f0f0f0; }
|
||||
table.table_list td.summary { width: 100%; }
|
||||
|
||||
dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
|
||||
dl.function dd {padding-bottom: 1em;}
|
||||
dl.function h3 {padding: 0; margin: 0; font-size: medium;}
|
||||
|
||||
dl.table dt {border-top: 1px solid #ccc; padding-top: 1em;}
|
||||
dl.table dd {padding-bottom: 1em;}
|
||||
dl.table h3 {padding: 0; margin: 0; font-size: medium;}
|
||||
|
||||
#TODO: make module_list, file_list, function_list, table_list inherit from a list
|
||||
|
@ -1,858 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li><strong>callbacks</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>callbacks</code></h1>
|
||||
|
||||
<p>These are the callbacks that are available to register.</p>
|
||||
|
||||
|
||||
|
||||
<h2>Functions</h2>
|
||||
<table class="function_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#channel_act">channel_act</a> (channel, from, message)</td>
|
||||
<td class="summary">This callback is triggered whenever a user performs a CTCP ACTION in a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#channel_msg">channel_msg</a> (channel, from, message)</td>
|
||||
<td class="summary">This callback is triggered whenever a user sends a message to a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#channel_notice">channel_notice</a> (channel, from, message)</td>
|
||||
<td class="summary">This callback is triggered whenever a user sends a notice to a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#connect">connect</a> ()</td>
|
||||
<td class="summary">This callback is triggered when the connection has completed.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ctcp_error">ctcp_error</a> (from, to, message)</td>
|
||||
<td class="summary">This callback is triggered when a CTCP command resulted in an error (for example, if the remote client doesn't implement that CTCP command).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#dcc_send">dcc_send</a> (from, to, filename, address, port, filesize)</td>
|
||||
<td class="summary">This callback is triggered when a user offers to send you a file using DCC SEND.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#deop">deop</a> (channel, from, to)</td>
|
||||
<td class="summary">This callback is triggered whenever somebody loses ops.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#devoice">devoice</a> (channel, from, to)</td>
|
||||
<td class="summary">This callback is triggered whenever somebody loses voice.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#invite">invite</a> (from, channel)</td>
|
||||
<td class="summary">This callback is triggered whenever an invite to a channel is received.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#join">join</a> (channel, from)</td>
|
||||
<td class="summary">This callback is triggered when a user joins a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#kick">kick</a> (channel, to, from)</td>
|
||||
<td class="summary">This callback is triggered when a user is kicked from a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#me_join">me_join</a> (channel)</td>
|
||||
<td class="summary">This callback is triggered after a join() command completes.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#nick_change">nick_change</a> (from, old_nick)</td>
|
||||
<td class="summary">This callback is triggered when a user changes their nick.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#op">op</a> (channel, from, to)</td>
|
||||
<td class="summary">This callback is triggered when a user is opped.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#part">part</a> (channel, from, message)</td>
|
||||
<td class="summary">This callback is triggered when a user leaves a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#private_act">private_act</a> (from, message)</td>
|
||||
<td class="summary">This callback is triggered when a user sends a CTCP ACTION in a private message.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#private_msg">private_msg</a> (from, message)</td>
|
||||
<td class="summary">This callback is triggered when a user sends a private message.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#private_notice">private_notice</a> (from, message)</td>
|
||||
<td class="summary">This callback is triggered when a user sends a private notice.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#quit">quit</a> (from, message)</td>
|
||||
<td class="summary">This callback is triggered when a user quits.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#topic_change">topic_change</a> (channel)</td>
|
||||
<td class="summary">This callback is triggered when a user changes the topic in a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#voice">voice</a> (channel, from, to)</td>
|
||||
<td class="summary">This callback is triggered when a user is voiced.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<dl class="function">
|
||||
|
||||
|
||||
|
||||
<dt><a name="channel_act"></a><strong>channel_act</strong> (channel, from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever a user performs a CTCP ACTION in a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the action was performed
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who performed the action
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The action which was performed
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="channel_msg"></a><strong>channel_msg</strong> (channel, from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever a user sends a message to a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the message was sent
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who sent the message
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The message which was sent
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="channel_notice"></a><strong>channel_notice</strong> (channel, from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever a user sends a notice to a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the notice was sent
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who sent the message
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The notice which was sent
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="connect"></a><strong>connect</strong> ()</dt>
|
||||
<dd>
|
||||
This callback is triggered when the connection has completed.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="ctcp_error"></a><strong>ctcp_error</strong> (from, to, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a CTCP command resulted in an error (for example, if the remote client doesn't implement that CTCP command).
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who sent the error response
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: Who the response was sent to (either you or a channel you are in)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: A description of the error
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="dcc_send"></a><strong>dcc_send</strong> (from, to, filename, address, port, filesize)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user offers to send you a file using DCC SEND. It allows you to determine whether or not you want to accept the file.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User offering the file
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who is being offered the file (likely yourself)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
filename: Name of the file being offered
|
||||
</li>
|
||||
|
||||
<li>
|
||||
address: IP address of the user offering the file
|
||||
</li>
|
||||
|
||||
<li>
|
||||
port: Port to connect to at that address
|
||||
</li>
|
||||
|
||||
<li>
|
||||
filesize: Size of the file being offered
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
True to accept the file, false to reject it
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="deop"></a><strong>deop</strong> (channel, from, to)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever somebody loses ops.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the user lost ops
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who removed the ops
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who lost ops
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="devoice"></a><strong>devoice</strong> (channel, from, to)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever somebody loses voice.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the user lost voice
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who removed the voice
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who lost voice
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="invite"></a><strong>invite</strong> (from, channel)</dt>
|
||||
<dd>
|
||||
This callback is triggered whenever an invite to a channel is received.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who sent the invite
|
||||
</li>
|
||||
|
||||
<li>
|
||||
channel: Channel name that the invite was to
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="join"></a><strong>join</strong> (channel, from)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user joins a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where there was a join
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who joined
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="kick"></a><strong>kick</strong> (channel, to, from)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user is kicked from a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where there was a kick
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who was kicked
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who did the kicking
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="me_join"></a><strong>me_join</strong> (channel)</dt>
|
||||
<dd>
|
||||
This callback is triggered after a join() command completes.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for the joined channel
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="nick_change"></a><strong>nick_change</strong> (from, old_nick)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user changes their nick.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who changed their nick
|
||||
</li>
|
||||
|
||||
<li>
|
||||
old_nick: The previous nick of that user
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="op"></a><strong>op</strong> (channel, from, to)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user is opped.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the user was opped
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who gave the ops
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who was opped
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="part"></a><strong>part</strong> (channel, from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user leaves a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the part occurred
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who left
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: Part message from the user
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="private_act"></a><strong>private_act</strong> (from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user sends a CTCP ACTION in a private message.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who sent the action
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The action that was sent
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="private_msg"></a><strong>private_msg</strong> (from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user sends a private message.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who sent the message
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The message that was sent
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="private_notice"></a><strong>private_notice</strong> (from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user sends a private notice.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who sent the notice
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The notice that was sent
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="quit"></a><strong>quit</strong> (from, message)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user quits.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
from: User who quit
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: The user's quit message
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="topic_change"></a><strong>topic_change</strong> (channel)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user changes the topic in a channel. The contents of the topic can be seen in the <i>topic</i> field of the channel object.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the topic was changed.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="voice"></a><strong>voice</strong> (channel, from, to)</dt>
|
||||
<dd>
|
||||
This callback is triggered when a user is voiced.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel object for where the user was voiced
|
||||
</li>
|
||||
|
||||
<li>
|
||||
from: User who gave the voice
|
||||
</li>
|
||||
|
||||
<li>
|
||||
to: User who was voiced
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,945 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.channel</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.channel</code></h1>
|
||||
|
||||
<p>This module implements a channel object representing a single channel we have joined.</p>
|
||||
|
||||
|
||||
|
||||
<h2>Functions</h2>
|
||||
<table class="function_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ban">ban</a> (self, name)</td>
|
||||
<td class="summary">Ban a user from a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#contains">contains</a> (self, nick)</td>
|
||||
<td class="summary">Test if a user is in the channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#deop">deop</a> (self, name)</td>
|
||||
<td class="summary">Remove ops from a user.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#devoice">devoice</a> (self, name)</td>
|
||||
<td class="summary">Remove voice from a user.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#each_member">each_member</a> (self)</td>
|
||||
<td class="summary">Iterator over all users in the channel </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#each_op">each_op</a> (self)</td>
|
||||
<td class="summary">Iterator over the ops in the channel </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#each_user">each_user</a> (self)</td>
|
||||
<td class="summary">Iterator over the normal users in the channel </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#each_voice">each_voice</a> (self)</td>
|
||||
<td class="summary">Iterator over the voiced users in the channel </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#members">members</a> (self)</td>
|
||||
<td class="summary">Gets an array of all the users in the channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#new">new</a> (chan)</td>
|
||||
<td class="summary">Creates a new Channel object.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#op">op</a> (self, name)</td>
|
||||
<td class="summary">Give a user ops on a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ops">ops</a> (self)</td>
|
||||
<td class="summary">Gets an array of all the ops in the channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_invite_only">set_invite_only</a> (self, set)</td>
|
||||
<td class="summary">Set whether joining the channel requires an invite.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_key">set_key</a> (self, key)</td>
|
||||
<td class="summary">Set a channel password.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_limit">set_limit</a> (self, new_limit)</td>
|
||||
<td class="summary">Set a channel limit.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_moderated">set_moderated</a> (self, set)</td>
|
||||
<td class="summary">Set whether voice is required to speak.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_no_outside_messages">set_no_outside_messages</a> (self, set)</td>
|
||||
<td class="summary">If true, users must be in the channel to send messages to it.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_private">set_private</a> (self, set)</td>
|
||||
<td class="summary">Set the private state of a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_secret">set_secret</a> (self, set)</td>
|
||||
<td class="summary">Set the secret state of a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_topic_lock">set_topic_lock</a> (self, set)</td>
|
||||
<td class="summary">If true, the topic can only be changed by an op.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#unban">unban</a> (self, name)</td>
|
||||
<td class="summary">Remove a ban on a user.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#users">users</a> (self)</td>
|
||||
<td class="summary">Gets an array of all the normal users in the channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#voice">voice</a> (self, name)</td>
|
||||
<td class="summary">Give a user voice on a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#voices">voices</a> (self)</td>
|
||||
<td class="summary">Gets an array of all the voiced users in the channel.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Tables</h2>
|
||||
<table class="table_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#Channel">Channel</a></td>
|
||||
<td class="summary">An object of the Channel class represents a single joined channel.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<dl class="function">
|
||||
|
||||
|
||||
|
||||
<dt><a name="ban"></a><strong>ban</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Ban a user from a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to ban
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="contains"></a><strong>contains</strong> (self, nick)</dt>
|
||||
<dd>
|
||||
Test if a user is in the channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
nick: Nick to search for
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
True if the nick is in the channel, false otherwise
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="deop"></a><strong>deop</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Remove ops from a user.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to remove ops from
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="devoice"></a><strong>devoice</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Remove voice from a user.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to remove voice from
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="each_member"></a><strong>each_member</strong> (self)</dt>
|
||||
<dd>
|
||||
Iterator over all users in the channel
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="each_op"></a><strong>each_op</strong> (self)</dt>
|
||||
<dd>
|
||||
Iterator over the ops in the channel
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="each_user"></a><strong>each_user</strong> (self)</dt>
|
||||
<dd>
|
||||
Iterator over the normal users in the channel
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="each_voice"></a><strong>each_voice</strong> (self)</dt>
|
||||
<dd>
|
||||
Iterator over the voiced users in the channel
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="members"></a><strong>members</strong> (self)</dt>
|
||||
<dd>
|
||||
Gets an array of all the users in the channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
Array of channel users
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="new"></a><strong>new</strong> (chan)</dt>
|
||||
<dd>
|
||||
Creates a new Channel object.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
chan: Name of the new channel
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
The new channel instance
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="op"></a><strong>op</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Give a user ops on a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to op
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="ops"></a><strong>ops</strong> (self)</dt>
|
||||
<dd>
|
||||
Gets an array of all the ops in the channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
Array of channel ops
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_invite_only"></a><strong>set_invite_only</strong> (self, set)</dt>
|
||||
<dd>
|
||||
Set whether joining the channel requires an invite.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to set the channel invite only, false to unset it
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_key"></a><strong>set_key</strong> (self, key)</dt>
|
||||
<dd>
|
||||
Set a channel password.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
key: New channel password (optional; password is unset if this argument isn't passed)
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_limit"></a><strong>set_limit</strong> (self, new_limit)</dt>
|
||||
<dd>
|
||||
Set a channel limit.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
new_limit: New value for the channel limit (optional; limit is unset if this argument isn't passed)
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_moderated"></a><strong>set_moderated</strong> (self, set)</dt>
|
||||
<dd>
|
||||
Set whether voice is required to speak.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to set the channel as moderated, false to unset it
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_no_outside_messages"></a><strong>set_no_outside_messages</strong> (self, set)</dt>
|
||||
<dd>
|
||||
If true, users must be in the channel to send messages to it.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to require users to be in the channel to send messages to it, false to remove this restriction
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_private"></a><strong>set_private</strong> (self, set)</dt>
|
||||
<dd>
|
||||
Set the private state of a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to set the channel as private, false to unset it
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_secret"></a><strong>set_secret</strong> (self, set)</dt>
|
||||
<dd>
|
||||
Set the secret state of a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to set the channel as secret, false to unset it
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_topic_lock"></a><strong>set_topic_lock</strong> (self, set)</dt>
|
||||
<dd>
|
||||
If true, the topic can only be changed by an op.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
set: True to lock the topic, false to unlock it
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="unban"></a><strong>unban</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Remove a ban on a user.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to unban
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="users"></a><strong>users</strong> (self)</dt>
|
||||
<dd>
|
||||
Gets an array of all the normal users in the channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
Array of channel normal users
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="voice"></a><strong>voice</strong> (self, name)</dt>
|
||||
<dd>
|
||||
Give a user voice on a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
<li>
|
||||
name: User to give voice to
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="voices"></a><strong>voices</strong> (self)</dt>
|
||||
<dd>
|
||||
Gets an array of all the voiced users in the channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
self: Channel object
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
Array of channel voiced users
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2><a name="tables"></a>Tables</h2>
|
||||
<dl class="table">
|
||||
|
||||
<dt><a name="Channel"></a><strong>Channel</strong></dt>
|
||||
<dd>An object of the Channel class represents a single joined channel. It has several table fields, and can be used in string contexts (returning the channel name).<br />
|
||||
|
||||
|
||||
<em>Fields</em>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
name: Name of the channel (read only)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
topic: Channel topic, if set (read/write, writing to this sends a topic change request to the server for this channel)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
chanmode: Channel mode (public/private/secret) (read only)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
members: Array of all members of this channel
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.constants</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.constants</code></h1>
|
||||
|
||||
<p>This module holds various constants used by the IRC protocol.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.ctcp</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.ctcp</code></h1>
|
||||
|
||||
<p>This module implements the various quoting and escaping requirements of the CTCP protocol.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,164 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.dcc</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.dcc</code></h1>
|
||||
|
||||
<p>This module implements the DCC protocol. File transfers (DCC SEND) are handled, but DCC CHAT is not, as of yet.</p>
|
||||
|
||||
|
||||
|
||||
<h2>Functions</h2>
|
||||
<table class="function_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#send">send</a> (nick, filename, port)</td>
|
||||
<td class="summary">Offers a file to a remote user.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<dl class="function">
|
||||
|
||||
|
||||
|
||||
<dt><a name="send"></a><strong>send</strong> (nick, filename, port)</dt>
|
||||
<dd>
|
||||
Offers a file to a remote user.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
nick: User to offer the file to
|
||||
</li>
|
||||
|
||||
<li>
|
||||
filename: Filename to offer
|
||||
</li>
|
||||
|
||||
<li>
|
||||
port: Port to accept connections on (optional, defaults to choosing an available port between FIRST_PORT and LAST_PORT above)
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,196 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.debug</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.debug</code></h1>
|
||||
|
||||
<p>This module implements a few useful debug functions for use throughout the rest of the code.</p>
|
||||
|
||||
|
||||
|
||||
<h2>Functions</h2>
|
||||
<table class="function_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#disable">disable</a> ()</td>
|
||||
<td class="summary">Turns off debug output.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#enable">enable</a> ()</td>
|
||||
<td class="summary">Turns on debug output.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_output">set_output</a> (file)</td>
|
||||
<td class="summary">Redirects output to a file rather than stdout.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<dl class="function">
|
||||
|
||||
|
||||
|
||||
<dt><a name="disable"></a><strong>disable</strong> ()</dt>
|
||||
<dd>
|
||||
Turns off debug output.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="enable"></a><strong>enable</strong> ()</dt>
|
||||
<dd>
|
||||
Turns on debug output.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_output"></a><strong>set_output</strong> (file)</dt>
|
||||
<dd>
|
||||
Redirects output to a file rather than stdout.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
file: File to write debug output to
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,683 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc</code></h1>
|
||||
|
||||
<p>LuaIRC - IRC framework written in Lua</p>
|
||||
|
||||
<p><small><b>Release:</b> 0.3</small></p>
|
||||
|
||||
|
||||
|
||||
<h2>Functions</h2>
|
||||
<table class="function_list">
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#act">act</a> (name, action)</td>
|
||||
<td class="summary">Perform a /me action.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#channels">channels</a> ()</td>
|
||||
<td class="summary">Iterate over currently joined channels.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#connect">connect</a> (args)</td>
|
||||
<td class="summary">Start a connection to the irc server.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ctcp_ping">ctcp_ping</a> (cb, nick)</td>
|
||||
<td class="summary">Send a CTCP ping request.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ctcp_time">ctcp_time</a> (cb, nick)</td>
|
||||
<td class="summary">Send a localtime request.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#ctcp_version">ctcp_version</a> (cb, nick)</td>
|
||||
<td class="summary">Send a client version request.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#get_ip">get_ip</a> ()</td>
|
||||
<td class="summary">Get the local IP address for the server connection.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#join">join</a> (channel)</td>
|
||||
<td class="summary">Join a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#notice">notice</a> (name, message)</td>
|
||||
<td class="summary">Send a notice to a user or channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#part">part</a> (channel)</td>
|
||||
<td class="summary">Leave a channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#quit">quit</a> (message)</td>
|
||||
<td class="summary">Close the connection to the irc server.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#register_callback">register_callback</a> (name, fn)</td>
|
||||
<td class="summary">Register a user function to be called when a specific event occurs.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#say">say</a> (name, message)</td>
|
||||
<td class="summary">Send a message to a user or channel.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#send">send</a> (command, ...)</td>
|
||||
<td class="summary">Send a raw IRC command.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#server_time">server_time</a> (cb)</td>
|
||||
<td class="summary">Request the current time of the server you are connected to.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#server_version">server_version</a> (cb)</td>
|
||||
<td class="summary">Request the version of the IRC server you are currently connected to.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#set_ip">set_ip</a> (new_ip)</td>
|
||||
<td class="summary">Set the local IP manually (to allow for NAT workarounds) </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#whois">whois</a> (cb, nick)</td>
|
||||
<td class="summary">Request WHOIS information about a given user.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<dl class="function">
|
||||
|
||||
|
||||
|
||||
<dt><a name="act"></a><strong>act</strong> (name, action)</dt>
|
||||
<dd>
|
||||
Perform a /me action.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
name: User or channel to send the action to
|
||||
</li>
|
||||
|
||||
<li>
|
||||
action: Action to send
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="channels"></a><strong>channels</strong> ()</dt>
|
||||
<dd>
|
||||
Iterate over currently joined channels. channels() is an iterator function for use in for loops. For example, <pre>for chan in irc.channels() do print(chan:name) end</pre>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<em>See also:</em>
|
||||
|
||||
<a href="../modules/irc.channel.html">
|
||||
irc.channel
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="connect"></a><strong>connect</strong> (args)</dt>
|
||||
<dd>
|
||||
Start a connection to the irc server.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
args: Table of named arguments containing connection parameters. Defaults are the all-caps versions of these parameters given at the top of the file, and are overridable by setting them as well, i.e. <pre>irc.NETWORK = irc.freenode.net</pre> Possible options are: <ul> <li><i>network:</i> address of the irc network to connect to (default: 'localhost')</li> <li><i>port:</i> port to connect to (default: '6667')</li> <li><i>pass:</i> irc server password (default: don't send)</li> <li><i>nick:</i> nickname to connect as (default: 'luabot')</li> <li><i>username:</i> username to connect with (default: 'LuaIRC')</li> <li><i>realname:</i> realname to connect with (default: 'LuaIRC')</li> <li><i>timeout:</i> amount of time in seconds to wait before dropping an idle connection (default: '60')</li> </ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="ctcp_ping"></a><strong>ctcp_ping</strong> (cb, nick)</dt>
|
||||
<dd>
|
||||
Send a CTCP ping request.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback will contain the fields: <ul> <li><i>nick:</i> the nick which responded to the request</li> <li><i>time:</i> the roundtrip ping time, in seconds</li> </ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
nick: User to ping
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="ctcp_time"></a><strong>ctcp_time</strong> (cb, nick)</dt>
|
||||
<dd>
|
||||
Send a localtime request.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback will contain the fields: <ul> <li><i>nick:</i> the nick which responded to the request</li> <li><i>time:</i> the localtime reported by the remote client</li> </ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
nick: User to request the localtime from
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="ctcp_version"></a><strong>ctcp_version</strong> (cb, nick)</dt>
|
||||
<dd>
|
||||
Send a client version request.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback will contain the fields: <ul> <li><i>nick:</i> the nick which responded to the request</li> <li><i>version:</i> the version reported by the remote client</li> </ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
nick: User to request the client version from
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="get_ip"></a><strong>get_ip</strong> ()</dt>
|
||||
<dd>
|
||||
Get the local IP address for the server connection.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
A string representation of the local IP address that the IRC server connection is communicating on
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="join"></a><strong>join</strong> (channel)</dt>
|
||||
<dd>
|
||||
Join a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel to join
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="notice"></a><strong>notice</strong> (name, message)</dt>
|
||||
<dd>
|
||||
Send a notice to a user or channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
name: User or channel to send the notice to
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: Message to send
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="part"></a><strong>part</strong> (channel)</dt>
|
||||
<dd>
|
||||
Leave a channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
channel: Channel to leave
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="quit"></a><strong>quit</strong> (message)</dt>
|
||||
<dd>
|
||||
Close the connection to the irc server.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
message: Quit message (optional, defaults to 'Leaving')
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="register_callback"></a><strong>register_callback</strong> (name, fn)</dt>
|
||||
<dd>
|
||||
Register a user function to be called when a specific event occurs.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
name: Name of the event
|
||||
</li>
|
||||
|
||||
<li>
|
||||
fn: Function to call when the event occurs, or nil to clear the callback for this event
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Return value:</h3>
|
||||
Value of the original callback for this event (or nil if no previous callback had been set)
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="say"></a><strong>say</strong> (name, message)</dt>
|
||||
<dd>
|
||||
Send a message to a user or channel.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
name: User or channel to send the message to
|
||||
</li>
|
||||
|
||||
<li>
|
||||
message: Message to send
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="send"></a><strong>send</strong> (command, ...)</dt>
|
||||
<dd>
|
||||
Send a raw IRC command.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
command: String containing the raw IRC command
|
||||
</li>
|
||||
|
||||
<li>
|
||||
...: Arguments to the command. Each argument is either a string or an array. Strings are sent literally, arrays are CTCP quoted as a group. The last argument (if it exists) is preceded by a : (so it may contain spaces).
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="server_time"></a><strong>server_time</strong> (cb)</dt>
|
||||
<dd>
|
||||
Request the current time of the server you are connected to.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback will contain the fields: <ul> <li><i>server:</i> the server which responded to the request</li> <li><i>time:</i> the time reported by the server</li> </ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="server_version"></a><strong>server_version</strong> (cb)</dt>
|
||||
<dd>
|
||||
Request the version of the IRC server you are currently connected to.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback will contain the fields: <ul> <li><i>server:</i> the server which responded to the request</li> <li><i>version:</i> the server version</li> <li><i>comments:</i> other data provided by the server</li> </ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="set_ip"></a><strong>set_ip</strong> (new_ip)</dt>
|
||||
<dd>
|
||||
Set the local IP manually (to allow for NAT workarounds)
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
new_ip: IP address to set
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
|
||||
|
||||
<dt><a name="whois"></a><strong>whois</strong> (cb, nick)</dt>
|
||||
<dd>
|
||||
Request WHOIS information about a given user.
|
||||
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
cb: Callback to call when the information is available. The single table parameter to this callback may contain any or all of the fields: <ul> <li><i>nick:</i> the nick that was passed to this function (this field will always be here)</li> <li><i>user:</i> the IRC username of the user</li> <li><i>host:</i> the user's hostname</li> <li><i>realname:</i> the IRC realname of the user</li> <li><i>server:</i> the IRC server the user is connected to</li> <li><i>serverinfo:</i> arbitrary information about the above server</li> <li><i>awaymsg:</i> set to the user's away message if they are away</li> <li><i>is_oper:</i> true if the user is an IRCop</li> <li><i>idle_time:</i> amount of time the user has been idle</li> <li><i>channels:</i> array containing the channels the user has joined</li> </ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
nick: User to request WHOIS information about
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.message</strong></li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.misc.html">irc.misc</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.message</code></h1>
|
||||
|
||||
<p>This module contains parsing functions for IRC server messages.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../luadoc.css" type="text/css" />
|
||||
<!--meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
<div id="main">
|
||||
|
||||
<div id="navigation">
|
||||
|
||||
|
||||
<h1>LuaDoc</h1>
|
||||
<ul>
|
||||
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- Module list -->
|
||||
|
||||
<h1>Modules</h1>
|
||||
<ul>
|
||||
|
||||
<li>
|
||||
<a href="../modules/callbacks.html">callbacks</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.html">irc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.channel.html">irc.channel</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.constants.html">irc.constants</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.ctcp.html">irc.ctcp</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.dcc.html">irc.dcc</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.debug.html">irc.debug</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="../modules/irc.message.html">irc.message</a>
|
||||
</li>
|
||||
|
||||
<li><strong>irc.misc</strong></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<!-- File list -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div><!-- id="navigation" -->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>irc.misc</code></h1>
|
||||
|
||||
<p>This module contains various useful functions which didn't fit in any of the other modules.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
|
||||
</div> <!-- id="main" -->
|
||||
|
||||
<div id="about">
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
|
||||
</div> <!-- id="about" -->
|
||||
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
@ -1,20 +0,0 @@
|
||||
LuaSocket 2.0 license
|
||||
Copyright © 2004-2005 Diego Nehab
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
@ -1,54 +0,0 @@
|
||||
What's New
|
||||
|
||||
There is no big change for the 2.0 (final) release. It is
|
||||
basically a bug fix release. The main improvement is in the
|
||||
non-blocking support.
|
||||
|
||||
* New: sample module dispatch.lua implements a coroutine
|
||||
based dispatcher;
|
||||
* New: sample check-links.lua works both in blocking and
|
||||
non-blocking mode using coroutines (using the new
|
||||
dispatcher);
|
||||
* New: sample forward.lua implements a coroutine based
|
||||
forward server (using the new dispatcher);
|
||||
* Improved: tcp:send(data, i, j) to return (i+sent-1). This
|
||||
is great for non-blocking I/O, but might break some code;
|
||||
* Improved: HTTP, SMTP, and FTP functions to accept a new
|
||||
field create that overrides the function used to create
|
||||
socket objects;
|
||||
* Improved: smtp.message now supports multipart/alternative
|
||||
(for the HTML messages we all love so much);
|
||||
* Fixed: smtp.send was hanging on errors returned by LTN12
|
||||
sources;
|
||||
* Fixed: url.absolute() to work when base_url is in parsed
|
||||
form;
|
||||
* Fixed: http.request() not to redirect when the location
|
||||
header is empty (naughty servers...);
|
||||
* Fixed: tcp{client}:shutdown() to check for class instead
|
||||
of group;
|
||||
* Fixed: The manual to stop using socket.try() in place of
|
||||
assert(), since it can't;
|
||||
* Improved: Got rid of package.loaded.base = _G kludge;
|
||||
* Fixed: Parts of the manual referred to require("http")
|
||||
instead of require("socket.http");
|
||||
* Improved: Socket and MIME binaries are called 'core' each
|
||||
inside their directory (ex. "socket/core.dll"). The 'l'
|
||||
prefix was just a bad idea;
|
||||
* Improved: Using bundles in Mac OS X, instead of dylibs;
|
||||
* Fixed: luasocket.h to export luaopen_socket_core;
|
||||
* Fixed: udp:setpeername() so you can "disconnect" an UDP
|
||||
socket;
|
||||
* Fixed: A weird bug in HTTP support that caused some
|
||||
requests to fail (Florian Berger);
|
||||
* Fixed: Bug in socket.select() that caused sockets with
|
||||
descriptor 0 to be ignored (Renato Maia);
|
||||
* Fixed: "Bug" that caused dns.toip() to crash under uLinux
|
||||
(William Trenker);
|
||||
* Fixed: "Bug" that caused gethostbyname to crash under VMS
|
||||
(Renato Maia);
|
||||
* Fixed: tcp:send("") to return 0 bytes sent (Alexander
|
||||
Marinov);
|
||||
* Improved: socket.DEBUG and socket.VERSION became
|
||||
socket._DEBUGs and socket._VERSION for uniformity with other
|
||||
libraries;
|
||||
* Improved: socket.select now works on empty sets on Windows.
|
@ -1,6 +0,0 @@
|
||||
This is the LuaSocket 2.0. It has been tested on WinXP, Mac OS X,
|
||||
and Linux. Please use the Lua mailing list to report any bugs
|
||||
(or "features") you encounter.
|
||||
|
||||
Have fun,
|
||||
Diego Nehab.
|
@ -1,132 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: DNS support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, DNS, Network, Library, Support">
|
||||
<title>LuaSocket: DNS support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- dns ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=dns>DNS</h2>
|
||||
|
||||
<p>
|
||||
Name resolution functions return <em>all</em> information obtained from the
|
||||
resolver in a table of the form:
|
||||
</p>
|
||||
|
||||
<blockquote><tt>
|
||||
resolved = {<br>
|
||||
name = <i>canonic-name</i>,<br>
|
||||
alias = <i>alias-list</i>,<br>
|
||||
ip = <i>ip-address-list</i><br>
|
||||
}
|
||||
</tt> </blockquote>
|
||||
|
||||
<p>
|
||||
Note that the <tt>alias</tt> list can be empty.
|
||||
</p>
|
||||
|
||||
<!-- gethostname ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=gethostname>
|
||||
socket.dns.<b>gethostname()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns the standard host name for the machine as a string.
|
||||
</p>
|
||||
|
||||
<!-- tohostname +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=tohostname>
|
||||
socket.dns.<b>tohostname(</b>address<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Converts from IP address to host name.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Address</tt> can be an IP address or host name.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a string with the canonic host name of the given
|
||||
<tt>address</tt>, followed by a table with all information returned by
|
||||
the resolver. In case of error, the function returns <b><tt>nil</tt></b>
|
||||
followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- toip +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=toip>
|
||||
socket.dns.<b>toip(</b>address<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Converts from host name to IP address.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Address</tt> can be an IP address or host name.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Returns a string with the first IP address found for <tt>address</tt>,
|
||||
followed by a table with all information returned by the resolver.
|
||||
In case of error, the function returns <b><tt>nil</tt></b> followed by an error
|
||||
message.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:56:09 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,289 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: FTP support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, FTP, Network, Library, Support">
|
||||
<title>LuaSocket: FTP support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- ftp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=ftp>FTP</h2>
|
||||
|
||||
<p>
|
||||
FTP (File Transfer Protocol) is a protocol used to transfer files
|
||||
between hosts. The <tt>ftp</tt> namespace offers thorough support
|
||||
to FTP, under a simple interface. The implementation conforms to
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc0959.txt">RFC 959</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
High level functions are provided supporting the most common operations.
|
||||
These high level functions are implemented on top of a lower level
|
||||
interface. Using the low-level interface, users can easily create their
|
||||
own functions to access <em>any</em> operation supported by the FTP
|
||||
protocol. For that, check the implementation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To really benefit from this module, a good understanding of
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">
|
||||
LTN012, Filters sources and sinks</a> is necessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>ftp</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the FTP module and any libraries it requires
|
||||
local ftp = require("socket.ftp")
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
URLs MUST conform to
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
|
||||
1738</a>, that is, an URL is a string in the form:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<tt>
|
||||
[ftp://][<user>[:<password>]@]<host>[:<port>][/<path>][<i>type</i>=a|i]</tt>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
The following constants in the namespace can be set to control the default behavior of
|
||||
the FTP module:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <tt>PASSWORD</tt>: default anonymous password.
|
||||
<li> <tt>PORT</tt>: default port used for the control connection;
|
||||
<li> <tt>TIMEOUT</tt>: sets the timeout for all I/O operations;
|
||||
<li> <tt>USER</tt>: default anonymous user;
|
||||
</ul>
|
||||
|
||||
|
||||
<!-- ftp.get ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=get>
|
||||
ftp.<b>get(</b>url<b>)</b><br>
|
||||
ftp.<b>get{</b><br>
|
||||
host = <i>string</i>,<br>
|
||||
sink = <i>LTN12 sink</i>,<br>
|
||||
argument <i>or</i> path = <i>string</i>,<br>
|
||||
[user = <i>string</i>,]<br>
|
||||
[password = <i>string</i>]<br>
|
||||
[command = <i>string</i>,]<br>
|
||||
[port = <i>number</i>,]<br>
|
||||
[type = <i>string</i>,]<br>
|
||||
[step = <i>LTN12 pump step</i>,]<br>
|
||||
[create = <i>function</i>]<br>
|
||||
<b>}</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
The <tt>get</tt> function has two forms. The simple form has fixed
|
||||
functionality: it downloads the contents of a URL and returns it as a
|
||||
string. The generic form allows a <em>lot</em> more control, as explained
|
||||
below.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
If the argument of the <tt>get</tt> function is a table, the function
|
||||
expects at least the fields <tt>host</tt>, <tt>sink</tt>, and one of
|
||||
<tt>argument</tt> or <tt>path</tt> (<tt>argument</tt> takes
|
||||
precedence). <tt>Host</tt> is the server to connect to. <tt>Sink</tt> is
|
||||
the <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
sink that will receive the downloaded data. <tt>Argument</tt> or
|
||||
<tt>path</tt> give the target path to the resource in the server. The
|
||||
optional arguments are the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>user</tt>, <tt>password</tt>: User name and password used for
|
||||
authentication. Defaults to "<tt>ftp:anonymous@anonymous.org</tt>";
|
||||
<li><tt>command</tt>: The FTP command used to obtain data. Defaults to
|
||||
"<tt>retr</tt>", but see example below;
|
||||
<li><tt>port</tt>: The port to used for the control connection. Defaults to 21;
|
||||
<li><tt>type</tt>: The transfer mode. Can take values "<tt>i</tt>" or
|
||||
"<tt>a</tt>". Defaults to whatever is the server default;
|
||||
<li><tt>step</tt>:
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
pump step function used to pass data from the
|
||||
server to the sink. Defaults to the LTN12 <tt>pump.step</tt> function;
|
||||
<li><tt>create</tt>: An optional function to be used instead of
|
||||
<a href=tcp.html#socket.tcp><tt>socket.tcp</tt></a> when the communications socket is created.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
If successful, the simple version returns the URL contents as a
|
||||
string, and the generic function returns 1. In case of error, both
|
||||
functions return <b><tt>nil</tt></b> and an error message describing the
|
||||
error.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ftp support
|
||||
local ftp = require("socket.ftp")
|
||||
|
||||
-- Log as user "anonymous" on server "ftp.tecgraf.puc-rio.br",
|
||||
-- and get file "lua.tar.gz" from directory "pub/lua" as binary.
|
||||
f, e = ftp.get("ftp://ftp.tecgraf.puc-rio.br/pub/lua/lua.tar.gz;type=i")
|
||||
</pre>
|
||||
|
||||
<pre class=example>
|
||||
-- load needed modules
|
||||
local ftp = require("socket.ftp")
|
||||
local ltn12 = require("ltn12")
|
||||
local url = require("socket.url")
|
||||
|
||||
-- a function that returns a directory listing
|
||||
function nlst(u)
|
||||
local t = {}
|
||||
local p = url.parse(u)
|
||||
p.command = "nlst"
|
||||
p.sink = ltn12.sink.table(t)
|
||||
local r, e = ftp.get(p)
|
||||
return r and table.concat(t), e
|
||||
end
|
||||
</pre>
|
||||
|
||||
<!-- put ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=put>
|
||||
ftp.<b>put(</b>url, content<b>)</b><br>
|
||||
ftp.<b>put{</b><br>
|
||||
host = <i>string</i>,<br>
|
||||
source = <i>LTN12 sink</i>,<br>
|
||||
argument <i>or</i> path = <i>string</i>,<br>
|
||||
[user = <i>string</i>,]<br>
|
||||
[password = <i>string</i>]<br>
|
||||
[command = <i>string</i>,]<br>
|
||||
[port = <i>number</i>,]<br>
|
||||
[type = <i>string</i>,]<br>
|
||||
[step = <i>LTN12 pump step</i>,]<br>
|
||||
[create = <i>function</i>]<br>
|
||||
<b>}</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
The <tt>put</tt> function has two forms. The simple form has fixed
|
||||
functionality: it uploads a string of content into a URL. The generic form
|
||||
allows a <em>lot</em> more control, as explained below.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
If the argument of the <tt>put</tt> function is a table, the function
|
||||
expects at least the fields <tt>host</tt>, <tt>source</tt>, and one of
|
||||
<tt>argument</tt> or <tt>path</tt> (<tt>argument</tt> takes
|
||||
precedence). <tt>Host</tt> is the server to connect to. <tt>Source</tt> is
|
||||
the <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
source that will provide the contents to be uploaded.
|
||||
<tt>Argument</tt> or
|
||||
<tt>path</tt> give the target path to the resource in the server. The
|
||||
optional arguments are the following:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>user</tt>, <tt>password</tt>: User name and password used for
|
||||
authentication. Defaults to "<tt>ftp:anonymous@anonymous.org</tt>";
|
||||
<li><tt>command</tt>: The FTP command used to send data. Defaults to
|
||||
"<tt>stor</tt>", but see example below;
|
||||
<li><tt>port</tt>: The port to used for the control connection. Defaults to 21;
|
||||
<li><tt>type</tt>: The transfer mode. Can take values "<tt>i</tt>" or
|
||||
"<tt>a</tt>". Defaults to whatever is the server default;
|
||||
<li><tt>step</tt>:
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
pump step function used to pass data from the
|
||||
server to the sink. Defaults to the LTN12 <tt>pump.step</tt> function;
|
||||
<li><tt>create</tt>: An optional function to be used instead of
|
||||
<a href=tcp.html#socket.tcp><tt>socket.tcp</tt></a> when the communications socket is created.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
Both functions return 1 if successful, or <b><tt>nil</tt></b> and an error
|
||||
message describing the reason for failure.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ftp support
|
||||
local ftp = require("socket.ftp")
|
||||
|
||||
-- Log as user "fulano" on server "ftp.example.com",
|
||||
-- using password "silva", and store a file "README" with contents
|
||||
-- "wrong password, of course"
|
||||
f, e = ftp.put("ftp://fulano:silva@ftp.example.com/README",
|
||||
"wrong password, of course")
|
||||
</pre>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ftp support
|
||||
local ftp = require("socket.ftp")
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- Log as user "fulano" on server "ftp.example.com",
|
||||
-- using password "silva", and append to the remote file "LOG", sending the
|
||||
-- contents of the local file "LOCAL-LOG"
|
||||
f, e = ftp.put{
|
||||
host = "ftp.example.com",
|
||||
user = "fulano",
|
||||
password = "silva",
|
||||
command = "appe",
|
||||
argument = "LOG",
|
||||
source = ltn12.source.file(io.open("LOCAL-LOG", "r"))
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:56:32 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,256 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="The LuaSocket Homepage">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Network, Library, Support, Internet">
|
||||
<title>LuaSocket: Network support for the Lua language </title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- whatis +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=whatis>What is LuaSocket?</h2>
|
||||
|
||||
<p>
|
||||
LuaSocket is a <a href="http://www.lua.org">Lua</a> extension library
|
||||
that is composed by two parts: a C core that provides support for the TCP
|
||||
and UDP transport layers, and a set of Lua modules that add support for
|
||||
functionality commonly needed by applications that deal with the Internet.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The core support has been implemented so that it is both efficient and
|
||||
simple to use. It is available to any Lua application once it has been
|
||||
properly initialized by the interpreter in use. The code has been tested
|
||||
and runs well on several Windows and Unix platforms. </p>
|
||||
|
||||
<p>
|
||||
Among the support modules, the most commonly used implement the
|
||||
<a href=smtp.html>SMTP</a>
|
||||
(sending e-mails),
|
||||
<a href=http.html>HTTP</a>
|
||||
(WWW access) and
|
||||
<a href=ftp.html>FTP</a>
|
||||
(uploading and downloading files) client
|
||||
protocols. These provide a very natural and generic interface to the
|
||||
functionality defined by each protocol.
|
||||
In addition, you will find that the
|
||||
<a href=mime.html>MIME</a> (common encodings),
|
||||
<a href=url.html>URL</a>
|
||||
(anything you could possible want to do with one) and
|
||||
<a href=ltn12.html>LTN12</a>
|
||||
(filters, sinks, sources and pumps) modules can be very handy.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The library is available under the same
|
||||
<a href="http://www.lua.org/copyright.html">
|
||||
terms and conditions</a> as the Lua language, the MIT license. The idea is
|
||||
that if you can use Lua in a project, you should also be able to use
|
||||
LuaSocket.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Copyright © 2004-2005 Diego Nehab. All rights reserved. <br>
|
||||
Author: <A href="http://www.cs.princeton.edu/~diego">Diego Nehab</a>
|
||||
</p>
|
||||
|
||||
<!-- download +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=download>Download</h2>
|
||||
|
||||
<p>
|
||||
LuaSocket version 2.0 (final) is now available for download! It is
|
||||
compatible with Lua 5.0 and has been tested on
|
||||
Windows XP, Linux, and Mac OS X.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The library can be downloaded in source code from the
|
||||
<a href=http://luaforge.net/projects/luasocket/>LuaSocket
|
||||
project page</a> at LuaForge.
|
||||
Besides the full C and Lua source code for the library, the distribution
|
||||
contains several examples, this user's manual and basic test procedures.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Danilo Tuler is maintaining Win32 binaries for LuaSocket, which are also
|
||||
available from LuaForge. These are compatible with the
|
||||
<a href=http://luaforge.net/projects/luabinaries>LuaBinaries</a>
|
||||
available from LuaForge.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For those that want to give LuaSocket a quick try, download the
|
||||
stand-alone archive and unpack everything into
|
||||
a directory, say <tt>c:\luasocket</tt>. Then set <tt>LUA_INIT</tt> to load
|
||||
the <tt>compat-5.1.lua</tt> and set <tt>LUA_PATH</tt> and
|
||||
<tt>LUA_CPATH</tt> to look for files in the current directory:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
c:\luasocket\> set LUA_INIT=@c:\luasocket\compat-5.1.lua
|
||||
c:\luasocket\> set LUA_CPATH=?.dll
|
||||
c:\luasocket\> set LUA_PATH=?.lua
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
From that directory, you can then run the interpreter and it should find all
|
||||
files it needs. To download this manual page from the Internet, for example,
|
||||
do the following:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
c:\luasocket\> lua50
|
||||
Lua 5.0.2 Copyright (C) 1994-2004 Tecgraf, PUC-Rio
|
||||
> http = require"socket.http"
|
||||
> print(http.request"http://www.cs.princeton.edu/~diego/professional/luasocket/")
|
||||
--> the source to this web page gets dumped to terminal
|
||||
</pre>
|
||||
|
||||
<p> When you are done playing, take a look at the
|
||||
<a href=installation.html>installation</a> section of the manual to find out
|
||||
how to properly install the library. </p>
|
||||
|
||||
<!-- thanks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=thanks>Special thanks</h2>
|
||||
|
||||
<p>
|
||||
Throughout LuaSocket's history, many people gave suggestions that helped
|
||||
improve it. For that, I thank the Lua community.
|
||||
Special thanks go to
|
||||
David Burgess, who has helped push the library to a new level of quality and
|
||||
from whom I have learned a lot of stuff that doesn't show up in RFCs.
|
||||
Special thanks also to Carlos Cassino, who played a big part in the
|
||||
extensible design seen in the C core of LuaSocket 2.0. Recently, Mike Pall
|
||||
has been helping a lot too! Thanks to you all!
|
||||
</p>
|
||||
|
||||
<!-- whatsnew +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=new>What's New</h2>
|
||||
|
||||
<p>
|
||||
There is no big change for the 2.0 (final) release. It is basically a
|
||||
bug fix release. The only improvement is in the non-blocking
|
||||
support.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> New: sample module <tt>dispatch.lua</tt> implements a
|
||||
coroutine based dispatcher;
|
||||
<li> New: sample <tt>check-links.lua</tt> works
|
||||
both in blocking and non-blocking mode using coroutines
|
||||
(using the new dispatcher);
|
||||
<li> New: sample <tt>forward.lua</tt> implements a coroutine
|
||||
based forward server (using the new dispatcher);
|
||||
<li> Improved: <tt>tcp:send(data, i, j)</tt> to return <tt>(i+sent-1)</tt>. This is great for non-blocking I/O, but might break some code;
|
||||
<li> Improved: HTTP, SMTP, and FTP functions to accept a new field
|
||||
<tt>create</tt> that overrides the function used to create socket objects;
|
||||
<li> Improved: <tt>smtp.message</tt> now supports multipart/alternative
|
||||
(for the HTML messages we all love so much);
|
||||
<li> Fixed: <tt>smtp.send</tt> was hanging on errors returned by LTN12 sources;
|
||||
<li> Fixed: <tt>url.absolute()</tt> to work when <tt>base_url</tt> is in
|
||||
parsed form;
|
||||
<li> Fixed: <tt>http.request()</tt> not to redirect when the location
|
||||
header is empty (naughty servers...);
|
||||
<li> Fixed: <tt>tcp{client}:shutdown()</tt> to check for class instead of
|
||||
group;
|
||||
<li> Fixed: The manual to stop using <tt>socket.try()</tt> in place of
|
||||
<tt>assert()</tt>, since it can't;
|
||||
<li> Improved: Got rid of <tt>package.loaded.base = _G</tt> kludge;
|
||||
<li> Fixed: Parts of the manual referred to <tt>require("http")</tt> instead of
|
||||
<tt>require("socket.http")</tt>;
|
||||
<li> Improved: Socket and MIME binaries are called 'core' each inside their
|
||||
directory (ex. "socket/core.dll"). The 'l' prefix was just a bad idea;
|
||||
<li> Improved: Using bundles in Mac OS X, instead of dylibs;
|
||||
<li> Fixed: <tt>luasocket.h</tt> to export <tt>luaopen_socket_core</tt>;
|
||||
<li> Fixed: <tt>udp:setpeername()</tt> so you can "disconnect" an
|
||||
<tt>UDP</tt> socket;
|
||||
<li> Fixed: A weird bug in HTTP support that caused some requests to
|
||||
fail (Florian Berger);
|
||||
<li> Fixed: Bug in <tt>socket.select()</tt> that caused sockets
|
||||
with descriptor 0 to be ignored (Renato Maia);
|
||||
<li> Fixed: "Bug" that caused <tt>dns.toip()</tt> to crash under uLinux
|
||||
(William Trenker);
|
||||
<li> Fixed: "Bug" that caused <tt>gethostbyname</tt> to crash under VMS
|
||||
(Renato Maia);
|
||||
<li> Fixed: <tt>tcp:send("")</tt> to return 0 bytes sent (Alexander Marinov);
|
||||
<li> Improved: <tt>socket.DEBUG</tt> and <tt>socket.VERSION</tt> became <tt>socket._DEBUGs</tt> and <tt>socket._VERSION</tt> for uniformity with other libraries;
|
||||
<li> Improved: <tt>socket.select</tt> now works on empty sets on Windows.
|
||||
</ul>
|
||||
|
||||
<!-- incompatible +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=incompatible>Incompatibilities with previous versions</h3>
|
||||
|
||||
<ul>
|
||||
<li> If you use the return value of <tt>tcp:send()</tt> <em>and</em> you
|
||||
use the extra parameters to select only part of the string to be sent, your
|
||||
code is now broken, but when you fix it, it will be much simpler;
|
||||
<li> If you check <tt>socket.DEBUG</tt> or <tt>socket.VERSION</tt>,
|
||||
change it to <tt>socket._DEBUG</tt> or <tt>socket._VERSION</tt>.
|
||||
</ul>
|
||||
|
||||
<!-- old ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=old>Old Versions</h2>
|
||||
|
||||
<p>
|
||||
All previous versions of the LuaSocket library can be downloaded <a
|
||||
href="http://www.cs.princeton.edu/~diego/professional/luasocket/old">
|
||||
here</a>. Although these versions are no longer supported, they are
|
||||
still available for those that have compatibility issues.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:56:56 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,325 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: HTTP support">
|
||||
<meta name="keywords" content="Lua, HTTP, Library, WWW, Browser, Network, Support">
|
||||
<title>LuaSocket: HTTP support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- http +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=http>HTTP</h2>
|
||||
|
||||
<p>
|
||||
HTTP (Hyper Text Transfer Protocol) is the protocol used to exchange
|
||||
information between web-browsers and servers. The <tt>http</tt>
|
||||
namespace offers full support for the client side of the HTTP
|
||||
protocol (i.e.,
|
||||
the facilities that would be used by a web-browser implementation). The
|
||||
implementation conforms to the HTTP/1.1 standard,
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
|
||||
2616</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The module exports functions that provide HTTP functionality in different
|
||||
levels of abstraction. From the simple
|
||||
string oriented requests, through generic
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> based, down to even lower-level if you bother to look through the source code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>http</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the HTTP module and any libraries it requires
|
||||
local http = require("socket.http")
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
URLs must conform to
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc1738.txt">RFC
|
||||
1738</a>,
|
||||
that is, an URL is a string in the form:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
[http://][<user>[:<password>]@]<host>[:<port>][/<path>]
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
MIME headers are represented as a Lua table in the form:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<table summary="MIME headers in Lua table">
|
||||
<tr><td><tt>
|
||||
headers = {<br>
|
||||
field-1-name = <i>field-1-value</i>,<br>
|
||||
field-2-name = <i>field-2-value</i>,<br>
|
||||
field-3-name = <i>field-3-value</i>,<br>
|
||||
...<br>
|
||||
field-n-name = <i>field-n-value</i><br>
|
||||
}
|
||||
</tt></td></tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
Field names are case insensitive (as specified by the standard) and all
|
||||
functions work with lowercase field names.
|
||||
Field values are left unmodified.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: MIME headers are independent of order. Therefore, there is no problem
|
||||
in representing them in a Lua table.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following constants can be set to control the default behavior of
|
||||
the HTTP module:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <tt>PORT</tt>: default port used for connections;
|
||||
<li> <tt>PROXY</tt>: default proxy used for connections;
|
||||
<li> <tt>TIMEOUT</tt>: sets the timeout for all I/O operations;
|
||||
<li> <tt>USERAGENT</tt>: default user agent reported to server.
|
||||
</ul>
|
||||
|
||||
<!-- http.request ++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=request>
|
||||
http.<b>request(</b>url [, body]<b>)</b><br>
|
||||
http.<b>request{</b><br>
|
||||
url = <i>string</i>,<br>
|
||||
[sink = <i>LTN12 sink</i>,]<br>
|
||||
[method = <i>string</i>,]<br>
|
||||
[headers = <i>header-table</i>,]<br>
|
||||
[source = <i>LTN12 source</i>],<br>
|
||||
[step = <i>LTN12 pump step</i>,]<br>
|
||||
[proxy = <i>string</i>,]<br>
|
||||
[redirect = <i>boolean</i>,]<br>
|
||||
[create = <i>function</i>]<br>
|
||||
<b>}</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
The request function has two forms. The simple form downloads
|
||||
a URL using the <tt>GET</tt> or <tt>POST</tt> method and is based
|
||||
on strings. The generic form performs any HTTP method and is
|
||||
<a href=http://lua-users.org/wiki/FiltersSourcesAndSinks>LTN12</a> based.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
If the first argument of the <tt>request</tt> function is a string, it
|
||||
should be an <tt>url</tt>. In that case, if a <tt>body</tt>
|
||||
is provided as a string, the function will perform a <tt>POST</tt> method
|
||||
in the <tt>url</tt>. Otherwise, it performs a <tt>GET</tt> in the
|
||||
<tt>url</tt>
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
If the first argument is instead a table, the most important fields are
|
||||
the <tt>url</tt> and the <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
<tt>sink</tt> that will receive the downloaded content.
|
||||
Any part of the <tt>url</tt> can be overridden by including
|
||||
the appropriate field in the request table.
|
||||
If authentication information is provided, the function
|
||||
uses the Basic Authentication Scheme (see <a href="#authentication">note</a>)
|
||||
to retrieve the document. If <tt>sink</tt> is <tt><b>nil</b></tt>, the
|
||||
function discards the downloaded data. The optional parameters are the
|
||||
following:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>method</tt>: The HTTP request method. Defaults to "GET";
|
||||
<li><tt>headers</tt>: Any additional HTTP headers to send with the request;
|
||||
<li><tt>source</tt>: <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
source to provide the request body. If there
|
||||
is a body, you need to provide an appropriate "<tt>content-length</tt>"
|
||||
request header field, or the function will attempt to send the body as
|
||||
"<tt>chunked</tt>" (something few servers support). Defaults to the empty source;
|
||||
<li><tt>step</tt>:
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
pump step function used to move data.
|
||||
Defaults to the LTN12 <tt>pump.step</tt> function.
|
||||
<li><tt>proxy</tt>: The URL of a proxy server to use. Defaults to no proxy;
|
||||
<li><tt>redirect</tt>: Set to <tt><b>false</b></tt> to prevent the
|
||||
function from automatically following 301 or 302 server redirect messages;
|
||||
<li><tt>create</tt>: An optional function to be used instead of
|
||||
<a href=tcp.html#socket.tcp><tt>socket.tcp</tt></a> when the communications socket is created.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
In case of failure, the function returns <tt><b>nil</b></tt> followed by an
|
||||
error message. If successful, the simple form returns the response
|
||||
body as a string, followed by the response status code, the response
|
||||
headers and the response status line. The complex function returns the same
|
||||
information, except the first return value is just the number 1 (the body
|
||||
goes to the <tt>sink</tt>).
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Even when the server fails to provide the contents of the requested URL (URL not found, for example),
|
||||
it usually returns a message body (a web page informing the
|
||||
URL was not found or some other useless page). To make sure the
|
||||
operation was successful, check the returned status <tt>code</tt>. For
|
||||
a list of the possible values and their meanings, refer to <a
|
||||
href="http://www.cs.princeton.edu/~diego/rfc/rfc2616.txt">RFC
|
||||
2616</a>.
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Here are a few examples with the simple interface:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the http module
|
||||
local io = require("io")
|
||||
local http = require("socket.http")
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- connect to server "www.cs.princeton.edu" and retrieves this manual
|
||||
-- file from "~diego/professional/luasocket/http.html" and print it to stdout
|
||||
http.request{
|
||||
url = "http://www.cs.princeton.edu/~diego/professional/luasocket/http.html",
|
||||
sink = ltn12.sink.file(io.stdout)
|
||||
}
|
||||
|
||||
-- connect to server "www.example.com" and tries to retrieve
|
||||
-- "/private/index.html". Fails because authentication is needed.
|
||||
b, c, h = http.request("http://www.example.com/private/index.html")
|
||||
-- b returns some useless page telling about the denied access,
|
||||
-- h returns authentication information
|
||||
-- and c returns with value 401 (Authentication Required)
|
||||
|
||||
-- tries to connect to server "wrong.host" to retrieve "/"
|
||||
-- and fails because the host does not exist.
|
||||
r, e = http.request("http://wrong.host/")
|
||||
-- r is nil, and e returns with value "host not found"
|
||||
</pre>
|
||||
|
||||
<p class=description>
|
||||
And here is an example using the generic interface:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the http module
|
||||
http = require("socket.http")
|
||||
|
||||
-- Requests information about a document, without downloading it.
|
||||
-- Useful, for example, if you want to display a download gauge and need
|
||||
-- to know the size of the document in advance
|
||||
r, c, h = http.request {
|
||||
method = "HEAD",
|
||||
url = "http://www.tecgraf.puc-rio.br/~diego"
|
||||
}
|
||||
-- r is 1, c is 200, and h would return the following headers:
|
||||
-- h = {
|
||||
-- date = "Tue, 18 Sep 2001 20:42:21 GMT",
|
||||
-- server = "Apache/1.3.12 (Unix) (Red Hat/Linux)",
|
||||
-- ["last-modified"] = "Wed, 05 Sep 2001 06:11:20 GMT",
|
||||
-- ["content-length"] = 15652,
|
||||
-- ["connection"] = "close",
|
||||
-- ["content-Type"] = "text/html"
|
||||
-- }
|
||||
</pre>
|
||||
|
||||
<p class=note id=authentication>
|
||||
Note: Some URLs are protected by their
|
||||
servers from anonymous download. For those URLs, the server must receive
|
||||
some sort of authentication along with the request or it will deny
|
||||
download and return status "401 Authentication Required".
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
The HTTP/1.1 standard defines two authentication methods: the Basic
|
||||
Authentication Scheme and the Digest Authentication Scheme, both
|
||||
explained in detail in
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2068.txt">RFC 2068</a>.
|
||||
</p>
|
||||
|
||||
<p class=note>The Basic Authentication Scheme sends
|
||||
<tt><user></tt> and
|
||||
<tt><password></tt> unencrypted to the server and is therefore
|
||||
considered unsafe. Unfortunately, by the time of this implementation,
|
||||
the wide majority of servers and browsers support the Basic Scheme only.
|
||||
Therefore, this is the method used by the toolkit whenever
|
||||
authentication is required.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load required modules
|
||||
http = require("socket.http")
|
||||
mime = require("mime")
|
||||
|
||||
-- Connect to server "www.example.com" and tries to retrieve
|
||||
-- "/private/index.html", using the provided name and password to
|
||||
-- authenticate the request
|
||||
b, c, h = http.request("http://fulano:silva@www.example.com/private/index.html")
|
||||
|
||||
-- Alternatively, one could fill the appropriate header and authenticate
|
||||
-- the request directly.
|
||||
r, c = http.request {
|
||||
url = "http://www.example.com/private/index.html",
|
||||
headers = { authentication = "Basic " .. (mime.b64("fulano:silva")) }
|
||||
}
|
||||
</pre>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:03 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,161 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: Introduction to the core">
|
||||
<meta name="keywords" content="Lua, LuaSocket, TCP, UDP, Network, Support,
|
||||
Installation">
|
||||
<title>LuaSocket: Installation</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- installation ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2>Installation</h2>
|
||||
|
||||
<p> LuaSocket 2.0 uses the new package proposal for Lua 5.1.
|
||||
All Lua library developers are encouraged to update their libraries so that
|
||||
all libraries can coexist peacefully and users can benefit from the
|
||||
standardization and flexibility of the standard.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The proposal was considered important enough by some of us to justify
|
||||
early adoption, even before release of Lua 5.1.
|
||||
Thus, a compatibility module
|
||||
<a href=http://www.keplerproject.org/compat/>compat-5.1</a>
|
||||
has been released in conjunction with Roberto Ierusalimschy and <a
|
||||
href=http://www.keplerproject.org/>The Kepler Project</a> team.
|
||||
It implements the Lua 5.1 package proposal on top of Lua 5.0. </p>
|
||||
|
||||
<p> As far as LuaSocket is concerned, this means that whoever is
|
||||
deploying a non-standard distribution of LuaSocket will probably
|
||||
have no problems customizing it. Here we will only describe the standard distribution. If the standard doesn't meet your
|
||||
needs, we refer you to the Lua discussion list, where any question about
|
||||
the package scheme will likely already have been answered.
|
||||
</p>
|
||||
|
||||
<h3>Directory structure</h3>
|
||||
|
||||
<p> On Unix systems, the standard distribution uses two base
|
||||
directories, one for system dependent files, and another for system
|
||||
independent files. Let's call these directories <tt><CDIR></tt>
|
||||
and <tt><LDIR></tt>, respectively.
|
||||
For instance, in my laptop, I use '<tt>/usr/local/lib/lua/5.0</tt>' for
|
||||
<tt><CDIR></tt> and '<tt>/usr/local/share/lua/5.0</tt>' for
|
||||
<tt><LDIR></tt>. On Windows, sometimes only one directory is used, say
|
||||
'<tt>c:\program files\lua\5.0</tt>'. Here is the standard LuaSocket
|
||||
distribution directory structure:</p>
|
||||
|
||||
<pre class=example>
|
||||
<LDIR>/compat-5.1.lua
|
||||
<LDIR>/ltn12.lua
|
||||
<LDIR>/socket.lua
|
||||
<CDIR>/socket/core.dll
|
||||
<LDIR>/socket/http.lua
|
||||
<LDIR>/socket/tp.lua
|
||||
<LDIR>/socket/ftp.lua
|
||||
<LDIR>/socket/smtp.lua
|
||||
<LDIR>/socket/url.lua
|
||||
<LDIR>/mime.lua
|
||||
<CDIR>/mime/core.dll
|
||||
</pre>
|
||||
|
||||
<p> Naturally, on Unix systems, <tt>core.dll</tt>
|
||||
would be replaced by <tt>core.so</tt>.
|
||||
</p>
|
||||
|
||||
<p> In order for the interpreter to find all LuaSocket components, three
|
||||
environment variables need to be set. The first environment variable tells
|
||||
the interpreter to load the <tt>compat-5.1.lua</tt> module at startup: </p>
|
||||
|
||||
<pre class=example>
|
||||
LUA_INIT=@<LDIR>/compat-5.1.lua
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The other two environment variables instruct the compatibility module to
|
||||
look for dynamic libraries and extension modules in the appropriate
|
||||
directories and with the appropriate filename extensions.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
LUA_PATH=<LDIR>/?.lua;?.lua
|
||||
LUA_CPATH=<CDIR>/?.dll;?.dll
|
||||
</pre>
|
||||
|
||||
<p> Again, naturally, on Unix systems the shared library extension would be
|
||||
<tt>.so</tt> instead of <tt>.dll</tt>.</p>
|
||||
|
||||
<h3>Using LuaSocket</h3>
|
||||
|
||||
<p> With the above setup, and an interpreter with shared library support,
|
||||
it should be easy to use LuaSocket. Just fire the interpreter and use the
|
||||
<tt>require</tt> function to gain access to whatever module you need:</p>
|
||||
|
||||
<pre class=example>
|
||||
Lua 5.0.2 Copyright (C) 1994-2004 Tecgraf, PUC-Rio
|
||||
> socket = require("socket")
|
||||
> print(socket._VERSION)
|
||||
--> LuaSocket 2.0
|
||||
</pre>
|
||||
|
||||
<p> Each module loads their dependencies automatically, so you only need to
|
||||
load the modules you directly depend upon: </p>
|
||||
|
||||
<pre class=example>
|
||||
Lua 5.0.2 Copyright (C) 1994-2004 Tecgraf, PUC-Rio
|
||||
> http = require("socket.http")
|
||||
> print(http.request("http://www.cs.princeton.edu/~diego/professional/luasocket"))
|
||||
--> homepage gets dumped to terminal
|
||||
</pre>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:22 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,333 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: Introduction to the core">
|
||||
<meta name="keywords" content="Lua, LuaSocket, TCP, UDP, Network,
|
||||
Library, Support">
|
||||
<title>LuaSocket: Introduction to the core</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- introduction +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
<p>
|
||||
LuaSocket is a <a href="http://www.lua.org">Lua</a> extension library
|
||||
that is composed by two parts: a C core that provides support for the TCP
|
||||
and UDP transport layers, and a set of Lua modules that add support for
|
||||
the SMTP (sending e-mails), HTTP (WWW access) and FTP (uploading and
|
||||
downloading files) protocols and other functionality commonly needed by
|
||||
applications that deal with the Internet. This introduction is about the C
|
||||
core.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Communication in LuaSocket is performed via I/O objects. These can
|
||||
represent different network domains. Currently, support is provided for TCP
|
||||
and UDP, but nothing prevents other developers from implementing SSL, Local
|
||||
Domain, Pipes, File Descriptors etc. I/O objects provide a standard
|
||||
interface to I/O across different domains and operating systems.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The API design had two goals in mind. First, users
|
||||
experienced with the C API to sockets should feel comfortable using LuaSocket.
|
||||
Second, the simplicity and the feel of the Lua language should be
|
||||
preserved. To achieve these goals, the LuaSocket API keeps the function names and semantics the C API whenever possible, but their usage in Lua has been greatly simplified.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
One of the simplifications is the receive pattern capability.
|
||||
Applications can read data from stream domains (such as TCP)
|
||||
line by line, block by block, or until the connection is closed.
|
||||
All I/O reads are buffered and the performance differences between
|
||||
different receive patterns are negligible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Another advantage is the flexible timeout control
|
||||
mechanism. As in C, all I/O operations are blocking by default. For
|
||||
example, the <a href=tcp.html#send><tt>send</tt></a>,
|
||||
<a href=tcp.html#receive><tt>receive</tt></a> and
|
||||
<a href=tcp.html#accept><tt>accept</tt></a> methods
|
||||
of the TCP domain will block the caller application until
|
||||
the operation is completed (if ever!). However, with a call to the
|
||||
<a href=tcp.html#settimeout><tt>settimeout</tt></a>
|
||||
method, an application can specify upper limits on
|
||||
the time it can be blocked by LuaSocket (the "<tt>total</tt>" timeout), on
|
||||
the time LuaSocket can internally be blocked by any OS call (the
|
||||
"<tt>block</tt>" timeout) or a combination of the two. Each LuaSocket
|
||||
call might perform several OS calls, so that the two timeout values are
|
||||
<em>not</em> equivalent.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, the host name resolution is transparent, meaning that most
|
||||
functions and methods accept both IP addresses and host names. In case a
|
||||
host name is given, the library queries the system's resolver and
|
||||
tries the main IP address returned. Note that direct use of IP addresses
|
||||
is more efficient, of course. The
|
||||
<a href=dns.html#toip><tt>toip</tt></a>
|
||||
and <a href=dns.html#tohostname><tt>tohostname</tt></a>
|
||||
functions from the DNS module are provided to convert between host names and IP addresses.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Together, these changes make network programming in LuaSocket much simpler
|
||||
than it is in C, as the following sections will show.
|
||||
</p>
|
||||
|
||||
<!-- tcp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=tcp>TCP</h3>
|
||||
|
||||
<p>
|
||||
TCP (Transfer Control Protocol) is reliable stream protocol. In other
|
||||
words, applications communicating through TCP can send and receive data as
|
||||
an error free stream of bytes. Data is split in one end and
|
||||
reassembled transparently on the other end. There are no boundaries in
|
||||
the data transfers. The library allows users to read data from the
|
||||
sockets in several different granularities: patterns are available for
|
||||
lines, arbitrary sized blocks or "read up to connection closed", all with
|
||||
good performance.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The library distinguishes three types of TCP sockets: <em>master</em>,
|
||||
<em>client</em> and <em>server</em> sockets.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Master sockets are newly created TCP sockets returned by the function
|
||||
<a href=tcp.html#tcp><tt>socket.tcp</tt></a>. A master socket is
|
||||
transformed into a server socket
|
||||
after it is associated with a <em>local</em> address by a call to the
|
||||
<a href=tcp.html#bind><tt>bind</tt></a> method followed by a call to the
|
||||
<a href=tcp.html#listen><tt>listen</tt></a>. Conversely, a master socket
|
||||
can be changed into a client socket with the method
|
||||
<a href=tcp.html#connect><tt>connect</tt></a>,
|
||||
which associates it with a <em>remote</em> address.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On server sockets, applications can use the
|
||||
<a href=tcp.html#accept><tt>accept</tt></a> method
|
||||
to wait for a client connection. Once a connection is established, a
|
||||
client socket object is returned representing this connection. The
|
||||
other methods available for server socket objects are
|
||||
<a href=tcp.html#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=tcp.html#setoption><tt>setoption</tt></a>,
|
||||
<a href=tcp.html#settimeout><tt>settimeout</tt></a>, and
|
||||
<a href=tcp.html#close><tt>close</tt></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Client sockets are used to exchange data between two applications over
|
||||
the Internet. Applications can call the methods
|
||||
<a href=tcp.html#send><tt>send</tt></a> and
|
||||
<a href=tcp.html#receive><tt>receive</tt></a>
|
||||
to send and receive data. The other methods
|
||||
available for client socket objects are
|
||||
<a href=tcp.html#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=tcp.html#getpeername><tt>getpeername</tt></a>,
|
||||
<a href=tcp.html#setoption><tt>setoption</tt></a>,
|
||||
<a href=tcp.html#settimeout><tt>settimeout</tt></a>,
|
||||
<a href=tcp.html#shutdown><tt>shutdown</tt></a>, and
|
||||
<a href=tcp.html#close><tt>close</tt></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example:
|
||||
</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
A simple echo server, using LuaSocket. The program binds to an ephemeral
|
||||
port (one that is chosen by the operating system) on the local host and
|
||||
awaits client connections on that port. When a connection is established,
|
||||
the program reads a line from the remote end and sends it back, closing
|
||||
the connection immediately. You can test it using the telnet
|
||||
program.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load namespace
|
||||
local socket = require("socket")
|
||||
-- create a TCP socket and bind it to the local host, at any port
|
||||
local server = assert(socket.bind("*", 0))
|
||||
-- find out which port the OS chose for us
|
||||
local ip, port = server:getsockname()
|
||||
-- print a message informing what's up
|
||||
print("Please telnet to localhost on port " .. port)
|
||||
print("After connecting, you have 10s to enter a line to be echoed")
|
||||
-- loop forever waiting for clients
|
||||
while 1 do
|
||||
-- wait for a connection from any client
|
||||
local client = server:accept()
|
||||
-- make sure we don't block waiting for this client's line
|
||||
client:settimeout(10)
|
||||
-- receive the line
|
||||
local line, err = client:receive()
|
||||
-- if there was no error, send it back to the client
|
||||
if not err then client:send(line .. "\n") end
|
||||
-- done with client, close the object
|
||||
client:close()
|
||||
end
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<!-- udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=udp>UDP</h3>
|
||||
|
||||
<p>
|
||||
UDP (User Datagram Protocol) is a non-reliable datagram protocol. In
|
||||
other words, applications communicating through UDP send and receive
|
||||
data as independent blocks, which are not guaranteed to reach the other
|
||||
end. Even when they do reach the other end, they are not guaranteed to be
|
||||
error free. Data transfers are atomic, one datagram at a time. Reading
|
||||
only part of a datagram discards the rest, so that the following read
|
||||
operation will act on the next datagram. The advantages are in
|
||||
simplicity (no connection setup) and performance (no error checking or
|
||||
error correction).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that although no guarantees are made, these days
|
||||
networks are so good that, under normal circumstances, few errors
|
||||
happen in practice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An UDP socket object is created by the
|
||||
<a href=udp.html#udp><tt>socket.udp</tt></a> function. UDP
|
||||
sockets do not need to be connected before use. The method
|
||||
<a href=udp.html#sendto><tt>sendto</tt></a>
|
||||
can be used immediately after creation to
|
||||
send a datagram to IP address and port. Host names are not allowed
|
||||
because performing name resolution for each packet would be forbiddingly
|
||||
slow. Methods
|
||||
<a href=udp.html#receive><tt>receive</tt></a> and
|
||||
<a href=udp.html#receivefrom><tt>receivefrom</tt></a>
|
||||
can be used to retrieve datagrams, the latter returning the IP and port of
|
||||
the sender as extra return values (thus being slightly less
|
||||
efficient).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When communication is performed repeatedly with a single peer, an
|
||||
application should call the
|
||||
<a href=udp.html#setpeername><tt>setpeername</tt></a> method to specify a
|
||||
permanent partner. Methods
|
||||
<a href=udp.html#sendto><tt>sendto</tt></a> and
|
||||
<a href=udp.html#receivefrom><tt>receivefrom</tt></a>
|
||||
can no longer be used, but the method
|
||||
<a href=udp.html#send><tt>send</tt></a> can be used to send data
|
||||
directly to the peer, and the method
|
||||
<a href=udp.html#receive><tt>receive</tt></a>
|
||||
will only return datagrams originating
|
||||
from that peer. There is about 30% performance gain due to this practice.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To associate an UDP socket with a local address, an application calls the
|
||||
<a href=udp.html#setsockname><tt>setsockname</tt></a>
|
||||
method <em>before</em> sending any datagrams. Otherwise, the socket is
|
||||
automatically bound to an ephemeral address before the first data
|
||||
transmission and once bound the local address cannot be changed.
|
||||
The other methods available for UDP sockets are
|
||||
<a href=udp.html#getpeername><tt>getpeername</tt></a>,
|
||||
<a href=udp.html#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=udp.html#settimeout><tt>settimeout</tt></a>,
|
||||
<a href=udp.html#setoption><tt>setoption</tt></a> and
|
||||
<a href=udp.html#close><tt>close</tt></a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example:
|
||||
</p>
|
||||
<blockquote>
|
||||
<p>
|
||||
A simple daytime client, using LuaSocket. The program connects to a remote
|
||||
server and tries to retrieve the daytime, printing the answer it got or an
|
||||
error message.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- change here to the host an port you want to contact
|
||||
local host, port = "localhost", 13
|
||||
-- load namespace
|
||||
local socket = require("socket")
|
||||
-- convert host name to ip address
|
||||
local ip = assert(socket.dns.toip(host))
|
||||
-- create a new UDP object
|
||||
local udp = assert(socket.udp())
|
||||
-- contact daytime host
|
||||
assert(udp:sendto("anything", ip, port))
|
||||
-- retrieve the answer and print results
|
||||
io.write(assert(udp:receive()))
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<!-- More +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=more>Support modules</h3>
|
||||
|
||||
<p> Although not covered in the introduction, LuaSocket offers
|
||||
much more than TCP and UDP functionality. As the library
|
||||
evolved, support for <a href=http.html>HTTP</a>, <a href=ftp.html>FTP</a>,
|
||||
and <a href=smtp.html>SMTP</a> were built on top of these. These modules
|
||||
and many others are covered by the <a href=reference.html>reference manual</a>.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:43 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,430 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: LTN12 support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Filters, Source, Sink,
|
||||
Pump, Support, Library">
|
||||
<title>LuaSocket: LTN12 module</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- ltn12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=ltn12>LTN12</h2>
|
||||
|
||||
<p> The <tt>ltn12</tt> namespace implements the ideas described in
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">
|
||||
LTN012, Filters sources and sinks</a>. This manual simply describes the
|
||||
functions. Please refer to the LTN for a deeper explanation of the
|
||||
functionality provided by this module.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>ltn12</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the LTN21 module
|
||||
local ltn12 = require("ltn12")
|
||||
</pre>
|
||||
|
||||
<!-- filters ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id="filter">Filters</h3>
|
||||
|
||||
<!-- chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="filter.chain">
|
||||
ltn12.filter.<b>chain(</b>filter<sub>1</sub>, filter<sub>2</sub>
|
||||
[, ... filter<sub>N</sub>]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a filter that passes all data it receives through each of a
|
||||
series of given filters.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Filter<sub>1</sub></tt> to <tt>filter<sub>N</sub></tt> are simple
|
||||
filters.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the chained filter.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
The nesting of filters can be arbitrary. For instance, the useless filter
|
||||
below doesn't do anything but return the data that was passed to it,
|
||||
unaltered.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load required modules
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
|
||||
-- create a silly identity filter
|
||||
id = ltn12.filter.chain(
|
||||
mime.encode("quoted-printable"),
|
||||
mime.encode("base64"),
|
||||
mime.decode("base64"),
|
||||
mime.decode("quoted-printable")
|
||||
)
|
||||
</pre>
|
||||
|
||||
<!-- cycle ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="filter.cycle">
|
||||
ltn12.filter.<b>cycle(</b>low [, ctx, extra]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a high-level filter that cycles though a low-level filter by
|
||||
passing it each chunk and updating a context between calls.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Low</tt> is the low-level filter to be cycled,
|
||||
<tt>ctx</tt> is the initial context and <tt>extra</tt> is any extra
|
||||
argument the low-level filter might take.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the high-level filter.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ltn12 module
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- the base64 mime filter factory
|
||||
encodet['base64'] = function()
|
||||
return ltn12.filter.cycle(b64, "")
|
||||
end
|
||||
</pre>
|
||||
|
||||
<!-- pumps ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id="pump">Pumps</h3>
|
||||
|
||||
<!-- all ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="pump.all">
|
||||
ltn12.pump.<b>all(</b>source, sink<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Pumps <em>all</em> data from a <tt>source</tt> to a <tt>sink</tt>.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
If successful, the function returns a value that evaluates to
|
||||
<b><tt>true</tt></b>. In case
|
||||
of error, the function returns a <b><tt>false</tt></b> value, followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- step +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="pump.step">
|
||||
ltn12.pump.<b>step(</b>source, sink<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Pumps <em>one</em> chunk of data from a <tt>source</tt> to a <tt>sink</tt>.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
If successful, the function returns a value that evaluates to
|
||||
<b><tt>true</tt></b>. In case
|
||||
of error, the function returns a <b><tt>false</tt></b> value, followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- sinks ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id="sink">Sinks</h3>
|
||||
|
||||
<!-- chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.chain">
|
||||
ltn12.sink.<b>chain(</b>filter, sink<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a new sink that passes data through a <tt>filter</tt> before sending it to a given <tt>sink</tt>.
|
||||
</p>
|
||||
|
||||
<!-- error ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.error">
|
||||
ltn12.sink.<b>error(</b>message<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a sink that aborts transmission with the error
|
||||
<tt>message</tt>.
|
||||
</p>
|
||||
|
||||
<!-- file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.file">
|
||||
ltn12.sink.<b>file(</b>handle, message<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates a sink that sends data to a file.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Handle</tt> is a file handle. If <tt>handle</tt> is <tt><b>nil</b></tt>,
|
||||
<tt>message</tt> should give the reason for failure.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a sink that sends all data to the given <tt>handle</tt>
|
||||
and closes the file when done, or a sink that aborts the transmission with
|
||||
the error <tt>message</tt>
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
In the following example, notice how the prototype is designed to
|
||||
fit nicely with the <tt>io.open</tt> function.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ltn12 module
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- copy a file
|
||||
ltn12.pump.all(
|
||||
ltn12.source.file(io.open("original.png")),
|
||||
ltn12.sink.file(io.open("copy.png"))
|
||||
)
|
||||
</pre>
|
||||
|
||||
<!-- null +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.null">
|
||||
ltn12.sink.<b>null()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a sink that ignores all data it receives.
|
||||
</p>
|
||||
|
||||
<!-- simplify +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.simplify">
|
||||
ltn12.sink.<b>simplify(</b>sink<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a simple sink given a fancy <tt>sink</tt>.
|
||||
</p>
|
||||
|
||||
<!-- table ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="sink.table">
|
||||
ltn12.sink.<b>table(</b>[table]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates a sink that stores all chunks in a table. The chunks can later be
|
||||
efficiently concatenated into a single string.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Table</tt> is used to hold the chunks. If
|
||||
<tt><b>nil</b></tt>, the function creates its own table.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the sink and the table used to store the chunks.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load needed modules
|
||||
local http = require("socket.http")
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- a simplified http.get function
|
||||
function http.get(u)
|
||||
local t = {}
|
||||
local respt = request{
|
||||
url = u,
|
||||
sink = ltn12.sink.table(t)
|
||||
}
|
||||
return table.concat(t), respt.headers, respt.code
|
||||
end
|
||||
</pre>
|
||||
|
||||
<!-- sinks ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id="source">Sources</h3>
|
||||
|
||||
<!-- cat ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.cat">
|
||||
ltn12.source.<b>cat(</b>source<sub>1</sub> [, source<sub>2</sub>, ...,
|
||||
source<sub>N</sub>]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates a new source that produces the concatenation of the data produced
|
||||
by a number of sources.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Source<sub>1</sub></tt> to <tt>source<sub>N</sub></tt> are the original
|
||||
sources.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the new source.
|
||||
</p>
|
||||
|
||||
<!-- chain ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.chain">
|
||||
ltn12.source.<b>chain(</b>source, filter<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates a new <tt>source</tt> that passes data through a <tt>filter</tt>
|
||||
before returning it.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the new source.
|
||||
</p>
|
||||
|
||||
<!-- empty ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.empty">
|
||||
ltn12.source.<b>empty()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns an empty source.
|
||||
</p>
|
||||
|
||||
<!-- error ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.error">
|
||||
ltn12.source.<b>error(</b>message<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a source that aborts transmission with the error
|
||||
<tt>message</tt>.
|
||||
</p>
|
||||
|
||||
<!-- file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.file">
|
||||
ltn12.source.<b>file(</b>handle, message<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates a source that produces the contents of a file.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Handle</tt> is a file handle. If <tt>handle</tt> is <tt><b>nil</b></tt>,
|
||||
<tt>message</tt> should give the reason for failure.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a source that reads chunks of data from
|
||||
given <tt>handle</tt> and returns it to the user,
|
||||
closing the file when done, or a source that aborts the transmission with
|
||||
the error <tt>message</tt>
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
In the following example, notice how the prototype is designed to
|
||||
fit nicely with the <tt>io.open</tt> function.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the ltn12 module
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- copy a file
|
||||
ltn12.pump.all(
|
||||
ltn12.source.file(io.open("original.png")),
|
||||
ltn12.sink.file(io.open("copy.png"))
|
||||
)
|
||||
</pre>
|
||||
|
||||
<!-- simplify +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.simplify">
|
||||
ltn12.source.<b>simplify(</b>source<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a simple source given a fancy <tt>source</tt>.
|
||||
</p>
|
||||
|
||||
<!-- string +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="source.string">
|
||||
ltn12.source.<b>string(</b>string<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a source that produces the contents of a
|
||||
<tt>string</tt>, chunk by chunk.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:47 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
@ -1,476 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: MIME support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, MIME, Library, Support">
|
||||
<title>LuaSocket: MIME module</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- mime +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=mime>MIME</h2>
|
||||
|
||||
<p>
|
||||
The <tt>mime</tt> namespace offers filters that apply and remove common
|
||||
content transfer encodings, such as Base64 and Quoted-Printable.
|
||||
It also provides functions to break text into lines and change
|
||||
the end-of-line convention.
|
||||
MIME is described mainly in
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2045.txt">RFC 2045</a>,
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">2046</a>,
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2047</a>,
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2047.txt">2048</a>, and
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2048.txt">2049</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All functionality provided by the MIME module
|
||||
follows the ideas presented in
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">
|
||||
LTN012, Filters sources and sinks</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>mime</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the MIME module and everything it requires
|
||||
local mime = require("mime")
|
||||
</pre>
|
||||
|
||||
|
||||
<!-- High-level +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=high>High-level filters</h3>
|
||||
|
||||
<!-- normalize ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="normalize">
|
||||
mime.<b>normalize(</b>[marker]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Converts most common end-of-line markers to a specific given marker.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Marker</tt> is the new marker. It defaults to CRLF, the canonic
|
||||
end-of-line marker defined by the MIME standard.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a filter that performs the conversion.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: There is no perfect solution to this problem. Different end-of-line
|
||||
markers are an evil that will probably plague developers forever.
|
||||
This function, however, will work perfectly for text created with any of
|
||||
the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF),
|
||||
or the DOS (CRLF) conventions. Even if the data has mixed end-of-line
|
||||
markers, the function will still work well, although it doesn't
|
||||
guarantee that the number of empty lines will be correct.
|
||||
</p>
|
||||
|
||||
<!-- decode +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="decode">
|
||||
mime.<b>decode(</b>"base64"<b>)</b><br>
|
||||
mime.<b>decode(</b>"quoted-printable"<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a filter that decodes data from a given transfer content
|
||||
encoding.
|
||||
</p>
|
||||
|
||||
<!-- encode +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="encode">
|
||||
mime.<b>encode(</b>"base64"<b>)</b><br>
|
||||
mime.<b>encode(</b>"quoted-printable" [, mode]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a filter that encodes data according to a given transfer content
|
||||
encoding.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
In the Quoted-Printable case, the user can specify whether the data is
|
||||
textual or binary, by passing the <tt>mode</tt> strings "<tt>text</tt>" or
|
||||
"<tt>binary</tt>". <tt>Mode</tt> defaults to "<tt>text</tt>".
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Although both transfer content encodings specify a limit for the line
|
||||
length, the encoding filters do <em>not</em> break text into lines (for
|
||||
added flexibility).
|
||||
Below is a filter that converts binary data to the Base64 transfer content
|
||||
encoding and breaks it into lines of the correct size.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
base64 = ltn12.filter.chain(
|
||||
mime.encode("base64"),
|
||||
mime.wrap("base64")
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p class=note>
|
||||
Note: Text data <em>has</em> to be converted to canonic form
|
||||
<em>before</em> being encoded.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
base64 = ltn12.filter.chain(
|
||||
mime.normalize(),
|
||||
mime.encode("base64"),
|
||||
mime.wrap("base64")
|
||||
)
|
||||
</pre>
|
||||
|
||||
<!-- stuff +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="stuff">
|
||||
mime.<b>stuff()</b><br>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a filter that performs stuffing of SMTP messages.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The <a href=smtp.html#send><tt>smtp.send</tt></a> function
|
||||
uses this filter automatically. You don't need to chain it with your
|
||||
source, or apply it to your message body.
|
||||
</p>
|
||||
|
||||
<!-- wrap +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="wrap">
|
||||
mime.<b>wrap(</b>"text" [, length]<b>)</b><br>
|
||||
mime.<b>wrap(</b>"base64"<b>)</b><br>
|
||||
mime.<b>wrap(</b>"quoted-printable"<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a filter that breaks data into lines.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
The "<tt>text</tt>" line-wrap filter simply breaks text into lines by
|
||||
inserting CRLF end-of-line markers at appropriate positions.
|
||||
<tt>Length</tt> defaults 76.
|
||||
The "<tt>base64</tt>" line-wrap filter works just like the default
|
||||
"<tt>text</tt>" line-wrap filter with default length.
|
||||
The function can also wrap "<tt>quoted-printable</tt>" lines, taking care
|
||||
not to break lines in the middle of an escaped character. In that case, the
|
||||
line length is fixed at 76.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
For example, to create an encoding filter for the Quoted-Printable transfer content encoding of text data, do the following:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
qp = ltn12.filter.chain(
|
||||
mime.normalize(),
|
||||
mime.encode("quoted-printable"),
|
||||
mime.wrap("quoted-printable")
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p class=note>
|
||||
Note: To break into lines with a different end-of-line convention, apply
|
||||
a normalization filter after the line break filter.
|
||||
</p>
|
||||
|
||||
<!-- Low-level ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h3 id=low>Low-level filters</h3>
|
||||
|
||||
<!-- b64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="b64">
|
||||
A, B = mime.<b>b64(</b>C [, D]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to perform Base64 encoding.
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
<tt>A</tt> is the encoded version of the largest prefix of
|
||||
<tt>C..D</tt>
|
||||
that can be encoded unambiguously. <tt>B</tt> has the remaining bytes of
|
||||
<tt>C..D</tt>, <em>before</em> encoding.
|
||||
If <tt>D</tt> is <tt><b>nil</b></tt>, <tt>A</tt> is padded with
|
||||
the encoding of the remaining bytes of <tt>C</tt>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The simplest use of this function is to encode a string into it's
|
||||
Base64 transfer content encoding. Notice the extra parenthesis around the
|
||||
call to <tt>mime.b64</tt>, to discard the second return value.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
print((mime.b64("diego:password")))
|
||||
--> ZGllZ286cGFzc3dvcmQ=
|
||||
</pre>
|
||||
|
||||
<!-- dot +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
<p class=name id="dot">
|
||||
A, n = mime.<b>dot(</b>m [, B]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to perform SMTP stuffing and enable transmission of
|
||||
messages containing the sequence "CRLF.CRLF".
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is the stuffed version of <tt>B</tt>. '<tt>n</tt>' gives the
|
||||
number of characters from the sequence CRLF seen in the end of <tt>B</tt>.
|
||||
'<tt>m</tt>' should tell the same, but for the previous chunk.
|
||||
</p>
|
||||
|
||||
<p class=note>Note: The message body is defined to begin with
|
||||
an implicit CRLF. Therefore, to stuff a message correctly, the
|
||||
first <tt>m</tt> should have the value 2.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
print((string.gsub(mime.dot(2, ".\r\nStuffing the message.\r\n.\r\n."), "\r\n", "\\n")))
|
||||
--> ..\nStuffing the message.\n..\n..
|
||||
</pre>
|
||||
|
||||
<p class=note>
|
||||
Note: The <a href=smtp.html#send><tt>smtp.send</tt></a> function
|
||||
uses this filter automatically. You don't need to
|
||||
apply it again.
|
||||
</p>
|
||||
|
||||
<!-- eol ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="eol">
|
||||
A, B = mime.<b>eol(</b>C [, D, marker]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to perform end-of-line marker translation.
|
||||
For each chunk, the function needs to know if the last character of the
|
||||
previous chunk could be part of an end-of-line marker or not. This is the
|
||||
context the function receives besides the chunk. An updated version of
|
||||
the context is returned after each new chunk.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is the translated version of <tt>D</tt>. <tt>C</tt> is the
|
||||
ASCII value of the last character of the previous chunk, if it was a
|
||||
candidate for line break, or 0 otherwise.
|
||||
<tt>B</tt> is the same as <tt>C</tt>, but for the current
|
||||
chunk. <tt>Marker</tt> gives the new end-of-line marker and defaults to CRLF.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- translates the end-of-line marker to UNIX
|
||||
unix = mime.eol(0, dos, "\n")
|
||||
</pre>
|
||||
|
||||
<!-- qp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="qp">
|
||||
A, B = mime.<b>qp(</b>C [, D, marker]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to perform Quoted-Printable encoding.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is the encoded version of the largest prefix of
|
||||
<tt>C..D</tt>
|
||||
that can be encoded unambiguously. <tt>B</tt> has the remaining bytes of
|
||||
<tt>C..D</tt>, <em>before</em> encoding.
|
||||
If <tt>D</tt> is <tt><b>nil</b></tt>, <tt>A</tt> is padded with
|
||||
the encoding of the remaining bytes of <tt>C</tt>.
|
||||
Throughout encoding, occurrences of CRLF are replaced by the
|
||||
<tt>marker</tt>, which itself defaults to CRLF.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The simplest use of this function is to encode a string into it's
|
||||
Quoted-Printable transfer content encoding.
|
||||
Notice the extra parenthesis around the call to <tt>mime.qp</tt>, to discard the second return value.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
print((mime.qp("maçã")))
|
||||
--> ma=E7=E3=
|
||||
</pre>
|
||||
|
||||
<!-- qpwrp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="qpwrp">
|
||||
A, m = mime.<b>qpwrp(</b>n [, B, length]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to break Quoted-Printable text into lines.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is a copy of <tt>B</tt>, broken into lines of at most
|
||||
<tt>length</tt> bytes (defaults to 76).
|
||||
'<tt>n</tt>' should tell how many bytes are left for the first
|
||||
line of <tt>B</tt> and '<tt>m</tt>' returns the number of bytes
|
||||
left in the last line of <tt>A</tt>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Besides breaking text into lines, this function makes sure the line
|
||||
breaks don't fall in the middle of an escaped character combination. Also,
|
||||
this function only breaks lines that are bigger than <tt>length</tt> bytes.
|
||||
</p>
|
||||
|
||||
<!-- unb64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="unb64">
|
||||
A, B = mime.<b>unb64(</b>C [, D]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to perform Base64 decoding.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is the decoded version of the largest prefix of
|
||||
<tt>C..D</tt>
|
||||
that can be decoded unambiguously. <tt>B</tt> has the remaining bytes of
|
||||
<tt>C..D</tt>, <em>before</em> decoding.
|
||||
If <tt>D</tt> is <tt><b>nil</b></tt>, <tt>A</tt> is the empty string
|
||||
and <tt>B</tt> returns whatever couldn't be decoded.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The simplest use of this function is to decode a string from it's
|
||||
Base64 transfer content encoding.
|
||||
Notice the extra parenthesis around the call to <tt>mime.unqp</tt>, to discard the second return value.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
print((mime.unb64("ZGllZ286cGFzc3dvcmQ=")))
|
||||
--> diego:password
|
||||
</pre>
|
||||
|
||||
<!-- unqp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="unqp">
|
||||
A, B = mime.<b>unqp(</b>C [, D]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to remove the Quoted-Printable transfer content encoding
|
||||
from data.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is the decoded version of the largest prefix of
|
||||
<tt>C..D</tt>
|
||||
that can be decoded unambiguously. <tt>B</tt> has the remaining bytes of
|
||||
<tt>C..D</tt>, <em>before</em> decoding.
|
||||
If <tt>D</tt> is <tt><b>nil</b></tt>, <tt>A</tt> is augmented with
|
||||
the encoding of the remaining bytes of <tt>C</tt>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The simplest use of this function is to decode a string from it's
|
||||
Quoted-Printable transfer content encoding.
|
||||
Notice the extra parenthesis around the call to <tt>mime.unqp</tt>, to discard the second return value.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
print((mime.qp("ma=E7=E3=")))
|
||||
--> maçã
|
||||
</pre>
|
||||
|
||||
<!-- wrp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="wrp">
|
||||
A, m = mime.<b>wrp(</b>n [, B, length]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Low-level filter to break text into lines with CRLF marker.
|
||||
Text is assumed to be in the <a href=#normalize><tt>normalize</tt></a> form.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>A</tt> is a copy of <tt>B</tt>, broken into lines of at most
|
||||
<tt>length</tt> bytes (defaults to 76).
|
||||
'<tt>n</tt>' should tell how many bytes are left for the first
|
||||
line of <tt>B</tt> and '<tt>m</tt>' returns the number of bytes
|
||||
left in the last line of <tt>A</tt>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: This function only breaks lines that are bigger than
|
||||
<tt>length</tt> bytes. The resulting line length does not include the CRLF
|
||||
marker.
|
||||
</p>
|
||||
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:51 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,54 +0,0 @@
|
||||
body {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-family: "Verdana", sans-serif;
|
||||
}
|
||||
|
||||
tt {
|
||||
font-family: "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 { margin-left: 0em; }
|
||||
|
||||
|
||||
h3 { padding-top: 1em; }
|
||||
|
||||
p { margin-left: 1em; }
|
||||
|
||||
p.name {
|
||||
font-family: "Andale Mono", monospace;
|
||||
padding-top: 1em;
|
||||
margin-left: 0em;
|
||||
}
|
||||
|
||||
a[href] { color: #00007f; }
|
||||
|
||||
blockquote { margin-left: 3em; }
|
||||
|
||||
pre.example {
|
||||
background: #ccc;
|
||||
padding: 1em;
|
||||
margin-left: 1em;
|
||||
font-family: "Andale Mono", monospace;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-left: 0em;
|
||||
background: #00007f;
|
||||
border: 0px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
ul { list-style-type: disc; }
|
||||
|
||||
table.index { border: 1px #00007f; }
|
||||
table.index td { text-align: left; vertical-align: top; }
|
||||
table.index ul { padding-top: 0em; margin-top: 0em; }
|
||||
|
||||
h1:first-letter,
|
||||
h2:first-letter,
|
||||
h2:first-letter,
|
||||
h3:first-letter { color: #00007f; }
|
||||
|
||||
div.header, div.footer { margin-left: 0em; }
|
@ -1,239 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: Index to reference manual">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Index, Manual, Network, Library,
|
||||
Support, Manual">
|
||||
<title>LuaSocket: Index to reference manual</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- reference +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2>Reference</h2>
|
||||
|
||||
<blockquote>
|
||||
<a href="dns.html">DNS (in socket)</a>
|
||||
<blockquote>
|
||||
<a href="dns.html#toip">toip</a>,
|
||||
<a href="dns.html#tohostname">tohostname</a>,
|
||||
<a href="dns.html#gethostname">gethostname</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- ftp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="ftp.html">FTP</a>
|
||||
<blockquote>
|
||||
<a href="ftp.html#get">get</a>,
|
||||
<a href="ftp.html#put">put</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- http +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="http.html">HTTP</a>
|
||||
<blockquote>
|
||||
<a href="http.html#request">request</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- ltn12 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="ltn12.html">LTN12</a>
|
||||
<blockquote>
|
||||
<a href="ltn12.html#filter">filter</a>:
|
||||
<a href="ltn12.html#filter.chain">chain</a>,
|
||||
<a href="ltn12.html#filter.cycle">cycle</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="ltn12.html#pump">pump</a>:
|
||||
<a href="ltn12.html#pump.all">all</a>,
|
||||
<a href="ltn12.html#pump.step">step</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="ltn12.html#sink">sink</a>:
|
||||
<a href="ltn12.html#sink.chain">chain</a>,
|
||||
<a href="ltn12.html#sink.error">error</a>,
|
||||
<a href="ltn12.html#sink.file">file</a>,
|
||||
<a href="ltn12.html#sink.null">null</a>,
|
||||
<a href="ltn12.html#sink.simplify">simplify</a>,
|
||||
<a href="ltn12.html#sink.table">table</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="ltn12.html#source">source</a>:
|
||||
<a href="ltn12.html#source.cat">cat</a>,
|
||||
<a href="ltn12.html#source.chain">chain</a>,
|
||||
<a href="ltn12.html#source.empty">empty</a>,
|
||||
<a href="ltn12.html#source.error">error</a>,
|
||||
<a href="ltn12.html#source.file">file</a>,
|
||||
<a href="ltn12.html#source.simplify">simplify</a>,
|
||||
<a href="ltn12.html#source.string">string</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- mime +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="mime.html">MIME</a>
|
||||
<blockquote>
|
||||
<a href="mime.html#high">high-level</a>:
|
||||
<a href="mime.html#normalize">normalize</a>,
|
||||
<a href="mime.html#decode">decode</a>,
|
||||
<a href="mime.html#encode">encode</a>,
|
||||
<a href="mime.html#stuff">stuff</a>,
|
||||
<a href="mime.html#wrap">wrap</a>.
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<a href="mime.html#low">low-level</a>:
|
||||
<a href="mime.html#b64">b64</a>,
|
||||
<a href="mime.html#dot">dot</a>,
|
||||
<a href="mime.html#eol">eol</a>,
|
||||
<a href="mime.html#qp">qp</a>,
|
||||
<a href="mime.html#wrp">wrp</a>,
|
||||
<a href="mime.html#qpwrp">qpwrp</a>.
|
||||
<a href="mime.html#unb64">unb64</a>,
|
||||
<a href="mime.html#unqp">unqp</a>,
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- smtp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="smtp.html">SMTP</a>
|
||||
<blockquote>
|
||||
<a href="smtp.html#message">message</a>,
|
||||
<a href="smtp.html#send">send</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- socket +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="socket.html">Socket</a>
|
||||
<blockquote>
|
||||
<a href="socket.html#debug">_DEBUG</a>,
|
||||
<a href="dns.html#dns">dns</a>,
|
||||
<a href="socket.html#gettime">gettime</a>,
|
||||
<a href="socket.html#newtry">newtry</a>,
|
||||
<a href="socket.html#protect">protect</a>,
|
||||
<a href="socket.html#select">select</a>,
|
||||
<a href="socket.html#sink">sink</a>,
|
||||
<a href="socket.html#skip">skip</a>,
|
||||
<a href="socket.html#sleep">sleep</a>,
|
||||
<a href="socket.html#source">source</a>,
|
||||
<a href="tcp.html#tcp">tcp</a>,
|
||||
<a href="socket.html#try">try</a>,
|
||||
<a href="udp.html#udp">udp</a>,
|
||||
<a href="socket.html#version">_VERSION</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="tcp.html">TCP (in socket)</a>
|
||||
<blockquote>
|
||||
<a href="tcp.html#accept">accept</a>,
|
||||
<a href="tcp.html#bind">bind</a>,
|
||||
<a href="tcp.html#close">close</a>,
|
||||
<a href="tcp.html#connect">connect</a>,
|
||||
<a href="tcp.html#getpeername">getpeername</a>,
|
||||
<a href="tcp.html#getsockname">getsockname</a>,
|
||||
<a href="tcp.html#getstats">getstats</a>,
|
||||
<a href="tcp.html#receive">receive</a>,
|
||||
<a href="tcp.html#send">send</a>,
|
||||
<a href="tcp.html#setoption">setoption</a>,
|
||||
<a href="tcp.html#setstats">setstats</a>,
|
||||
<a href="tcp.html#settimeout">settimeout</a>,
|
||||
<a href="tcp.html#shutdown">shutdown</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- udp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="udp.html">UDP (in socket)</a>
|
||||
<blockquote>
|
||||
<a href="udp.html#close">close</a>,
|
||||
<a href="udp.html#getpeername">getpeername</a>,
|
||||
<a href="udp.html#getsockname">getsockname</a>,
|
||||
<a href="udp.html#receive">receive</a>,
|
||||
<a href="udp.html#receivefrom">receivefrom</a>,
|
||||
<a href="udp.html#send">send</a>,
|
||||
<a href="udp.html#sendto">sendto</a>,
|
||||
<a href="udp.html#setpeername">setpeername</a>,
|
||||
<a href="udp.html#setsockname">setsockname</a>,
|
||||
<a href="udp.html#setoption">setoption</a>,
|
||||
<a href="udp.html#settimeout">settimeout</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- url ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<blockquote>
|
||||
<a href="url.html">URL</a>
|
||||
<blockquote>
|
||||
<a href="url.html#absolute">absolute</a>,
|
||||
<a href="url.html#build">build</a>,
|
||||
<a href="url.html#build_path">build_path</a>,
|
||||
<a href="url.html#escape">escape</a>,
|
||||
<a href="url.html#parse">parse</a>,
|
||||
<a href="url.html#parse_path">parse_path</a>,
|
||||
<a href="url.html#unescape">unescape</a>.
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<!-- footer ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:57:56 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,417 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: SMTP support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, SMTP, E-Mail, MIME, Multipart,
|
||||
Library, Support">
|
||||
<title>LuaSocket: SMTP support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- smtp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=smtp>SMTP</h2>
|
||||
|
||||
<p> The <tt>smtp</tt> namespace provides functionality to send e-mail
|
||||
messages. The high-level API consists of two functions: one to
|
||||
define an e-mail message, and another to actually send the message.
|
||||
Although almost all users will find that these functions provide more than
|
||||
enough functionality, the underlying implementation allows for even more
|
||||
control (if you bother to read the code).
|
||||
</p>
|
||||
|
||||
<p>The implementation conforms to the Simple Mail Transfer Protocol,
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>.
|
||||
Another RFC of interest is <a
|
||||
href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>,
|
||||
which governs the Internet Message Format.
|
||||
Multipart messages (those that contain attachments) are part
|
||||
of the MIME standard, but described mainly
|
||||
in <a href="http://www.cs.princeton.edu/~diego/rfc/rfc2046.txt">RFC
|
||||
2046</a>
|
||||
|
||||
<p> In the description below, good understanding of <a
|
||||
href="http://lua-users.org/wiki/FiltersSourcesAndSinks"> LTN012, Filters
|
||||
sources and sinks</a> and the <a href=mime.html>MIME</a> module is
|
||||
assumed. In fact, the SMTP module was the main reason for their
|
||||
creation. </p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>smtp</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the SMTP module and everything it requires
|
||||
local smtp = require("socket.smtp")
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
MIME headers are represented as a Lua table in the form:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<table summary="MIME headers in Lua table">
|
||||
<tr><td><tt>
|
||||
headers = {<br>
|
||||
field-1-name = <i>field-1-value</i>,<br>
|
||||
field-2-name = <i>field-2-value</i>,<br>
|
||||
field-3-name = <i>field-3-value</i>,<br>
|
||||
...<br>
|
||||
field-n-name = <i>field-n-value</i><br>
|
||||
}
|
||||
</tt></td></tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
Field names are case insensitive (as specified by the standard) and all
|
||||
functions work with lowercase field names.
|
||||
Field values are left unmodified.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: MIME headers are independent of order. Therefore, there is no problem
|
||||
in representing them in a Lua table.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following constants can be set to control the default behavior of
|
||||
the SMTP module:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <tt>DOMAIN</tt>: domain used to greet the server;
|
||||
<li> <tt>PORT</tt>: default port used for the connection;
|
||||
<li> <tt>SERVER</tt>: default server used for the connection;
|
||||
<li> <tt>TIMEOUT</tt>: default timeout for all I/O operations;
|
||||
<li> <tt>ZONE</tt>: default time zone.
|
||||
</ul>
|
||||
|
||||
<!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=send>
|
||||
smtp.<b>send{</b><br>
|
||||
from = <i>string</i>,<br>
|
||||
rcpt = <i>string</i> or <i>string-table</i>,<br>
|
||||
source = <i>LTN12 source</i>,<br>
|
||||
[user = <i>string</i>,]<br>
|
||||
[password = <i>string</i>,]<br>
|
||||
[server = <i>string</i>,]<br>
|
||||
[port = <i>number</i>,]<br>
|
||||
[domain = <i>string</i>,]<br>
|
||||
[step = <i>LTN12 pump step</i>,]<br>
|
||||
[create = <i>function</i>]<br>
|
||||
<b>}</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Sends a message to a recipient list. Since sending messages is not as
|
||||
simple as downloading an URL from a FTP or HTTP server, this function
|
||||
doesn't have a simple interface. However, see the
|
||||
<a href=#message><tt>message</tt></a> source factory for
|
||||
a very powerful way to define the message contents.
|
||||
</p>
|
||||
|
||||
|
||||
<p class=parameters>
|
||||
The sender is given by the e-mail address in the <tt>from</tt> field.
|
||||
<tt>Rcpt</tt> is a Lua table with one entry for each recipient e-mail
|
||||
address, or a string
|
||||
in case there is just one recipient.
|
||||
The contents of the message are given by a <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
<tt>source</tt>. Several arguments are optional:
|
||||
</p>
|
||||
<ul>
|
||||
<li> <tt>user</tt>, <tt>password</tt>: User and password for
|
||||
authentication. The function will attempt LOGIN and PLAIN authentication
|
||||
methods if supported by the server (both are unsafe);
|
||||
<li> <tt>server</tt>: Server to connect to. Defaults to "localhost";
|
||||
<li> <tt>port</tt>: Port to connect to. Defaults to 25;
|
||||
<li> <tt>domain</tt>: Domain name used to greet the server; Defaults to the
|
||||
local machine host name;
|
||||
<li> <tt>step</tt>:
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
pump step function used to pass data from the
|
||||
source to the server. Defaults to the LTN12 <tt>pump.step</tt> function;
|
||||
<li><tt>create</tt>: An optional function to be used instead of
|
||||
<a href=tcp.html#socket.tcp><tt>socket.tcp</tt></a> when the communications socket is created.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
If successful, the function returns 1. Otherwise, the function returns
|
||||
<b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: SMTP servers can be very picky with the format of e-mail
|
||||
addresses. To be safe, use only addresses of the form
|
||||
"<tt><fulano@example.com></tt>" in the <tt>from</tt> and
|
||||
<tt>rcpt</tt> arguments to the <tt>send</tt> function. In headers, e-mail
|
||||
addresses can take whatever form you like. </p>
|
||||
|
||||
<p class=note>
|
||||
Big note: There is a good deal of misconception with the use of the
|
||||
destination address field headers, i.e., the '<tt>To</tt>', '<tt>Cc</tt>',
|
||||
and, more importantly, the '<tt>Bcc</tt>' headers. Do <em>not</em> add a
|
||||
'<tt>Bcc</tt>' header to your messages because it will probably do the
|
||||
exact opposite of what you expect.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Only recipients specified in the <tt>rcpt</tt> list will receive a copy of the
|
||||
message. Each recipient of an SMTP mail message receives a copy of the
|
||||
message body along with the headers, and nothing more. The headers
|
||||
<em>are</em> part of the message and should be produced by the
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
<tt>source</tt> function. The <tt>rcpt</tt> list is <em>not</em>
|
||||
part of the message and will not be sent to anyone.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>
|
||||
has two <em>important and short</em> sections, "3.6.3. Destination address
|
||||
fields" and "5. Security considerations", explaining the proper
|
||||
use of these headers. Here is a summary of what it says:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <tt>To</tt>: contains the address(es) of the primary recipient(s)
|
||||
of the message;
|
||||
<li> <tt>Cc</tt>: (where the "Cc" means "Carbon Copy" in the sense of
|
||||
making a copy on a typewriter using carbon paper) contains the
|
||||
addresses of others who are to receive the message, though the
|
||||
content of the message may not be directed at them;
|
||||
<li> <tt>Bcc</tt>: (where the "Bcc" means "Blind Carbon
|
||||
Copy") contains addresses of recipients of the message whose addresses are not to be revealed to other recipients of the message.
|
||||
</ul>
|
||||
|
||||
<p class=note>
|
||||
The LuaSocket <tt>send</tt> function does not care or interpret the
|
||||
headers you send, but it gives you full control over what is sent and
|
||||
to whom it is sent:
|
||||
</p>
|
||||
<ul>
|
||||
<li> If someone is to receive the message, the e-mail address <em>has</em>
|
||||
to be in the recipient list. This is the only parameter that controls who
|
||||
gets a copy of the message;
|
||||
<li> If there are multiple recipients, none of them will automatically
|
||||
know that someone else got that message. That is, the default behavior is
|
||||
similar to the <tt>Bcc</tt> field of popular e-mail clients;
|
||||
<li> It is up to you to add the <tt>To</tt> header with the list of primary
|
||||
recipients so that other recipients can see it;
|
||||
<li> It is also up to you to add the <tt>Cc</tt> header with the
|
||||
list of additional recipients so that everyone else sees it;
|
||||
<li> Adding a header <tt>Bcc</tt> is nonsense, unless it is
|
||||
empty. Otherwise, everyone receiving the message will see it and that is
|
||||
exactly what you <em>don't</em> want to happen!
|
||||
</ul>
|
||||
|
||||
<p class=note>
|
||||
I hope this clarifies the issue. Otherwise, please refer to
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2821.txt">RFC 2821</a>
|
||||
and
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2822.txt">RFC 2822</a>.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the smtp support
|
||||
local smtp = require("socket.smtp")
|
||||
|
||||
-- Connects to server "localhost" and sends a message to users
|
||||
-- "fulano@example.com", "beltrano@example.com",
|
||||
-- and "sicrano@example.com".
|
||||
-- Note that "fulano" is the primary recipient, "beltrano" receives a
|
||||
-- carbon copy and neither of them knows that "sicrano" received a blind
|
||||
-- carbon copy of the message.
|
||||
from = "<luasocket@example.com>"
|
||||
|
||||
rcpt = {
|
||||
"<fulano@example.com>",
|
||||
"<beltrano@example.com>",
|
||||
"<sicrano@example.com>"
|
||||
}
|
||||
|
||||
mesgt = {
|
||||
headers = {
|
||||
to = "Fulano da Silva <fulano@example.com>",
|
||||
cc = '"Beltrano F. Nunes" <beltrano@example.com>',
|
||||
subject = "My first message"
|
||||
},
|
||||
body = "I hope this works. If it does, I can send you another 1000 copies."
|
||||
}
|
||||
|
||||
r, e = smtp.send{
|
||||
from = from,
|
||||
rcpt = rcpt,
|
||||
source = smtp.message(mesgt)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<!-- message ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=message>
|
||||
smtp.<b>message(</b>mesgt<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns a <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a> source that sends an SMTP message body, possibly multipart (arbitrarily deep).
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
The only parameter of the function is a table describing the message.
|
||||
<tt>Mesgt</tt> has the following form (notice the recursive structure):
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<table summary="Mesgt table structure">
|
||||
<tr><td><tt>
|
||||
mesgt = {<br>
|
||||
headers = <i>header-table</i>,<br>
|
||||
body = <i>LTN12 source</i> or <i>string</i> or
|
||||
<i>multipart-mesgt</i><br>
|
||||
}<br>
|
||||
<br>
|
||||
multipart-mesgt = {<br>
|
||||
[preamble = <i>string</i>,]<br>
|
||||
[1] = <i>mesgt</i>,<br>
|
||||
[2] = <i>mesgt</i>,<br>
|
||||
...<br>
|
||||
[<i>n</i>] = <i>mesgt</i>,<br>
|
||||
[epilogue = <i>string</i>,]<br>
|
||||
}<br>
|
||||
</tt></td></tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
|
||||
<p class=parameters>
|
||||
For a simple message, all that is needed is a set of <tt>headers</tt>
|
||||
and the <tt>body</tt>. The message <tt>body</tt> can be given as a string
|
||||
or as a <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
source. For multipart messages, the body is a table that
|
||||
recursively defines each part as an independent message, plus an optional
|
||||
<tt>preamble</tt> and <tt>epilogue</tt>.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a <em>simple</em>
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
source that produces the
|
||||
message contents as defined by <tt>mesgt</tt>, chunk by chunk.
|
||||
Hopefully, the following
|
||||
example will make things clear. When in doubt, refer to the appropriate RFC
|
||||
as listed in the introduction. </p>
|
||||
|
||||
<pre class=example>
|
||||
-- load the smtp support and its friends
|
||||
local smtp = require("socket.smtp")
|
||||
local mime = require("mime")
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- creates a source to send a message with two parts. The first part is
|
||||
-- plain text, the second part is a PNG image, encoded as base64.
|
||||
source = smtp.message{
|
||||
headers = {
|
||||
-- Remember that headers are *ignored* by smtp.send.
|
||||
from = "Sicrano de Oliveira <sicrano@example.com>",
|
||||
to = "Fulano da Silva <fulano@example.com>",
|
||||
subject = "Here is a message with attachments"
|
||||
},
|
||||
body = {
|
||||
preamble = "If your client doesn't understand attachments, \r\n" ..
|
||||
"it will still display the preamble and the epilogue.\r\n" ..
|
||||
"Preamble will probably appear even in a MIME enabled client.",
|
||||
-- first part: no headers means plain text, us-ascii.
|
||||
-- The mime.eol low-level filter normalizes end-of-line markers.
|
||||
[1] = {
|
||||
body = mime.eol(0, [[
|
||||
Lines in a message body should always end with CRLF.
|
||||
The smtp module will *NOT* perform translation. However, the
|
||||
send function *DOES* perform SMTP stuffing, whereas the message
|
||||
function does *NOT*.
|
||||
]])
|
||||
},
|
||||
-- second part: headers describe content to be a png image,
|
||||
-- sent under the base64 transfer content encoding.
|
||||
-- notice that nothing happens until the message is actually sent.
|
||||
-- small chunks are loaded into memory right before transmission and
|
||||
-- translation happens on the fly.
|
||||
[2] = {
|
||||
headers = {
|
||||
["content-type"] = 'image/png; name="image.png"',
|
||||
["content-disposition"] = 'attachment; filename="image.png"',
|
||||
["content-description"] = 'a beautiful image',
|
||||
["content-transfer-encoding"] = "BASE64"
|
||||
},
|
||||
body = ltn12.source.chain(
|
||||
ltn12.source.file(io.open("image.png", "rb")),
|
||||
ltn12.filter.chain(
|
||||
mime.encode("base64"),
|
||||
mime.wrap()
|
||||
)
|
||||
)
|
||||
},
|
||||
epilogue = "This might also show up, but after the attachments"
|
||||
}
|
||||
}
|
||||
|
||||
-- finally send it
|
||||
r, e = smtp.send{
|
||||
from = "<sicrano@example.com>",
|
||||
rcpt = "<fulano@example.com>",
|
||||
source = source,
|
||||
}
|
||||
</pre>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:58:01 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,398 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: The core namespace">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Socket, Network, Library, Support">
|
||||
<title>LuaSocket: The socket namespace</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- socket +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=socket>The socket namespace</h2>
|
||||
|
||||
<p>
|
||||
The <tt>socket</tt> namespace contains the core functionality of LuaSocket.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>socket</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the socket module
|
||||
local socket = require("socket")
|
||||
</pre>
|
||||
|
||||
<!-- bind ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=bind>
|
||||
socket.<b>bind(</b>address, port [, backlog]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function is a shortcut that creates and returns a TCP server object
|
||||
bound to a local <tt>address</tt> and <tt>port</tt>, ready to
|
||||
accept client connections. Optionally,
|
||||
user can also specify the <tt>backlog</tt> argument to the
|
||||
<a href=tcp.html#listen><tt>listen</tt></a> method (defaults to 32).
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The server object returned will have the option "<tt>reuseaddr</tt>"
|
||||
set to <tt><b>true</b></tt>.
|
||||
</p>
|
||||
|
||||
<!-- connect ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=connect>
|
||||
socket.<b>connect(</b>address, port [, locaddr, locport]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This function is a shortcut that creates and returns a TCP client object
|
||||
connected to a remote <tt>host</tt> at a given <tt>port</tt>. Optionally,
|
||||
the user can also specify the local address and port to bind
|
||||
(<tt>locaddr</tt> and <tt>locport</tt>).
|
||||
</p>
|
||||
|
||||
<!-- debug ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=debug>
|
||||
socket.<b>_DEBUG</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This constant is set to <tt><b>true</b></tt> if the library was compiled
|
||||
with debug support.
|
||||
</p>
|
||||
|
||||
<!-- newtry +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=newtry>
|
||||
socket.<b>newtry(</b>finalizer<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a <em>clean</em>
|
||||
<a href="#try"><tt>try</tt></a>
|
||||
function that allows for cleanup before the exception
|
||||
is raised.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Finalizer</tt> is a function that will be called before
|
||||
<tt>try</tt> throws the exception. It will be called
|
||||
in <em>protected</em> mode.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns your customized <tt>try</tt> function.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: This idea saved a <em>lot</em> of work with the
|
||||
implementation of protocols in LuaSocket:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
foo = socket.protect(function()
|
||||
-- connect somewhere
|
||||
local c = socket.try(socket.connect("somewhere", 42))
|
||||
-- create a try function that closes 'c' on error
|
||||
local try = socket.newtry(function() c:close() end)
|
||||
-- do everything reassured c will be closed
|
||||
try(c:send("hello there?\r\n"))
|
||||
local answer = try(c:receive())
|
||||
...
|
||||
try(c:send("good bye\r\n"))
|
||||
c:close()
|
||||
end)
|
||||
</pre>
|
||||
|
||||
|
||||
<!-- protect +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=protect>
|
||||
socket.<b>protect(</b>func<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Converts a function that throws exceptions into a safe function. This
|
||||
function only catches exceptions thrown by the <a href=#try><tt>try</tt></a>
|
||||
and <a href=#newtry><tt>newtry</tt></a> functions. It does not catch normal
|
||||
Lua errors.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Func</tt> is a function that calls
|
||||
<a href=#try><tt>try</tt></a> (or <tt>assert</tt>, or <tt>error</tt>)
|
||||
to throw exceptions.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Returns an equivalent function that instead of throwing exceptions,
|
||||
returns <tt><b>nil</b></tt> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Beware that if your function performs some illegal operation that
|
||||
raises an error, the protected function will catch the error and return it
|
||||
as a string. This is because the <a href=#try><tt>try</tt></a> function
|
||||
uses errors as the mechanism to throw exceptions.
|
||||
</p>
|
||||
|
||||
<!-- select +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=select>
|
||||
socket.<b>select(</b>recvt, sendt [, timeout]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Waits for a number of sockets to change status.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Recvt</tt> is an array with the sockets to test for characters
|
||||
available for reading. Sockets in the <tt>sendt</tt> array are watched to
|
||||
see if it is OK to immediately write on them. <tt>Timeout</tt> is the
|
||||
maximum amount of time (in seconds) to wait for a change in status. A
|
||||
<tt><b>nil</b></tt>, negative or omitted <tt>timeout</tt> value allows the
|
||||
function to block indefinitely. <tt>Recvt</tt> and <tt>sendt</tt> can also
|
||||
be empty tables or <tt><b>nil</b></tt>. Non-socket values (or values with
|
||||
non-numeric indices) in the arrays will be silently ignored.
|
||||
</p>
|
||||
|
||||
<p class=return> The function returns a table with the sockets ready for
|
||||
reading, a table with the sockets ready for writing and an error message.
|
||||
The error message is "<tt>timeout</tt>" if a timeout condition was met and
|
||||
<tt><b>nil</b></tt> otherwise. The returned tables are associative, to
|
||||
simplify the test if a specific socket has changed status.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
<b>Important note</b>: a known bug in WinSock causes <tt>select</tt> to fail
|
||||
on non-blocking TCP sockets. The function may return a socket as
|
||||
writable even though the socket is <em>not</em> ready for sending.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
<b>Another important note</b>: calling select with a server socket in the receive parameter before a call to accept does <em>not</em> guarantee
|
||||
<a href=tcp.html#accept><tt>accept</tt></a> will return immediately.
|
||||
Use the <a href=tcp.html#settimeout><tt>settimeout</tt></a>
|
||||
method or <tt>accept</tt> might block forever.
|
||||
</p>
|
||||
|
||||
<!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=sink>
|
||||
socket.<b>sink(</b>mode, socket<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates an
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
sink from a stream socket object.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Mode</tt> defines the behavior of the sink. The following
|
||||
options are available:
|
||||
</p>
|
||||
<ul>
|
||||
<li> <tt>"http-chunked"</tt>: sends data through socket after applying the
|
||||
<em>chunked transfer coding</em>, closing the socket when done;
|
||||
<li> <tt>"close-when-done"</tt>: sends all received data through the
|
||||
socket, closing the socket when done;
|
||||
<li> <tt>"keep-open"</tt>: sends all received data through the
|
||||
socket, leaving it open when done.
|
||||
</ul>
|
||||
<p>
|
||||
<tt>Socket</tt> is the stream socket object used to send the data.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a sink with the appropriate behavior.
|
||||
</p>
|
||||
|
||||
<!-- skip ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=skip>
|
||||
socket.<b>skip(</b>d [, ret<sub>1</sub>, ret<sub>2</sub> ... ret<sub>N</sub>]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Drops a number of arguments and returns the remaining.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>D</tt> is the number of arguments to drop. <tt>Ret<sub>1</sub></tt> to
|
||||
<tt>ret<sub>N</sub></tt> are the arguments.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns <tt>ret<sub>d+1</sub></tt> to <tt>ret<sub>N</sub></tt>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: This function is useful to avoid creation of dummy variables:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- get the status code and separator from SMTP server reply
|
||||
local code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
|
||||
</pre>
|
||||
|
||||
<!-- sleep ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=sleep>
|
||||
socket.<b>sleep(</b>time<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Freezes the program execution during a given amount of time.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Time</tt> is the number of seconds to sleep for.
|
||||
The function truncates <tt>time</tt> down to the nearest integer.
|
||||
</p>
|
||||
|
||||
<!-- source +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=source>
|
||||
socket.<b>source(</b>mode, socket [, length]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates an
|
||||
<a href="http://lua-users.org/wiki/FiltersSourcesAndSinks">LTN12</a>
|
||||
source from a stream socket object.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Mode</tt> defines the behavior of the source. The following
|
||||
options are available:
|
||||
</p>
|
||||
<ul>
|
||||
<li> <tt>"http-chunked"</tt>: receives data from socket and removes the
|
||||
<em>chunked transfer coding</em> before returning the data;
|
||||
<li> <tt>"by-length"</tt>: receives a fixed number of bytes from the
|
||||
socket. This mode requires the extra argument <tt>length</tt>;
|
||||
<li> <tt>"until-closed"</tt>: receives data from a socket until the other
|
||||
side closes the connection.
|
||||
</ul>
|
||||
<p>
|
||||
<tt>Socket</tt> is the stream socket object used to receive the data.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a source with the appropriate behavior.
|
||||
</p>
|
||||
|
||||
<!-- time ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=gettime>
|
||||
socket.<b>gettime()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns the time in seconds, relative to the origin of the
|
||||
universe. You should subtract the values returned by this function
|
||||
to get meaningful values.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
t = socket.gettime()
|
||||
-- do stuff
|
||||
print(socket.gettime() - t .. " seconds elapsed")
|
||||
</pre>
|
||||
|
||||
<!-- try ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=try>
|
||||
socket.<b>try(</b>ret<sub>1</sub> [, ret<sub>2</sub> ... ret<sub>N</sub>]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Throws an exception in case of error. The exception can only be caught
|
||||
by the <a href=#protect><tt>protect</tt></a> function. It does not explode
|
||||
into an error message.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Ret<sub>1</sub></tt> to <tt>ret<sub>N</sub></tt> can be arbitrary
|
||||
arguments, but are usually the return values of a function call
|
||||
nested with <tt>try</tt>.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns <tt>ret</tt><sub>1</sub> to <tt>ret</tt><sub>N</sub> if
|
||||
<tt>ret</tt><sub>1</sub> is not <tt><b>nil</b></tt>. Otherwise, it calls <tt>error</tt> passing <tt>ret</tt><sub>2</sub>.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- connects or throws an exception with the appropriate error message
|
||||
c = socket.try(socket.connect("localhost", 80))
|
||||
</pre>
|
||||
|
||||
<!-- version ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=version>
|
||||
socket.<b>_VERSION</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
This constant has a string describing the current LuaSocket version.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:58:06 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,532 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: The TCP/IP support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Socket, TCP, Library, Network, Support">
|
||||
<title>LuaSocket: TCP/IP support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- tcp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=tcp>TCP</h2>
|
||||
|
||||
<!-- socket.tcp +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=socket.tcp>
|
||||
socket.<b>tcp()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Creates and returns a TCP master object. A master object can
|
||||
be transformed into a server object with the method
|
||||
<a href=#listen><tt>listen</tt></a> (after a call to <a
|
||||
href=#bind><tt>bind</tt></a>) or into a client object with
|
||||
the method <a href=#connect><tt>connect</tt></a>. The only other
|
||||
method supported by a master object is the
|
||||
<a href=#close><tt>close</tt></a> method.</p>
|
||||
|
||||
<p class=return>
|
||||
In case of success, a new master object is returned. In case of error,
|
||||
<b><tt>nil</tt></b> is returned, followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- accept +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=accept>
|
||||
server:<b>accept()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Waits for a remote connection on the server
|
||||
object and returns a client object representing that connection.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
If a connection is successfully initiated, a client object is returned.
|
||||
If a timeout condition is met, the method returns <b><tt>nil</tt></b>
|
||||
followed by the error string '<tt>timeout</tt>'. Other errors are
|
||||
reported by <b><tt>nil</tt></b> followed by a message describing the error.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: calling <a href=socket.html#select><tt>socket.select</tt></a>
|
||||
with a server object in
|
||||
the <tt>recvt</tt> parameter before a call to <tt>accept</tt> does
|
||||
<em>not</em> guarantee <tt>accept</tt> will return immediately. Use the <a
|
||||
href=#settimeout><tt>settimeout</tt></a> method or <tt>accept</tt>
|
||||
might block until <em>another</em> client shows up.
|
||||
</p>
|
||||
|
||||
<!-- bind +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=bind>
|
||||
master:<b>bind(</b>address, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Binds a master object to <tt>address</tt> and <tt>port</tt> on the
|
||||
local host.
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Address</tt> can be an IP address or a host name.
|
||||
<tt>Port</tt> must be an integer number in the range [0..64K).
|
||||
If <tt>address</tt>
|
||||
is '<tt>*</tt>', the system binds to all local interfaces
|
||||
using the <tt>INADDR_ANY</tt> constant. If <tt>port</tt> is 0, the system automatically
|
||||
chooses an ephemeral port.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
In case of success, the method returns 1. In case of error, the
|
||||
method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The function <a href=socket.html#bind><tt>socket.bind</tt></a>
|
||||
is available and is a shortcut for the creation of server sockets.
|
||||
</p>
|
||||
|
||||
<!-- close ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=close>
|
||||
master:<b>close()</b><br>
|
||||
client:<b>close()</b><br>
|
||||
server:<b>close()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Closes a TCP object. The internal socket used by the object is closed
|
||||
and the local address to which the object was
|
||||
bound is made available to other applications. No further operations
|
||||
(except for further calls to the <tt>close</tt> method) are allowed on
|
||||
a closed socket.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: It is important to close all used sockets once they are not
|
||||
needed, since, in many systems, each socket uses a file descriptor,
|
||||
which are limited system resources. Garbage-collected objects are
|
||||
automatically closed before destruction, though.
|
||||
</p>
|
||||
|
||||
<!-- connect ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=connect>
|
||||
master:<b>connect(</b>address, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Attempts to connect a master object to a remote host, transforming it into a
|
||||
client object.
|
||||
Client objects support methods
|
||||
<a href=#send><tt>send</tt></a>,
|
||||
<a href=#receive><tt>receive</tt></a>,
|
||||
<a href=#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=#getpeername><tt>getpeername</tt></a>,
|
||||
<a href=#settimeout><tt>settimeout</tt></a>,
|
||||
and <a href=#close><tt>close</tt></a>.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Address</tt> can be an IP address or a host name.
|
||||
<tt>Port</tt> must be an integer number in the range [1..64K).
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
In case of error, the method returns <b><tt>nil</tt></b> followed by a string
|
||||
describing the error. In case of success, the method returns 1.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The function <a href=socket.html#connect><tt>socket.connect</tt></a>
|
||||
is available and is a shortcut for the creation of client sockets.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Starting with LuaSocket 2.0,
|
||||
the <a href=#settimeout><tt>settimeout</tt></a>
|
||||
method affects the behavior of <tt>connect</tt>, causing it to return
|
||||
with an error in case of a timeout. If that happens, you can still call <a
|
||||
href=socket.html#select><tt>socket.select</tt></a> with the socket in the
|
||||
<tt>sendt</tt> table. The socket will be writable when the connection is
|
||||
established.
|
||||
</p>
|
||||
|
||||
<!-- getpeername ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=getpeername>
|
||||
client:<b>getpeername()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns information about the remote side of a connected client object.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Returns a string with the IP address of the peer, followed by the
|
||||
port number that peer is using for the connection.
|
||||
In case of error, the method returns <b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: It makes no sense to call this method on server objects.
|
||||
</p>
|
||||
|
||||
<!-- getsockname ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=getsockname>
|
||||
master:<b>getsockname()</b><br>
|
||||
client:<b>getsockname()</b><br>
|
||||
server:<b>getsockname()</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns the local address information associated to the object.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The method returns a string with local IP address and a number with
|
||||
the port. In case of error, the method returns <b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<!-- getstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=getstats>
|
||||
master:<b>getstats()</b><br>
|
||||
client:<b>getstats()</b><br>
|
||||
server:<b>getstats()</b><br>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Returns accounting information on the socket, useful for throttling
|
||||
of bandwidth.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The method returns the number of bytes received, the number of bytes sent,
|
||||
and the age of the socket object in seconds.
|
||||
</p>
|
||||
|
||||
<!-- listen ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=listen>
|
||||
master:<b>listen(</b>backlog<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Specifies the socket is willing to receive connections, transforming the
|
||||
object into a server object. Server objects support the
|
||||
<a href=#accept><tt>accept</tt></a>,
|
||||
<a href=#getsockname><tt>getsockname</tt></a>,
|
||||
<a href=#setoption><tt>setoption</tt></a>,
|
||||
<a href=#settimeout><tt>settimeout</tt></a>,
|
||||
and <a href=#close><tt>close</tt></a> methods.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
The parameter <tt>backlog</tt> specifies the number of client
|
||||
connections that can
|
||||
be queued waiting for service. If the queue is full and another client
|
||||
attempts connection, the connection is refused.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
In case of success, the method returns 1. In case of error, the
|
||||
method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<!-- receive ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=receive>
|
||||
client:<b>receive(</b>[pattern [, prefix]]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Reads data from a client object, according to the specified <em>read
|
||||
pattern</em>. Patterns follow the Lua file I/O format, and the difference in performance between all patterns is negligible.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Pattern</tt> can be any of the following:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> '<tt>*a</tt>': reads from the socket until the connection is
|
||||
closed. No end-of-line translation is performed;
|
||||
<li> '<tt>*l</tt>': reads a line of text from the socket. The line is
|
||||
terminated by a LF character (ASCII 10), optionally preceded by a
|
||||
CR character (ASCII 13). The CR and LF characters are not included in
|
||||
the returned line. This is the default pattern;
|
||||
<li> <tt>number</tt>: causes the method to read a specified <tt>number</tt>
|
||||
of bytes from the socket.
|
||||
</ul>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Prefix</tt> is an optional string to be concatenated to the beginning
|
||||
of any received data before return.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
If successful, the method returns the received pattern. In case of error,
|
||||
the method returns <tt><b>nil</b></tt> followed by an error message which
|
||||
can be the string '<tt>closed</tt>' in case the connection was
|
||||
closed before the transmission was completed or the string
|
||||
'<tt>timeout</tt>' in case there was a timeout during the operation.
|
||||
Also, after the error message, the function returns the partial result of
|
||||
the transmission.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
<b>Important note</b>: This function was changed <em>severely</em>. It used
|
||||
to support multiple patterns (but I have never seen this feature used) and
|
||||
now it doesn't anymore. Partial results used to be returned in the same
|
||||
way as successful results. This last feature violated the idea that all
|
||||
functions should return <tt><b>nil</b></tt> on error. Thus it was changed
|
||||
too.
|
||||
</p>
|
||||
|
||||
<!-- send +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=send>
|
||||
client:<b>send(</b>data [, i [, j]]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Sends <tt>data</tt> through client object.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Data</tt> is the string to be sent. The optional arguments
|
||||
<tt>i</tt> and <tt>j</tt> work exactly like the standard
|
||||
<tt>string.sub</tt> Lua function to allow the selection of a
|
||||
substring to be sent.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
If successful, the method returns the index of the last byte
|
||||
within <tt>[i, j]</tt> that has been sent. Notice that, if
|
||||
<tt>i</tt> is 1 or absent, this is effectively the total
|
||||
number of bytes sent. In case of error, the method returns
|
||||
<b><tt>nil</tt></b>, followed by an error message, followed
|
||||
by the index of the last byte within <tt>[i, j]</tt> that
|
||||
has been sent. You might want to try again from the byte
|
||||
following that. The error message can be '<tt>closed</tt>'
|
||||
in case the connection was closed before the transmission
|
||||
was completed or the string '<tt>timeout</tt>' in case
|
||||
there was a timeout during the operation.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: Output is <em>not</em> buffered. For small strings,
|
||||
it is always better to concatenate them in Lua
|
||||
(with the '<tt>..</tt>' operator) and send the result in one call
|
||||
instead of calling the method several times.
|
||||
</p>
|
||||
|
||||
<!-- setoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=setoption>
|
||||
client:<b>setoption(</b>option [, value]<b>)</b><br>
|
||||
server:<b>setoption(</b>option [, value]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Sets options for the TCP object. Options are only needed by low-level or
|
||||
time-critical applications. You should only modify an option if you
|
||||
are sure you need it.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Option</tt> is a string with the option name, and <tt>value</tt>
|
||||
depends on the option being set:
|
||||
|
||||
<ul>
|
||||
|
||||
<li> '<tt>keepalive</tt>': Setting this option to <tt>true</tt> enables
|
||||
the periodic transmission of messages on a connected socket. Should the
|
||||
connected party fail to respond to these messages, the connection is
|
||||
considered broken and processes using the socket are notified;
|
||||
|
||||
<li> '<tt>linger</tt>': Controls the action taken when unsent data are
|
||||
queued on a socket and a close is performed. The value is a table with a
|
||||
boolean entry '<tt>on</tt>' and a numeric entry for the time interval
|
||||
'<tt>timeout</tt>' in seconds. If the '<tt>on</tt>' field is set to
|
||||
<tt>true</tt>, the system will block the process on the close attempt until
|
||||
it is able to transmit the data or until '<tt>timeout</tt>' has passed. If
|
||||
'<tt>on</tt>' is <tt>false</tt> and a close is issued, the system will
|
||||
process the close in a manner that allows the process to continue as
|
||||
quickly as possible. I do not advise you to set this to anything other than
|
||||
zero;
|
||||
|
||||
<li> '<tt>reuseaddr</tt>': Setting this option indicates that the rules
|
||||
used in validating addresses supplied in a call to
|
||||
<a href=#bind><tt>bind</tt></a> should allow reuse of local addresses;
|
||||
|
||||
<li> '<tt>tcp-nodelay</tt>': Setting this option to <tt>true</tt>
|
||||
disables the Nagle's algorithm for the connection.
|
||||
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
The method returns 1 in case of success, or <b><tt>nil</tt></b> otherwise.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The descriptions above come from the man pages.
|
||||
</p>
|
||||
|
||||
<!-- setstats +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=setstats>
|
||||
master:<b>setstats(</b>received, sent, age<b>)</b><br>
|
||||
client:<b>setstats(</b>received, sent, age<b>)</b><br>
|
||||
server:<b>setstats(</b>received, sent, age<b>)</b><br>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Resets accounting information on the socket, useful for throttling
|
||||
of bandwidth.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Received</tt> is a number with the new number of bytes received.
|
||||
<tt>Sent</tt> is a number with the new number of bytes sent.
|
||||
<tt>Age</tt> is the new age in seconds.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The method returns 1 in case of success and <tt><b>nil</b></tt> otherwise.
|
||||
</p>
|
||||
|
||||
<!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=settimeout>
|
||||
master:<b>settimeout(</b>value [, mode]<b>)</b><br>
|
||||
client:<b>settimeout(</b>value [, mode]<b>)</b><br>
|
||||
server:<b>settimeout(</b>value [, mode]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Changes the timeout values for the object. By default,
|
||||
all I/O operations are blocking. That is, any call to the methods
|
||||
<a href=#send><tt>send</tt></a>,
|
||||
<a href=#receive><tt>receive</tt></a>, and
|
||||
<a href=#accept><tt>accept</tt></a>
|
||||
will block indefinitely, until the operation completes. The
|
||||
<tt>settimeout</tt> method defines a limit on the amount of time the
|
||||
I/O methods can block. When a timeout is set and the specified amount of
|
||||
time has elapsed, the affected methods give up and fail with an error code.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
The amount of time to wait is specified as the
|
||||
<tt>value</tt> parameter, in seconds. There are two timeout modes and
|
||||
both can be used together for fine tuning:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> '<tt>b</tt>': <em>block</em> timeout. Specifies the upper limit on
|
||||
the amount of time LuaSocket can be blocked by the operating system
|
||||
while waiting for completion of any single I/O operation. This is the
|
||||
default mode;</li>
|
||||
|
||||
<li> '<tt>t</tt>': <em>total</em> timeout. Specifies the upper limit on
|
||||
the amount of time LuaSocket can block a Lua script before returning from
|
||||
a call.</li>
|
||||
</ul>
|
||||
|
||||
<p class=parameters>
|
||||
The <b><tt>nil</tt></b> timeout <tt>value</tt> allows operations to block
|
||||
indefinitely. Negative timeout values have the same effect.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: although timeout values have millisecond precision in LuaSocket,
|
||||
large blocks can cause I/O functions not to respect timeout values due
|
||||
to the time the library takes to transfer blocks to and from the OS
|
||||
and to and from the Lua interpreter. Also, function that accept host names
|
||||
and perform automatic name resolution might be blocked by the resolver for
|
||||
longer than the specified timeout value.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The old <tt>timeout</tt> method is deprecated. The name has been
|
||||
changed for sake of uniformity, since all other method names already
|
||||
contained verbs making their imperative nature obvious.
|
||||
</p>
|
||||
|
||||
<!-- shutdown +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=shutdown>
|
||||
client:<b>shutdown(</b>mode<b>)</b><br>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Shuts down part of a full-duplex connection.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
Mode tells which way of the connection should be shut down and can
|
||||
take the value:
|
||||
<ul>
|
||||
<li>"<tt>both</tt>": disallow further sends and receives on the object.
|
||||
This is the default mode;
|
||||
<li>"<tt>send</tt>": disallow further sends on the object;
|
||||
<li>"<tt>receive</tt>": disallow further receives on the object.
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
This function returns 1.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:58:10 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,416 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: The UDP support">
|
||||
<meta name="keywords" content="Lua, LuaSocket, Socket, UDP, Library, Network, Support">
|
||||
<title>LuaSocket: UDP support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=udp>UDP</h2>
|
||||
|
||||
<!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="socket.udp">
|
||||
socket.<b>udp()</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Creates and returns an unconnected UDP object. Unconnected objects support the
|
||||
<a href="#sendto"><tt>sendto</tt></a>,
|
||||
<a href="#receive"><tt>receive</tt></a>,
|
||||
<a href="#receivefrom"><tt>receivefrom</tt></a>,
|
||||
<a href="#getsockname"><tt>getsockname</tt></a>,
|
||||
<a href="#setoption"><tt>setoption</tt></a>,
|
||||
<a href="#settimeout"><tt>settimeout</tt></a>,
|
||||
<a href="#setpeername"><tt>setpeername</tt></a>,
|
||||
<a href="#setsockname"><tt>setsockname</tt></a>, and
|
||||
<a href="#close"><tt>close</tt></a>.
|
||||
The <a href="#setpeername"><tt>setpeername</tt></a>
|
||||
is used to connect the object.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
In case of success, a new unconnected UDP object
|
||||
returned. In case of error, <b><tt>nil</tt></b> is returned, followed by
|
||||
an error message.
|
||||
</p>
|
||||
|
||||
<!-- close +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="close">
|
||||
connected:<b>close()</b><br>
|
||||
unconnected:<b>close()</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Closes a UDP object. The internal socket
|
||||
used by the object is closed and the local address to which the
|
||||
object was bound is made available to other applications. No
|
||||
further operations (except for further calls to the <tt>close</tt>
|
||||
method) are allowed on a closed socket.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: It is important to close all used sockets
|
||||
once they are not needed, since, in many systems, each socket uses
|
||||
a file descriptor, which are limited system resources.
|
||||
Garbage-collected objects are automatically closed before
|
||||
destruction, though.
|
||||
</p>
|
||||
|
||||
<!-- getpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="getpeername">
|
||||
connected:<b>getpeername()</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Retrieves information about the peer
|
||||
associated with a connected UDP object.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
Returns the IP address and port number of the peer.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: It makes no sense to call this method on unconnected objects.
|
||||
</p>
|
||||
|
||||
<!-- getsockname +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="getsockname">
|
||||
connected:<b>getsockname()</b><br>
|
||||
unconnected:<b>getsockname()</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Returns the local address information associated to the object.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
The method returns a string with local IP
|
||||
address and a number with the port. In case of error, the method
|
||||
returns <b><tt>nil</tt></b>.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: UDP sockets are not bound to any address
|
||||
until the <a href="#setsockname"><tt>setsockname</tt></a> or the
|
||||
<a href="#sendto"><tt>sendto</tt></a> method is called for the
|
||||
first time (in which case it is bound to an ephemeral port and the
|
||||
wild-card address).
|
||||
</p>
|
||||
|
||||
<!-- receive +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="receive">
|
||||
connected:<b>receive(</b>[size]<b>)</b><br>
|
||||
unconnected:<b>receive(</b>[size]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Receives a datagram from the UDP object. If
|
||||
the UDP object is connected, only datagrams coming from the peer
|
||||
are accepted. Otherwise, the returned datagram can come from any
|
||||
host.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
The optional <tt>size</tt> parameter
|
||||
specifies the maximum size of the datagram to be retrieved. If
|
||||
there are more than <tt>size</tt> bytes available in the datagram,
|
||||
the excess bytes are discarded. If there are less then
|
||||
<tt>size</tt> bytes available in the current datagram, the
|
||||
available bytes are returned. If <tt>size</tt> is omitted, the
|
||||
maximum datagram size is used (which is currently limited by the
|
||||
implementation to 8192 bytes).
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
In case of success, the method returns the
|
||||
received datagram. In case of timeout, the method returns
|
||||
<b><tt>nil</tt></b> followed by the string '<tt>timeout</tt>'.
|
||||
</p>
|
||||
|
||||
<!-- receivefrom +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="receivefrom">
|
||||
unconnected:<b>receivefrom(</b>[size]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Works exactly as the <a href="#receive"><tt>receive</tt></a>
|
||||
method, except it returns the IP
|
||||
address and port as extra return values (and is therefore slightly less
|
||||
efficient).
|
||||
</p>
|
||||
|
||||
<!-- send ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="send">
|
||||
connected:<b>send(</b>datagram<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Sends a datagram to the UDP peer of a connected object.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
<tt>Datagram</tt> is a string with the datagram contents.
|
||||
The maximum datagram size for UDP is 64K minus IP layer overhead.
|
||||
However datagrams larger than the link layer packet size will be
|
||||
fragmented, which may deteriorate performance and/or reliability.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
If successful, the method returns 1. In case of
|
||||
error, the method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: In UDP, the <tt>send</tt> method never blocks
|
||||
and the only way it can fail is if the underlying transport layer
|
||||
refuses to send a message to the specified address (i.e. no
|
||||
interface accepts the address).
|
||||
</p>
|
||||
|
||||
<!-- sendto ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="sendto">
|
||||
unconnected:<b>sendto(</b>datagram, ip, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Sends a datagram to the specified IP address and port number.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
<tt>Datagram</tt> is a string with the
|
||||
datagram contents.
|
||||
The maximum datagram size for UDP is 64K minus IP layer overhead.
|
||||
However datagrams larger than the link layer packet size will be
|
||||
fragmented, which may deteriorate performance and/or reliability.
|
||||
<tt>Ip</tt> is the IP address of the recipient.
|
||||
Host names are <em>not</em> allowed for performance reasons.
|
||||
|
||||
<tt>Port</tt> is the port number at the recipient.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
If successful, the method returns 1. In case of
|
||||
error, the method returns <b><tt>nil</tt></b> followed by an error message.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: In UDP, the <tt>send</tt> method never blocks
|
||||
and the only way it can fail is if the underlying transport layer
|
||||
refuses to send a message to the specified address (i.e. no
|
||||
interface accepts the address).
|
||||
</p>
|
||||
|
||||
<!-- setpeername +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="setpeername">
|
||||
connected:<b>setpeername(</b>'*'<b>)</b><br>
|
||||
unconnected:<b>setpeername(</b>address, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Changes the peer of a UDP object. This
|
||||
method turns an unconnected UDP object into a connected UDP
|
||||
object or vice versa.
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
For connected objects, outgoing datagrams
|
||||
will be sent to the specified peer, and datagrams received from
|
||||
other peers will be discarded by the OS. Connected UDP objects must
|
||||
use the <a href="#send"><tt>send</tt></a> and
|
||||
<a href="#receive"><tt>receive</tt></a> methods instead of
|
||||
<a href="#sendto"><tt>sendto</tt></a> and
|
||||
<a href="#receivefrom"><tt>receivefrom</tt></a>.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
<tt>Address</tt> can be an IP address or a
|
||||
host name. <tt>Port</tt> is the port number. If <tt>address</tt> is
|
||||
'<tt>*</tt>' and the object is connected, the peer association is
|
||||
removed and the object becomes an unconnected object again. In that
|
||||
case, the <tt>port</tt> argument is ignored.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
In case of error the method returns
|
||||
<b><tt>nil</tt></b> followed by an error message. In case of success, the
|
||||
method returns 1.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: Since the address of the peer does not have
|
||||
to be passed to and from the OS, the use of connected UDP objects
|
||||
is recommended when the same peer is used for several transmissions
|
||||
and can result in up to 30% performance gains.
|
||||
</p>
|
||||
|
||||
<!-- setsockname +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="setsockname">
|
||||
unconnected:<b>setsockname(</b>address, port<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Binds the UDP object to a local address.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
<tt>Address</tt> can be an IP address or a
|
||||
host name. If <tt>address</tt> is '<tt>*</tt>' the system binds to
|
||||
all local interfaces using the constant <tt>INADDR_ANY</tt>. If
|
||||
<tt>port</tt> is 0, the system chooses an ephemeral port.
|
||||
</p>
|
||||
|
||||
<p class="return">
|
||||
If successful, the method returns 1. In case of
|
||||
error, the method returns <b><tt>nil</tt></b> followed by an error
|
||||
message.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: This method can only be called before any
|
||||
datagram is sent through the UDP object, and only once. Otherwise,
|
||||
the system automatically binds the object to all local interfaces
|
||||
and chooses an ephemeral port as soon as the first datagram is
|
||||
sent. After the local address is set, either automatically by the
|
||||
system or explicitly by <tt>setsockname</tt>, it cannot be
|
||||
changed.
|
||||
</p>
|
||||
|
||||
<!-- setoption +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="setoption">
|
||||
connected:<b>setoption(</b>option [, value]<b>)</b><br>
|
||||
unconnected:<b>setoption(</b>option [, value]<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Sets options for the UDP object. Options are
|
||||
only needed by low-level or time-critical applications. You should
|
||||
only modify an option if you are sure you need it.</p>
|
||||
<p class="parameters"><tt>Option</tt> is a string with the option
|
||||
name, and <tt>value</tt> depends on the option being set:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>'<tt>dontroute</tt>': Setting this option to <tt>true</tt>
|
||||
indicates that outgoing messages should bypass the standard routing
|
||||
facilities;</li>
|
||||
<li>'<tt>broadcast</tt>': Setting this option to <tt>true</tt>
|
||||
requests permission to send broadcast datagrams on the
|
||||
socket.</li>
|
||||
</ul>
|
||||
|
||||
<p class="return">
|
||||
The method returns 1 in case of success, or
|
||||
<b><tt>nil</tt></b> followed by an error message otherwise.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: The descriptions above come from the man
|
||||
pages.
|
||||
</p>
|
||||
|
||||
<!-- settimeout +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class="name" id="settimeout">
|
||||
connected:<b>settimeout(</b>value<b>)</b><br>
|
||||
unconnected:<b>settimeout(</b>value<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class="description">
|
||||
Changes the timeout values for the object. By default, the
|
||||
<a href="#receive"><tt>receive</tt></a> and
|
||||
<a href="#receivefrom"><tt>receivefrom</tt></a>
|
||||
operations are blocking. That is, any call to the methods will block
|
||||
indefinitely, until data arrives. The <tt>settimeout</tt> function defines
|
||||
a limit on the amount of time the functions can block. When a timeout is
|
||||
set and the specified amount of time has elapsed, the affected methods
|
||||
give up and fail with an error code.
|
||||
</p>
|
||||
|
||||
<p class="parameters">
|
||||
The amount of time to wait is specified as
|
||||
the <tt>value</tt> parameter, in seconds. The <b><tt>nil</tt></b> timeout
|
||||
<tt>value</tt> allows operations to block indefinitely. Negative
|
||||
timeout values have the same effect.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: In UDP, the <a href="#send"><tt>send</tt></a>
|
||||
and <a href="#sentdo"><tt>sendto</tt></a> methods never block (the
|
||||
datagram is just passed to the OS and the call returns
|
||||
immediately). Therefore, the <tt>settimeout</tt> method has no
|
||||
effect on them.
|
||||
</p>
|
||||
|
||||
<p class="note">
|
||||
Note: The old <tt>timeout</tt> method is
|
||||
deprecated. The name has been changed for sake of uniformity, since
|
||||
all other method names already contained verbs making their
|
||||
imperative nature obvious.
|
||||
</p>
|
||||
|
||||
<!-- footer ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:58:15 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,329 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="description" content="LuaSocket: URL manipulation">
|
||||
<meta name="keywords" content="Lua, LuaSocket, URL, Library, Link, Network, Support">
|
||||
<title>LuaSocket: URL support</title>
|
||||
<link rel="stylesheet" href="reference.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- header +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=header>
|
||||
<hr>
|
||||
<center>
|
||||
<table summary="LuaSocket logo">
|
||||
<tr><td align=center><a href="http://www.lua.org">
|
||||
<img width=128 height=128 border=0 alt="LuaSocket" src="luasocket.png">
|
||||
</a></td></tr>
|
||||
<tr><td align=center valign=top>Network support for the Lua language
|
||||
</td></tr>
|
||||
</table>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#download">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
</center>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<!-- url ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<h2 id=url>URL</h2>
|
||||
|
||||
<p>
|
||||
The <tt>url</tt> namespace provides functions to parse, protect,
|
||||
and build URLs, as well as functions to compose absolute URLs
|
||||
from base and relative URLs, according to
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC
|
||||
2396</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To obtain the <tt>url</tt> namespace, run:
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- loads the URL module
|
||||
local url = require("socket.url")
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
An URL is defined by the following grammar:
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<tt>
|
||||
<url> ::= [<scheme>:][//<authority>][/<path>][;<params>][?<query>][#<fragment>]<br>
|
||||
<authority> ::= [<userinfo>@]<host>[:<port>]<br>
|
||||
<userinfo> ::= <user>[:<password>]<br>
|
||||
<path> ::= {<segment>/}<segment><br>
|
||||
</tt>
|
||||
</blockquote>
|
||||
|
||||
<!-- absolute +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=absolute>
|
||||
url.<b>absolute(</b>base, relative<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Builds an absolute URL from a base URL and a relative URL.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Base</tt> is a string with the base URL or
|
||||
a parsed URL table. <tt>Relative</tt> is a
|
||||
string with the relative URL.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a string with the absolute URL.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The rules that
|
||||
govern the composition are fairly complex, and are described in detail in
|
||||
<a href="http://www.cs.princeton.edu/~diego/rfc/rfc2396.txt">RFC 2396</a>.
|
||||
The example bellow should give an idea of what the rules are.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
http://a/b/c/d;p?q
|
||||
|
||||
+
|
||||
|
||||
g:h = g:h
|
||||
g = http://a/b/c/g
|
||||
./g = http://a/b/c/g
|
||||
g/ = http://a/b/c/g/
|
||||
/g = http://a/g
|
||||
//g = http://g
|
||||
?y = http://a/b/c/?y
|
||||
g?y = http://a/b/c/g?y
|
||||
#s = http://a/b/c/d;p?q#s
|
||||
g#s = http://a/b/c/g#s
|
||||
g?y#s = http://a/b/c/g?y#s
|
||||
;x = http://a/b/c/;x
|
||||
g;x = http://a/b/c/g;x
|
||||
g;x?y#s = http://a/b/c/g;x?y#s
|
||||
. = http://a/b/c/
|
||||
./ = http://a/b/c/
|
||||
.. = http://a/b/
|
||||
../ = http://a/b/
|
||||
../g = http://a/b/g
|
||||
../.. = http://a/
|
||||
../../ = http://a/
|
||||
../../g = http://a/g
|
||||
</pre>
|
||||
|
||||
<!-- build ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=build>
|
||||
url.<b>build(</b>parsed_url<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Rebuilds an URL from its parts.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Parsed_url</tt> is a table with same components returned by
|
||||
<a href="#parse"><tt>parse</tt></a>.
|
||||
Lower level components, if specified,
|
||||
take precedence over high level components of the URL grammar.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a string with the built URL.
|
||||
</p>
|
||||
|
||||
<!-- build_path +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=build_path>
|
||||
url.<b>build_path(</b>segments, unsafe<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Builds a <tt><path></tt> component from a list of
|
||||
<tt><segment></tt> parts.
|
||||
Before composition, any reserved characters found in a segment are escaped into
|
||||
their protected form, so that the resulting path is a valid URL path
|
||||
component.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Segments</tt> is a list of strings with the <tt><segment></tt>
|
||||
parts. If <tt>unsafe</tt> is anything but <b><tt>nil</tt></b>, reserved
|
||||
characters are left untouched.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a string with the
|
||||
built <tt><path></tt> component.
|
||||
</p>
|
||||
|
||||
<!-- escape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="escape">
|
||||
url.<b>escape(</b>content<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Applies the URL escaping content coding to a string
|
||||
Each byte is encoded as a percent character followed
|
||||
by the two byte hexadecimal representation of its integer
|
||||
value.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Content</tt> is the string to be encoded.
|
||||
</p>
|
||||
|
||||
<p class=result>
|
||||
The function returns the encoded string.
|
||||
</p>
|
||||
|
||||
<pre class=example>
|
||||
-- load url module
|
||||
url = require("socket.url")
|
||||
|
||||
code = url.escape("/#?;")
|
||||
-- code = "%2f%23%3f%3b"
|
||||
</pre>
|
||||
|
||||
<!-- parse ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=parse>
|
||||
url.<b>parse(</b>url, default<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Parses an URL given as a string into a Lua table with its components.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Url</tt> is the URL to be parsed. If the <tt>default</tt> table is
|
||||
present, it is used to store the parsed fields. Only fields present in the
|
||||
URL are overwritten. Therefore, this table can be used to pass default
|
||||
values for each field.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns a table with all the URL components:
|
||||
</p>
|
||||
|
||||
<blockquote><tt>
|
||||
parsed_url = {<br>
|
||||
url = <i>string</i>,<br>
|
||||
scheme = <i>string</i>,<br>
|
||||
authority = <i>string</i>,<br>
|
||||
path = <i>string</i>,<br>
|
||||
params = <i>string</i>,<br>
|
||||
query = <i>string</i>,<br>
|
||||
fragment = <i>string</i>,<br>
|
||||
userinfo = <i>string</i>,<br>
|
||||
host = <i>string</i>,<br>
|
||||
port = <i>string</i>,<br>
|
||||
user = <i>string</i>,<br>
|
||||
password = <i>string</i><br>
|
||||
}
|
||||
</tt></blockquote>
|
||||
|
||||
<pre class=example>
|
||||
-- load url module
|
||||
url = require("socket.url")
|
||||
|
||||
parsed_url = url.parse("http://www.example.com/cgilua/index.lua?a=2#there")
|
||||
-- parsed_url = {
|
||||
-- scheme = "http",
|
||||
-- authority = "www.example.com",
|
||||
-- path = "/cgilua/index.lua"
|
||||
-- query = "a=2",
|
||||
-- fragment = "there",
|
||||
-- host = "www.puc-rio.br",
|
||||
-- }
|
||||
|
||||
parsed_url = url.parse("ftp://root:passwd@unsafe.org/pub/virus.exe;type=i")
|
||||
-- parsed_url = {
|
||||
-- scheme = "ftp",
|
||||
-- authority = "root:passwd@unsafe.org",
|
||||
-- path = "/pub/virus.exe",
|
||||
-- params = "type=i",
|
||||
-- userinfo = "root:passwd",
|
||||
-- host = "unsafe.org",
|
||||
-- user = "root",
|
||||
-- password = "passwd",
|
||||
-- }
|
||||
</pre>
|
||||
|
||||
<!-- parse_path +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=parse_path>
|
||||
url.<b>parse_path(</b>path<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Breaks a <tt><path></tt> URL component into all its
|
||||
<tt><segment></tt> parts.
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
<tt>Path</tt> is a string with the path to be parsed.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
Since some characters are reserved in URLs, they must be escaped
|
||||
whenever present in a <tt><path></tt> component. Therefore, before
|
||||
returning a list with all the parsed segments, the function removes
|
||||
escaping from all of them.
|
||||
</p>
|
||||
|
||||
<!-- unescape +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id="unescape">
|
||||
url.<b>unescape(</b>content<b>)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Removes the URL escaping content coding from a string.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Content</tt> is the string to be decoded.
|
||||
</p>
|
||||
|
||||
<p class=return>
|
||||
The function returns the decoded string.
|
||||
</p>
|
||||
|
||||
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<div class=footer>
|
||||
<hr>
|
||||
<center>
|
||||
<p class=bar>
|
||||
<a href="home.html">home</a> ·
|
||||
<a href="home.html#down">download</a> ·
|
||||
<a href="installation.html">installation</a> ·
|
||||
<a href="introduction.html">introduction</a> ·
|
||||
<a href="reference.html">reference</a>
|
||||
</p>
|
||||
<p>
|
||||
<small>
|
||||
Last modified by Diego Nehab on <br>
|
||||
Mon Nov 21 01:58:20 EST 2005
|
||||
</small>
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,11 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# ONLY FOR MAINTAINER USE!!
|
||||
|
||||
destdir="$HOME/.minetest/games/testing/mods/irc";
|
||||
|
||||
echo rm -fr "\"$destdir\"";
|
||||
rm -fr "$destdir";
|
||||
|
||||
echo cp -fr Build/irc "\"$destdir\"";
|
||||
cp -fr Build/irc "$destdir";
|
@ -1,50 +0,0 @@
|
||||
This directory contains some sample programs using
|
||||
LuaSocket. This code is not supported.
|
||||
|
||||
listener.lua -- socket to stdout
|
||||
talker.lua -- stdin to socket
|
||||
|
||||
listener.lua and talker.lua are about the simplest
|
||||
applications you can write using LuaSocket. Run
|
||||
|
||||
'lua listener.lua' and 'lua talker.lua'
|
||||
|
||||
on different terminals. Whatever you type on talk.lua will
|
||||
be printed by listen.lua.
|
||||
|
||||
lpr.lua -- lpr client
|
||||
|
||||
This is a cool program written by David Burgess to print
|
||||
files using the Line Printer Daemon protocol, widely used in
|
||||
Unix machines. It uses the lp.lua implementation, in the
|
||||
etc directory. Just run 'lua lpr.lua <filename>
|
||||
queue=<printername>' and the file will print!
|
||||
|
||||
cddb.lua -- CDDB client
|
||||
|
||||
This is the first try on a simple CDDB client. Not really
|
||||
useful, but one day it might become a module.
|
||||
|
||||
daytimeclnt.lua -- day time client
|
||||
|
||||
Just run the program to retrieve the hour and date in
|
||||
readable form from any server running an UDP daytime daemon.
|
||||
|
||||
echoclnt.lua -- UDP echo client
|
||||
echosrvr.lua -- UDP echo server
|
||||
|
||||
These are a UDP echo client/server pair. They work with
|
||||
other client and servers as well.
|
||||
|
||||
tinyirc.lua -- irc like broadcast server
|
||||
|
||||
This is a simple server that waits simultaneously on two
|
||||
server sockets for telnet connections. Everything it
|
||||
receives from the telnet clients is broadcasted to every
|
||||
other connected client. It tests the select function and
|
||||
shows how to create a simple server whith LuaSocket. Just
|
||||
run tinyirc.lua and then open as many telnet connections
|
||||
as you want to ports 8080 and 8081.
|
||||
|
||||
Good luck,
|
||||
Diego.
|
@ -1,46 +0,0 @@
|
||||
local socket = require("socket")
|
||||
local http = require("socket.http")
|
||||
|
||||
if not arg or not arg[1] or not arg[2] then
|
||||
print("luasocket cddb.lua <category> <disc-id> [<server>]")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local server = arg[3] or "http://freedb.freedb.org/~cddb/cddb.cgi"
|
||||
|
||||
function parse(body)
|
||||
local lines = string.gfind(body, "(.-)\r\n")
|
||||
local status = lines()
|
||||
local code, message = socket.skip(2, string.find(status, "(%d%d%d) (.*)"))
|
||||
if tonumber(code) ~= 210 then
|
||||
return nil, code, message
|
||||
end
|
||||
local data = {}
|
||||
for l in lines do
|
||||
local c = string.sub(l, 1, 1)
|
||||
if c ~= '#' and c ~= '.' then
|
||||
local key, value = socket.skip(2, string.find(l, "(.-)=(.*)"))
|
||||
value = string.gsub(value, "\\n", "\n")
|
||||
value = string.gsub(value, "\\\\", "\\")
|
||||
value = string.gsub(value, "\\t", "\t")
|
||||
data[key] = value
|
||||
end
|
||||
end
|
||||
return data, code, message
|
||||
end
|
||||
|
||||
local host = socket.dns.gethostname()
|
||||
local query = "%s?cmd=cddb+read+%s+%s&hello=LuaSocket+%s+LuaSocket+2.0&proto=6"
|
||||
local url = string.format(query, server, arg[1], arg[2], host)
|
||||
local body, headers, code = http.get(url)
|
||||
|
||||
if code == 200 then
|
||||
local data, code, error = parse(body)
|
||||
if not data then
|
||||
print(error or code)
|
||||
else
|
||||
for i,v in pairs(data) do
|
||||
io.write(i, ': ', v, '\n')
|
||||
end
|
||||
end
|
||||
else print(error) end
|
@ -1,23 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: daytime protocol client
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: daytimeclnt.lua,v 1.11 2004/06/21 06:07:57 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require"socket"
|
||||
host = host or "127.0.0.1"
|
||||
port = port or 13
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port = arg[2] or port
|
||||
end
|
||||
host = socket.dns.toip(host)
|
||||
udp = socket.udp()
|
||||
print("Using host '" ..host.. "' and port " ..port.. "...")
|
||||
udp:setpeername(host, port)
|
||||
udp:settimeout(3)
|
||||
sent, err = udp:send("anything")
|
||||
if err then print(err) os.exit() end
|
||||
dgram, err = udp:receive()
|
||||
if not dgram then print(err) os.exit() end
|
||||
io.write(dgram)
|
@ -1,24 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol client
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: echoclnt.lua,v 1.10 2005/01/02 22:44:00 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
host = host or "localhost"
|
||||
port = port or 7
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port = arg[2] or port
|
||||
end
|
||||
host = socket.dns.toip(host)
|
||||
udp = assert(socket.udp())
|
||||
assert(udp:setpeername(host, port))
|
||||
print("Using remote host '" ..host.. "' and port " .. port .. "...")
|
||||
while 1 do
|
||||
line = io.read()
|
||||
if not line or line == "" then os.exit() end
|
||||
assert(udp:send(line))
|
||||
dgram = assert(udp:receive())
|
||||
print(dgram)
|
||||
end
|
@ -1,29 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol server
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: echosrvr.lua,v 1.12 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
host = host or "127.0.0.1"
|
||||
port = port or 7
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port = arg[2] or port
|
||||
end
|
||||
print("Binding to host '" ..host.. "' and port " ..port.. "...")
|
||||
udp = assert(socket.udp())
|
||||
assert(udp:setsockname(host, port))
|
||||
assert(udp:settimeout(5))
|
||||
ip, port = udp:getsockname()
|
||||
assert(ip, port)
|
||||
print("Waiting packets on " .. ip .. ":" .. port .. "...")
|
||||
while 1 do
|
||||
dgram, ip, port = udp:receivefrom()
|
||||
if dgram then
|
||||
print("Echoing '" .. dgram .. "' to " .. ip .. ":" .. port)
|
||||
udp:sendto(dgram, ip, port)
|
||||
else
|
||||
print(ip)
|
||||
end
|
||||
end
|
@ -1,26 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TCP sample: Little program to dump lines received at a given port
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: listener.lua,v 1.11 2005/01/02 22:44:00 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
host = host or "*"
|
||||
port = port or 8080
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port = arg[2] or port
|
||||
end
|
||||
print("Binding to host '" ..host.. "' and port " ..port.. "...")
|
||||
s = assert(socket.bind(host, port))
|
||||
i, p = s:getsockname()
|
||||
assert(i, p)
|
||||
print("Waiting connection from talker on " .. i .. ":" .. p .. "...")
|
||||
c = assert(s:accept())
|
||||
print("Connected. Here is the stuff:")
|
||||
l, e = c:receive()
|
||||
while not e do
|
||||
print(l)
|
||||
l, e = c:receive()
|
||||
end
|
||||
print(e)
|
@ -1,51 +0,0 @@
|
||||
local lp = require("socket.lp")
|
||||
|
||||
local function usage()
|
||||
print('\nUsage: lua lpr.lua [filename] [keyword=val...]\n')
|
||||
print('Valid keywords are :')
|
||||
print(
|
||||
' host=remote host or IP address (default "localhost")\n' ..
|
||||
' queue=remote queue or printer name (default "printer")\n' ..
|
||||
' port=remote port number (default 515)\n' ..
|
||||
' user=sending user name\n' ..
|
||||
' format=["binary" | "text" | "ps" | "pr" | "fortran"] (default "binary")\n' ..
|
||||
' banner=true|false\n' ..
|
||||
' indent=number of columns to indent\n' ..
|
||||
' mail=email of address to notify when print is complete\n' ..
|
||||
' title=title to use for "pr" format\n' ..
|
||||
' width=width for "text" or "pr" formats\n' ..
|
||||
' class=\n' ..
|
||||
' job=\n' ..
|
||||
' name=\n' ..
|
||||
' localbind=true|false\n'
|
||||
)
|
||||
return nil
|
||||
end
|
||||
|
||||
if not arg or not arg[1] then
|
||||
return usage()
|
||||
end
|
||||
|
||||
do
|
||||
local opt = {}
|
||||
local pat = "[%s%c%p]*([%w]*)=([\"]?[%w%s_!@#$%%^&*()<>:;]+[\"]\?\.?)"
|
||||
for i = 2, table.getn(arg), 1 do
|
||||
string.gsub(arg[i], pat, function(name, value) opt[name] = value end)
|
||||
end
|
||||
if not arg[2] then
|
||||
return usage()
|
||||
end
|
||||
if arg[1] ~= "query" then
|
||||
opt.file = arg[1]
|
||||
r,e=lp.send(opt)
|
||||
io.stdout:write(tostring(r or e),'\n')
|
||||
else
|
||||
r,e=lp.query(opt)
|
||||
io.stdout:write(tostring(r or e), '\n')
|
||||
end
|
||||
end
|
||||
|
||||
-- trivial tests
|
||||
--lua lp.lua lp.lua queue=default host=localhost
|
||||
--lua lp.lua lp.lua queue=default host=localhost format=binary localbind=1
|
||||
--lua lp.lua query queue=default host=localhost
|
@ -1,21 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TCP sample: Little program to send text lines to a given host/port
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: talker.lua,v 1.9 2005/01/02 22:44:00 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
host = host or "localhost"
|
||||
port = port or 8080
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port = arg[2] or port
|
||||
end
|
||||
print("Attempting connection to host '" ..host.. "' and port " ..port.. "...")
|
||||
c = assert(socket.connect(host, port))
|
||||
print("Connected! Please type stuff (empty line to stop):")
|
||||
l = io.read()
|
||||
while l and l ~= "" and not e do
|
||||
assert(c:send(l .. "\n"))
|
||||
l = io.read()
|
||||
end
|
@ -1,90 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Select sample: simple text line server
|
||||
-- LuaSocket sample files.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: tinyirc.lua,v 1.14 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
host = host or "*"
|
||||
port1 = port1 or 8080
|
||||
port2 = port2 or 8181
|
||||
if arg then
|
||||
host = arg[1] or host
|
||||
port1 = arg[2] or port1
|
||||
port2 = arg[3] or port2
|
||||
end
|
||||
|
||||
server1 = assert(socket.bind(host, port1))
|
||||
server2 = assert(socket.bind(host, port2))
|
||||
server1:settimeout(1) -- make sure we don't block in accept
|
||||
server2:settimeout(1)
|
||||
|
||||
io.write("Servers bound\n")
|
||||
|
||||
-- simple set implementation
|
||||
-- the select function doesn't care about what is passed to it as long as
|
||||
-- it behaves like a table
|
||||
-- creates a new set data structure
|
||||
function newset()
|
||||
local reverse = {}
|
||||
local set = {}
|
||||
return setmetatable(set, {__index = {
|
||||
insert = function(set, value)
|
||||
if not reverse[value] then
|
||||
table.insert(set, value)
|
||||
reverse[value] = table.getn(set)
|
||||
end
|
||||
end,
|
||||
remove = function(set, value)
|
||||
local index = reverse[value]
|
||||
if index then
|
||||
reverse[value] = nil
|
||||
local top = table.remove(set)
|
||||
if top ~= value then
|
||||
reverse[top] = index
|
||||
set[index] = top
|
||||
end
|
||||
end
|
||||
end
|
||||
}})
|
||||
end
|
||||
|
||||
set = newset()
|
||||
|
||||
io.write("Inserting servers in set\n")
|
||||
set:insert(server1)
|
||||
set:insert(server2)
|
||||
|
||||
while 1 do
|
||||
local readable, _, error = socket.select(set, nil)
|
||||
for _, input in ipairs(readable) do
|
||||
-- is it a server socket?
|
||||
if input == server1 or input == server2 then
|
||||
io.write("Waiting for clients\n")
|
||||
local new = input:accept()
|
||||
if new then
|
||||
new:settimeout(1)
|
||||
io.write("Inserting client in set\n")
|
||||
set:insert(new)
|
||||
end
|
||||
-- it is a client socket
|
||||
else
|
||||
local line, error = input:receive()
|
||||
if error then
|
||||
input:close()
|
||||
io.write("Removing client from set\n")
|
||||
set:remove(input)
|
||||
else
|
||||
io.write("Broadcasting line '", line, "'\n")
|
||||
writable, error = socket.skip(1, socket.select(nil, set, 1))
|
||||
if not error then
|
||||
for __, output in ipairs(writable) do
|
||||
if output ~= input then
|
||||
output:send(line .. "\n")
|
||||
end
|
||||
end
|
||||
else io.write("No client ready to receive!!!\n") end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,89 +0,0 @@
|
||||
This directory contains code that is more useful than the
|
||||
samples. This code *is* supported.
|
||||
|
||||
tftp.lua -- Trivial FTP client
|
||||
|
||||
This module implements file retrieval by the TFTP protocol.
|
||||
Its main use was to test the UDP code, but since someone
|
||||
found it usefull, I turned it into a module that is almost
|
||||
official (no uploads, yet).
|
||||
|
||||
dict.lua -- Dict client
|
||||
|
||||
The dict.lua module started with a cool simple client
|
||||
for the DICT protocol, written by Luiz Henrique Figueiredo.
|
||||
This new version has been converted into a library, similar
|
||||
to the HTTP and FTP libraries, that can be used from within
|
||||
any luasocket application. Take a look on the source code
|
||||
and you will be able to figure out how to use it.
|
||||
|
||||
lp.lua -- LPD client library
|
||||
|
||||
The lp.lua module implements the client part of the Line
|
||||
Printer Daemon protocol, used to print files on Unix
|
||||
machines. It is courtesy of David Burgess! See the source
|
||||
code and the lpr.lua in the examples directory.
|
||||
|
||||
b64.lua
|
||||
qp.lua
|
||||
eol.lua
|
||||
|
||||
These are tiny programs that perform Base64,
|
||||
Quoted-Printable and end-of-line marker conversions.
|
||||
|
||||
get.lua -- file retriever
|
||||
|
||||
This little program is a client that uses the FTP and
|
||||
HTTP code to implement a command line file graber. Just
|
||||
run
|
||||
|
||||
lua get.lua <remote-file> [<local-file>]
|
||||
|
||||
to download a remote file (either ftp:// or http://) to
|
||||
the specified local file. The program also prints the
|
||||
download throughput, elapsed time, bytes already downloaded
|
||||
etc during download.
|
||||
|
||||
check-memory.lua -- checks memory consumption
|
||||
|
||||
This is just to see how much memory each module uses.
|
||||
|
||||
dispatch.lua -- coroutine based dispatcher
|
||||
|
||||
This is a first try at a coroutine based non-blocking
|
||||
dispatcher for LuaSocket. Take a look at 'check-links.lua'
|
||||
and at 'forward.lua' to see how to use it.
|
||||
|
||||
check-links.lua -- HTML link checker program
|
||||
|
||||
This little program scans a HTML file and checks for broken
|
||||
links. It is similar to check-links.pl by Jamie Zawinski,
|
||||
but uses all facilities of the LuaSocket library and the Lua
|
||||
language. It has not been thoroughly tested, but it should
|
||||
work. Just run
|
||||
|
||||
lua check-links.lua [-n] {<url>} > output
|
||||
|
||||
and open the result to see a list of broken links. You can
|
||||
also use the '-n' switch to run the same program in
|
||||
non-blocking mode to see how much faster things can get.
|
||||
|
||||
forward.lua -- coroutine based forward server
|
||||
|
||||
This is a forward server that can accept several connections
|
||||
and transfers simultaneously using non-blocking I/O and the
|
||||
coroutine-based dispatcher. You can run, for example
|
||||
|
||||
lua forward.lua 8080:proxy.com:3128
|
||||
|
||||
to redirect all local conections to port 8080 to the host
|
||||
'proxy.com' at port 3128.
|
||||
|
||||
unix.c and unix.h
|
||||
|
||||
This is an implementation of Unix local domain sockets and
|
||||
demonstrates how to extend LuaSocket with a new type of
|
||||
transport. It has been tested on Linux and on Mac OS X.
|
||||
|
||||
Good luck,
|
||||
Diego.
|
@ -1,20 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to convert to and from Base64
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: b64.lua,v 1.8 2004/06/16 04:28:21 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
local source = ltn12.source.file(io.stdin)
|
||||
local sink = ltn12.sink.file(io.stdout)
|
||||
local convert
|
||||
if arg and arg[1] == '-d' then
|
||||
convert = mime.decode("base64")
|
||||
else
|
||||
local base64 = mime.encode("base64")
|
||||
local wrap = mime.wrap()
|
||||
convert = ltn12.filter.chain(base64, wrap)
|
||||
end
|
||||
sink = ltn12.sink.chain(convert, sink)
|
||||
ltn12.pump.all(source, sink)
|
@ -1,112 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program that checks links in HTML files, using coroutines and
|
||||
-- non-blocking I/O via the dispatcher module.
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $$
|
||||
-----------------------------------------------------------------------------
|
||||
local url = require("socket.url")
|
||||
local dispatch = require("dispatch")
|
||||
local http = require("socket.http")
|
||||
dispatch.TIMEOUT = 10
|
||||
|
||||
-- make sure the user knows how to invoke us
|
||||
arg = arg or {}
|
||||
if table.getn(arg) < 1 then
|
||||
print("Usage:\n luasocket check-links.lua [-n] {<url>}")
|
||||
exit()
|
||||
end
|
||||
|
||||
-- '-n' means we are running in non-blocking mode
|
||||
if arg[1] == "-n" then
|
||||
-- if non-blocking I/O was requested, use real dispatcher interface
|
||||
table.remove(arg, 1)
|
||||
handler = dispatch.newhandler("coroutine")
|
||||
else
|
||||
-- if using blocking I/O, use fake dispatcher interface
|
||||
handler = dispatch.newhandler("sequential")
|
||||
end
|
||||
|
||||
local nthreads = 0
|
||||
|
||||
-- get the status of a URL using the dispatcher
|
||||
function getstatus(link)
|
||||
local parsed = url.parse(link, {scheme = "file"})
|
||||
if parsed.scheme == "http" then
|
||||
nthreads = nthreads + 1
|
||||
handler:start(function()
|
||||
local r, c, h, s = http.request{
|
||||
method = "HEAD",
|
||||
url = link,
|
||||
create = handler.tcp
|
||||
}
|
||||
if r and c == 200 then io.write('\t', link, '\n')
|
||||
else io.write('\t', link, ': ', tostring(c), '\n') end
|
||||
nthreads = nthreads - 1
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function readfile(path)
|
||||
path = url.unescape(path)
|
||||
local file, error = io.open(path, "r")
|
||||
if file then
|
||||
local body = file:read("*a")
|
||||
file:close()
|
||||
return body
|
||||
else return nil, error end
|
||||
end
|
||||
|
||||
function load(u)
|
||||
local parsed = url.parse(u, { scheme = "file" })
|
||||
local body, headers, code, error
|
||||
local base = u
|
||||
if parsed.scheme == "http" then
|
||||
body, code, headers = http.request(u)
|
||||
if code == 200 then
|
||||
-- if there was a redirect, update base to reflect it
|
||||
base = headers.location or base
|
||||
end
|
||||
if not body then
|
||||
error = code
|
||||
end
|
||||
elseif parsed.scheme == "file" then
|
||||
body, error = readfile(parsed.path)
|
||||
else error = string.format("unhandled scheme '%s'", parsed.scheme) end
|
||||
return base, body, error
|
||||
end
|
||||
|
||||
function getlinks(body, base)
|
||||
-- get rid of comments
|
||||
body = string.gsub(body, "%<%!%-%-.-%-%-%>", "")
|
||||
local links = {}
|
||||
-- extract links
|
||||
body = string.gsub(body, '[Hh][Rr][Ee][Ff]%s*=%s*"([^"]*)"', function(href)
|
||||
table.insert(links, url.absolute(base, href))
|
||||
end)
|
||||
body = string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*'([^']*)'", function(href)
|
||||
table.insert(links, url.absolute(base, href))
|
||||
end)
|
||||
string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*(.-)>", function(href)
|
||||
table.insert(links, url.absolute(base, href))
|
||||
end)
|
||||
return links
|
||||
end
|
||||
|
||||
function checklinks(address)
|
||||
local base, body, error = load(address)
|
||||
if not body then print(error) return end
|
||||
print("Checking ", base)
|
||||
local links = getlinks(body, base)
|
||||
for _, link in ipairs(links) do
|
||||
getstatus(link)
|
||||
end
|
||||
end
|
||||
|
||||
for _, address in ipairs(arg) do
|
||||
checklinks(url.absolute("file:", address))
|
||||
end
|
||||
|
||||
while nthreads > 0 do
|
||||
handler:step()
|
||||
end
|
@ -1,17 +0,0 @@
|
||||
function load(s)
|
||||
collectgarbage()
|
||||
local a = gcinfo()
|
||||
_G[s] = require(s)
|
||||
collectgarbage()
|
||||
local b = gcinfo()
|
||||
print(s .. ":\t " .. (b-a) .. "k")
|
||||
end
|
||||
|
||||
load("socket.url")
|
||||
load("ltn12")
|
||||
load("socket")
|
||||
load("mime")
|
||||
load("socket.tp")
|
||||
load("socket.smtp")
|
||||
load("socket.http")
|
||||
load("socket.ftp")
|
@ -1,152 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download DICT word definitions
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: dict.lua,v 1.22 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- 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)
|
||||
|
@ -1,301 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- A hacked dispatcher module
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $$
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local socket = require("socket")
|
||||
local coroutine = require("coroutine")
|
||||
module("dispatch")
|
||||
|
||||
-- if too much time goes by without any activity in one of our sockets, we
|
||||
-- just kill it
|
||||
TIMEOUT = 60
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- We implement 3 types of dispatchers:
|
||||
-- sequential
|
||||
-- coroutine
|
||||
-- threaded
|
||||
-- The user can choose whatever one is needed
|
||||
-----------------------------------------------------------------------------
|
||||
local handlert = {}
|
||||
|
||||
-- default handler is coroutine
|
||||
function newhandler(mode)
|
||||
mode = mode or "coroutine"
|
||||
return handlert[mode]()
|
||||
end
|
||||
|
||||
local function seqstart(self, func)
|
||||
return func()
|
||||
end
|
||||
|
||||
-- sequential handler simply calls the functions and doesn't wrap I/O
|
||||
function handlert.sequential()
|
||||
return {
|
||||
tcp = socket.tcp,
|
||||
start = seqstart
|
||||
}
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Mega hack. Don't try to do this at home.
|
||||
-----------------------------------------------------------------------------
|
||||
-- we can't yield across calls to protect, so we rewrite it with coxpcall
|
||||
-- make sure you don't require any module that uses socket.protect before
|
||||
-- loading our hack
|
||||
function socket.protect(f)
|
||||
return function(...)
|
||||
local co = coroutine.create(f)
|
||||
while true do
|
||||
local results = {coroutine.resume(co, unpack(arg))}
|
||||
local status = table.remove(results, 1)
|
||||
if not status then
|
||||
if type(results[1]) == 'table' then
|
||||
return nil, results[1][1]
|
||||
else error(results[1]) end
|
||||
end
|
||||
if coroutine.status(co) == "suspended" then
|
||||
arg = {coroutine.yield(unpack(results))}
|
||||
else
|
||||
return unpack(results)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Simple set data structure. O(1) everything.
|
||||
-----------------------------------------------------------------------------
|
||||
local function newset()
|
||||
local reverse = {}
|
||||
local set = {}
|
||||
return setmetatable(set, {__index = {
|
||||
insert = function(set, value)
|
||||
if not reverse[value] then
|
||||
table.insert(set, value)
|
||||
reverse[value] = table.getn(set)
|
||||
end
|
||||
end,
|
||||
remove = function(set, value)
|
||||
local index = reverse[value]
|
||||
if index then
|
||||
reverse[value] = nil
|
||||
local top = table.remove(set)
|
||||
if top ~= value then
|
||||
reverse[top] = index
|
||||
set[index] = top
|
||||
end
|
||||
end
|
||||
end
|
||||
}})
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- socket.tcp() wrapper for the coroutine dispatcher
|
||||
-----------------------------------------------------------------------------
|
||||
local function cowrap(dispatcher, tcp, error)
|
||||
if not tcp then return nil, error end
|
||||
-- put it in non-blocking mode right away
|
||||
tcp:settimeout(0)
|
||||
-- metatable for wrap produces new methods on demand for those that we
|
||||
-- don't override explicitly.
|
||||
local metat = { __index = function(table, key)
|
||||
table[key] = function(...)
|
||||
arg[1] = tcp
|
||||
return tcp[key](unpack(arg))
|
||||
end
|
||||
return table[key]
|
||||
end}
|
||||
-- does our user want to do his own non-blocking I/O?
|
||||
local zero = false
|
||||
-- create a wrap object that will behave just like a real socket object
|
||||
local wrap = { }
|
||||
-- we ignore settimeout to preserve our 0 timeout, but record whether
|
||||
-- the user wants to do his own non-blocking I/O
|
||||
function wrap:settimeout(value, mode)
|
||||
if value == 0 then zero = true
|
||||
else zero = false end
|
||||
return 1
|
||||
end
|
||||
-- send in non-blocking mode and yield on timeout
|
||||
function wrap:send(data, first, last)
|
||||
first = (first or 1) - 1
|
||||
local result, error
|
||||
while true do
|
||||
-- return control to dispatcher and tell it we want to send
|
||||
-- if upon return the dispatcher tells us we timed out,
|
||||
-- return an error to whoever called us
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- try sending
|
||||
result, error, first = tcp:send(data, first+1, last)
|
||||
-- if we are done, or there was an unexpected error,
|
||||
-- break away from loop
|
||||
if error ~= "timeout" then return result, error, first end
|
||||
end
|
||||
end
|
||||
-- receive in non-blocking mode and yield on timeout
|
||||
-- or simply return partial read, if user requested timeout = 0
|
||||
function wrap:receive(pattern, partial)
|
||||
local error = "timeout"
|
||||
local value
|
||||
while true do
|
||||
-- return control to dispatcher and tell it we want to receive
|
||||
-- if upon return the dispatcher tells us we timed out,
|
||||
-- return an error to whoever called us
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- try receiving
|
||||
value, error, partial = tcp:receive(pattern, partial)
|
||||
-- if we are done, or there was an unexpected error,
|
||||
-- break away from loop. also, if the user requested
|
||||
-- zero timeout, return all we got
|
||||
if (error ~= "timeout") or zero then
|
||||
return value, error, partial
|
||||
end
|
||||
end
|
||||
end
|
||||
-- connect in non-blocking mode and yield on timeout
|
||||
function wrap:connect(host, port)
|
||||
local result, error = tcp:connect(host, port)
|
||||
if error == "timeout" then
|
||||
-- return control to dispatcher. we will be writable when
|
||||
-- connection succeeds.
|
||||
-- if upon return the dispatcher tells us we have a
|
||||
-- timeout, just abort
|
||||
if coroutine.yield(dispatcher.sending, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
-- when we come back, check if connection was successful
|
||||
result, error = tcp:connect(host, port)
|
||||
if result or error == "already connected" then return 1
|
||||
else return nil, "non-blocking connect failed" end
|
||||
else return result, error end
|
||||
end
|
||||
-- accept in non-blocking mode and yield on timeout
|
||||
function wrap:accept()
|
||||
while 1 do
|
||||
-- return control to dispatcher. we will be readable when a
|
||||
-- connection arrives.
|
||||
-- if upon return the dispatcher tells us we have a
|
||||
-- timeout, just abort
|
||||
if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then
|
||||
return nil, "timeout"
|
||||
end
|
||||
local client, error = tcp:accept()
|
||||
if error ~= "timeout" then
|
||||
return cowrap(dispatcher, client, error)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- remove cortn from context
|
||||
function wrap:close()
|
||||
dispatcher.stamp[tcp] = nil
|
||||
dispatcher.sending.set:remove(tcp)
|
||||
dispatcher.sending.cortn[tcp] = nil
|
||||
dispatcher.receiving.set:remove(tcp)
|
||||
dispatcher.receiving.cortn[tcp] = nil
|
||||
return tcp:close()
|
||||
end
|
||||
return setmetatable(wrap, metat)
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Our coroutine dispatcher
|
||||
-----------------------------------------------------------------------------
|
||||
local cometat = { __index = {} }
|
||||
|
||||
function schedule(cortn, status, operation, tcp)
|
||||
if status then
|
||||
if cortn and operation then
|
||||
operation.set:insert(tcp)
|
||||
operation.cortn[tcp] = cortn
|
||||
operation.stamp[tcp] = socket.gettime()
|
||||
end
|
||||
else error(operation) end
|
||||
end
|
||||
|
||||
function kick(operation, tcp)
|
||||
operation.cortn[tcp] = nil
|
||||
operation.set:remove(tcp)
|
||||
end
|
||||
|
||||
function wakeup(operation, tcp)
|
||||
local cortn = operation.cortn[tcp]
|
||||
-- if cortn is still valid, wake it up
|
||||
if cortn then
|
||||
kick(operation, tcp)
|
||||
return cortn, coroutine.resume(cortn)
|
||||
-- othrewise, just get scheduler not to do anything
|
||||
else
|
||||
return nil, true
|
||||
end
|
||||
end
|
||||
|
||||
function abort(operation, tcp)
|
||||
local cortn = operation.cortn[tcp]
|
||||
if cortn then
|
||||
kick(operation, tcp)
|
||||
coroutine.resume(cortn, "timeout")
|
||||
end
|
||||
end
|
||||
|
||||
-- step through all active cortns
|
||||
function cometat.__index:step()
|
||||
-- check which sockets are interesting and act on them
|
||||
local readable, writable = socket.select(self.receiving.set,
|
||||
self.sending.set, 1)
|
||||
-- for all readable connections, resume their cortns and reschedule
|
||||
-- when they yield back to us
|
||||
for _, tcp in ipairs(readable) do
|
||||
schedule(wakeup(self.receiving, tcp))
|
||||
end
|
||||
-- for all writable connections, do the same
|
||||
for _, tcp in ipairs(writable) do
|
||||
schedule(wakeup(self.sending, tcp))
|
||||
end
|
||||
-- politely ask replacement I/O functions in idle cortns to
|
||||
-- return reporting a timeout
|
||||
local now = socket.gettime()
|
||||
for tcp, stamp in pairs(self.stamp) do
|
||||
if tcp.class == "tcp{client}" and now - stamp > TIMEOUT then
|
||||
abort(self.sending, tcp)
|
||||
abort(self.receiving, tcp)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cometat.__index:start(func)
|
||||
local cortn = coroutine.create(func)
|
||||
schedule(cortn, coroutine.resume(cortn))
|
||||
end
|
||||
|
||||
function handlert.coroutine()
|
||||
local stamp = {}
|
||||
local dispatcher = {
|
||||
stamp = stamp,
|
||||
sending = {
|
||||
name = "sending",
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
stamp = stamp
|
||||
},
|
||||
receiving = {
|
||||
name = "receiving",
|
||||
set = newset(),
|
||||
cortn = {},
|
||||
stamp = stamp
|
||||
},
|
||||
}
|
||||
function dispatcher.tcp()
|
||||
return cowrap(dispatcher, socket.tcp())
|
||||
end
|
||||
return setmetatable(dispatcher, cometat)
|
||||
end
|
||||
|
@ -1,14 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to adjust end of line markers.
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: eol.lua,v 1.8 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local mime = require("mime")
|
||||
local ltn12 = require("ltn12")
|
||||
local marker = '\n'
|
||||
if arg and arg[1] == '-d' then marker = '\r\n' end
|
||||
local filter = mime.normalize(marker)
|
||||
local source = ltn12.source.chain(ltn12.source.file(io.stdin), filter)
|
||||
local sink = ltn12.sink.file(io.stdout)
|
||||
ltn12.pump.all(source, sink)
|
@ -1,65 +0,0 @@
|
||||
-- load our favourite library
|
||||
local dispatch = require("dispatch")
|
||||
local handler = dispatch.newhandler()
|
||||
|
||||
-- make sure the user knows how to invoke us
|
||||
if table.getn(arg) < 1 then
|
||||
print("Usage")
|
||||
print(" lua forward.lua <iport:ohost:oport> ...")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
-- function to move data from one socket to the other
|
||||
local function move(foo, bar)
|
||||
local live
|
||||
while 1 do
|
||||
local data, error, partial = foo:receive(2048)
|
||||
live = data or error == "timeout"
|
||||
data = data or partial
|
||||
local result, error = bar:send(data)
|
||||
if not live or not result then
|
||||
foo:close()
|
||||
bar:close()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- for each tunnel, start a new server
|
||||
for i, v in ipairs(arg) do
|
||||
-- capture forwarding parameters
|
||||
local _, _, iport, ohost, oport = string.find(v, "([^:]+):([^:]+):([^:]+)")
|
||||
assert(iport, "invalid arguments")
|
||||
-- create our server socket
|
||||
local server = assert(handler.tcp())
|
||||
assert(server:setoption("reuseaddr", true))
|
||||
assert(server:bind("*", iport))
|
||||
assert(server:listen(32))
|
||||
-- handler for the server object loops accepting new connections
|
||||
handler:start(function()
|
||||
while 1 do
|
||||
local client = assert(server:accept())
|
||||
assert(client:settimeout(0))
|
||||
-- for each new connection, start a new client handler
|
||||
handler:start(function()
|
||||
-- handler tries to connect to peer
|
||||
local peer = assert(handler.tcp())
|
||||
assert(peer:settimeout(0))
|
||||
assert(peer:connect(ohost, oport))
|
||||
-- if sucessful, starts a new handler to send data from
|
||||
-- client to peer
|
||||
handler:start(function()
|
||||
move(client, peer)
|
||||
end)
|
||||
-- afte starting new handler, enter in loop sending data from
|
||||
-- peer to client
|
||||
move(peer, client)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- simply loop stepping the server
|
||||
while 1 do
|
||||
handler:step()
|
||||
end
|
@ -1,140 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download files from URLs
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: get.lua,v 1.24 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
local http = require("socket.http")
|
||||
local ftp = require("socket.ftp")
|
||||
local url = require("socket.url")
|
||||
local ltn12 = require("ltn12")
|
||||
|
||||
-- formats a number of seconds into human readable form
|
||||
function nicetime(s)
|
||||
local l = "s"
|
||||
if s > 60 then
|
||||
s = s / 60
|
||||
l = "m"
|
||||
if s > 60 then
|
||||
s = s / 60
|
||||
l = "h"
|
||||
if s > 24 then
|
||||
s = s / 24
|
||||
l = "d" -- hmmm
|
||||
end
|
||||
end
|
||||
end
|
||||
if l == "s" then return string.format("%5.0f%s", s, l)
|
||||
else return string.format("%5.2f%s", s, l) end
|
||||
end
|
||||
|
||||
-- formats a number of bytes into human readable form
|
||||
function nicesize(b)
|
||||
local l = "B"
|
||||
if b > 1024 then
|
||||
b = b / 1024
|
||||
l = "KB"
|
||||
if b > 1024 then
|
||||
b = b / 1024
|
||||
l = "MB"
|
||||
if b > 1024 then
|
||||
b = b / 1024
|
||||
l = "GB" -- hmmm
|
||||
end
|
||||
end
|
||||
end
|
||||
return string.format("%7.2f%2s", b, l)
|
||||
end
|
||||
|
||||
-- returns a string with the current state of the download
|
||||
local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining"
|
||||
local elapsed_s = "%s received, %s/s throughput, %s elapsed "
|
||||
function gauge(got, delta, size)
|
||||
local rate = got / delta
|
||||
if size and size >= 1 then
|
||||
return string.format(remaining_s, nicesize(got), nicesize(rate),
|
||||
100*got/size, nicetime((size-got)/rate))
|
||||
else
|
||||
return string.format(elapsed_s, nicesize(got),
|
||||
nicesize(rate), nicetime(delta))
|
||||
end
|
||||
end
|
||||
|
||||
-- creates a new instance of a receive_cb that saves to disk
|
||||
-- kind of copied from luasocket's manual callback examples
|
||||
function stats(size)
|
||||
local start = socket.gettime()
|
||||
local got = 0
|
||||
return function(chunk)
|
||||
-- elapsed time since start
|
||||
local delta = socket.gettime() - start
|
||||
if chunk then
|
||||
-- total bytes received
|
||||
got = got + string.len(chunk)
|
||||
-- not enough time for estimate
|
||||
if delta > 0.1 then
|
||||
io.stderr:write("\r", gauge(got, delta, size))
|
||||
io.stderr:flush()
|
||||
end
|
||||
else
|
||||
-- close up
|
||||
io.stderr:write("\r", gauge(got, delta), "\n")
|
||||
end
|
||||
return chunk
|
||||
end
|
||||
end
|
||||
|
||||
-- determines the size of a http file
|
||||
function gethttpsize(u)
|
||||
local r, c, h = http.request {method = "HEAD", url = u}
|
||||
if c == 200 then
|
||||
return tonumber(h["content-length"])
|
||||
end
|
||||
end
|
||||
|
||||
-- downloads a file using the http protocol
|
||||
function getbyhttp(u, file)
|
||||
local save = ltn12.sink.file(file or io.stdout)
|
||||
-- only print feedback if output is not stdout
|
||||
if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end
|
||||
local r, c, h, s = http.request {url = u, sink = save }
|
||||
if c ~= 200 then io.stderr:write(s or c, "\n") end
|
||||
end
|
||||
|
||||
-- downloads a file using the ftp protocol
|
||||
function getbyftp(u, file)
|
||||
local save = ltn12.sink.file(file or io.stdout)
|
||||
-- only print feedback if output is not stdout
|
||||
-- and we don't know how big the file is
|
||||
if file then save = ltn12.sink.chain(stats(), save) end
|
||||
local gett = url.parse(u)
|
||||
gett.sink = save
|
||||
gett.type = "i"
|
||||
local ret, err = ftp.get(gett)
|
||||
if err then print(err) end
|
||||
end
|
||||
|
||||
-- determines the scheme
|
||||
function getscheme(u)
|
||||
-- this is an heuristic to solve a common invalid url poblem
|
||||
if not string.find(u, "//") then u = "//" .. u end
|
||||
local parsed = url.parse(u, {scheme = "http"})
|
||||
return parsed.scheme
|
||||
end
|
||||
|
||||
-- gets a file either by http or ftp, saving as <name>
|
||||
function get(u, name)
|
||||
local fout = name and io.open(name, "wb")
|
||||
local scheme = getscheme(u)
|
||||
if scheme == "ftp" then getbyftp(u, fout)
|
||||
elseif scheme == "http" then getbyhttp(u, fout)
|
||||
else print("unknown scheme" .. scheme) end
|
||||
end
|
||||
|
||||
-- main program
|
||||
arg = arg or {}
|
||||
if table.getn(arg) < 1 then
|
||||
io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n")
|
||||
os.exit(1)
|
||||
else get(arg[1], arg[2]) end
|
@ -1,324 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- LPD support for the Lua language
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: David Burgess
|
||||
-- Modified by Diego Nehab, but David is in charge
|
||||
-- RCS ID: $Id: lp.lua,v 1.14 2005/11/21 07:04:44 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
--[[
|
||||
if you have any questions: RFC 1179
|
||||
]]
|
||||
-- make sure LuaSocket is loaded
|
||||
local io = require("io")
|
||||
local base = _G
|
||||
local os = require("os")
|
||||
local math = require("math")
|
||||
local string = require("string")
|
||||
local socket = require("socket")
|
||||
local ltn12 = require("ltn12")
|
||||
module("socket.lp")
|
||||
|
||||
-- default port
|
||||
PORT = 515
|
||||
SERVER = os.getenv("SERVER_NAME") or os.getenv("COMPUTERNAME") or "localhost"
|
||||
PRINTER = os.getenv("PRINTER") or "printer"
|
||||
|
||||
local function connect(localhost, option)
|
||||
local host = option.host or SERVER
|
||||
local port = option.port or PORT
|
||||
local skt
|
||||
local try = socket.newtry(function() if skt then skt:close() end end)
|
||||
if option.localbind then
|
||||
-- bind to a local port (if we can)
|
||||
local localport = 721
|
||||
local done, err
|
||||
repeat
|
||||
skt = socket.try(socket.tcp())
|
||||
try(skt:settimeout(30))
|
||||
done, err = skt:bind(localhost, localport)
|
||||
if not done then
|
||||
localport = localport + 1
|
||||
skt:close()
|
||||
skt = nil
|
||||
else break end
|
||||
until localport > 731
|
||||
socket.try(skt, err)
|
||||
else skt = socket.try(socket.tcp()) end
|
||||
try(skt:connect(host, port))
|
||||
return { skt = skt, try = try }
|
||||
end
|
||||
|
||||
--[[
|
||||
RFC 1179
|
||||
5.3 03 - Send queue state (short)
|
||||
|
||||
+----+-------+----+------+----+
|
||||
| 03 | Queue | SP | List | LF |
|
||||
+----+-------+----+------+----+
|
||||
Command code - 3
|
||||
Operand 1 - Printer queue name
|
||||
Other operands - User names or job numbers
|
||||
|
||||
If the user names or job numbers or both are supplied then only those
|
||||
jobs for those users or with those numbers will be sent.
|
||||
|
||||
The response is an ASCII stream which describes the printer queue.
|
||||
The stream continues until the connection closes. Ends of lines are
|
||||
indicated with ASCII LF control characters. The lines may also
|
||||
contain ASCII HT control characters.
|
||||
|
||||
5.4 04 - Send queue state (long)
|
||||
|
||||
+----+-------+----+------+----+
|
||||
| 04 | Queue | SP | List | LF |
|
||||
+----+-------+----+------+----+
|
||||
Command code - 4
|
||||
Operand 1 - Printer queue name
|
||||
Other operands - User names or job numbers
|
||||
|
||||
If the user names or job numbers or both are supplied then only those
|
||||
jobs for those users or with those numbers will be sent.
|
||||
|
||||
The response is an ASCII stream which describes the printer queue.
|
||||
The stream continues until the connection closes. Ends of lines are
|
||||
indicated with ASCII LF control characters. The lines may also
|
||||
contain ASCII HT control characters.
|
||||
]]
|
||||
|
||||
-- gets server acknowledement
|
||||
local function recv_ack(con)
|
||||
local ack = con.skt:receive(1)
|
||||
con.try(string.char(0) == ack, "failed to receive server acknowledgement")
|
||||
end
|
||||
|
||||
-- sends client acknowledement
|
||||
local function send_ack(con)
|
||||
local sent = con.skt:send(string.char(0))
|
||||
con.try(sent == 1, "failed to send acknowledgement")
|
||||
end
|
||||
|
||||
-- sends queue request
|
||||
-- 5.2 02 - Receive a printer job
|
||||
--
|
||||
-- +----+-------+----+
|
||||
-- | 02 | Queue | LF |
|
||||
-- +----+-------+----+
|
||||
-- Command code - 2
|
||||
-- Operand - Printer queue name
|
||||
--
|
||||
-- Receiving a job is controlled by a second level of commands. The
|
||||
-- daemon is given commands by sending them over the same connection.
|
||||
-- The commands are described in the next section (6).
|
||||
--
|
||||
-- After this command is sent, the client must read an acknowledgement
|
||||
-- octet from the daemon. A positive acknowledgement is an octet of
|
||||
-- zero bits. A negative acknowledgement is an octet of any other
|
||||
-- pattern.
|
||||
local function send_queue(con, queue)
|
||||
queue = queue or PRINTER
|
||||
local str = string.format("\2%s\10", queue)
|
||||
local sent = con.skt:send(str)
|
||||
con.try(sent == string.len(str), "failed to send print request")
|
||||
recv_ack(con)
|
||||
end
|
||||
|
||||
-- sends control file
|
||||
-- 6.2 02 - Receive control file
|
||||
--
|
||||
-- +----+-------+----+------+----+
|
||||
-- | 02 | Count | SP | Name | LF |
|
||||
-- +----+-------+----+------+----+
|
||||
-- Command code - 2
|
||||
-- Operand 1 - Number of bytes in control file
|
||||
-- Operand 2 - Name of control file
|
||||
--
|
||||
-- The control file must be an ASCII stream with the ends of lines
|
||||
-- indicated by ASCII LF. The total number of bytes in the stream is
|
||||
-- sent as the first operand. The name of the control file is sent as
|
||||
-- the second. It should start with ASCII "cfA", followed by a three
|
||||
-- digit job number, followed by the host name which has constructed the
|
||||
-- control file. Acknowledgement processing must occur as usual after
|
||||
-- the command is sent.
|
||||
--
|
||||
-- The next "Operand 1" octets over the same TCP connection are the
|
||||
-- intended contents of the control file. Once all of the contents have
|
||||
-- been delivered, an octet of zero bits is sent as an indication that
|
||||
-- the file being sent is complete. A second level of acknowledgement
|
||||
-- processing must occur at this point.
|
||||
|
||||
-- sends data file
|
||||
-- 6.3 03 - Receive data file
|
||||
--
|
||||
-- +----+-------+----+------+----+
|
||||
-- | 03 | Count | SP | Name | LF |
|
||||
-- +----+-------+----+------+----+
|
||||
-- Command code - 3
|
||||
-- Operand 1 - Number of bytes in data file
|
||||
-- Operand 2 - Name of data file
|
||||
--
|
||||
-- The data file may contain any 8 bit values at all. The total number
|
||||
-- of bytes in the stream may be sent as the first operand, otherwise
|
||||
-- the field should be cleared to 0. The name of the data file should
|
||||
-- start with ASCII "dfA". This should be followed by a three digit job
|
||||
-- number. The job number should be followed by the host name which has
|
||||
-- constructed the data file. Interpretation of the contents of the
|
||||
-- data file is determined by the contents of the corresponding control
|
||||
-- file. If a data file length has been specified, the next "Operand 1"
|
||||
-- octets over the same TCP connection are the intended contents of the
|
||||
-- data file. In this case, once all of the contents have been
|
||||
-- delivered, an octet of zero bits is sent as an indication that the
|
||||
-- file being sent is complete. A second level of acknowledgement
|
||||
-- processing must occur at this point.
|
||||
|
||||
|
||||
local function send_hdr(con, control)
|
||||
local sent = con.skt:send(control)
|
||||
con.try(sent and sent >= 1 , "failed to send header file")
|
||||
recv_ack(con)
|
||||
end
|
||||
|
||||
local function send_control(con, control)
|
||||
local sent = con.skt:send(control)
|
||||
con.try(sent and sent >= 1, "failed to send control file")
|
||||
send_ack(con)
|
||||
end
|
||||
|
||||
local function send_data(con,fh,size)
|
||||
local buf
|
||||
while size > 0 do
|
||||
buf,message = fh:read(8192)
|
||||
if buf then
|
||||
st = con.try(con.skt:send(buf))
|
||||
size = size - st
|
||||
else
|
||||
con.try(size == 0, "file size mismatch")
|
||||
end
|
||||
end
|
||||
recv_ack(con) -- note the double acknowledgement
|
||||
send_ack(con)
|
||||
recv_ack(con)
|
||||
return size
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
local control_dflt = {
|
||||
"H"..string.sub(socket.hostname,1,31).."\10", -- host
|
||||
"C"..string.sub(socket.hostname,1,31).."\10", -- class
|
||||
"J"..string.sub(filename,1,99).."\10", -- jobname
|
||||
"L"..string.sub(user,1,31).."\10", -- print banner page
|
||||
"I"..tonumber(indent).."\10", -- indent column count ('f' only)
|
||||
"M"..string.sub(mail,1,128).."\10", -- mail when printed user@host
|
||||
"N"..string.sub(filename,1,131).."\10", -- name of source file
|
||||
"P"..string.sub(user,1,31).."\10", -- user name
|
||||
"T"..string.sub(title,1,79).."\10", -- title for banner ('p' only)
|
||||
"W"..tonumber(width or 132).."\10", -- width of print f,l,p only
|
||||
|
||||
"f"..file.."\10", -- formatted print (remove control chars)
|
||||
"l"..file.."\10", -- print
|
||||
"o"..file.."\10", -- postscript
|
||||
"p"..file.."\10", -- pr format - requires T, L
|
||||
"r"..file.."\10", -- fortran format
|
||||
"U"..file.."\10", -- Unlink (data file only)
|
||||
}
|
||||
]]
|
||||
|
||||
-- generate a varying job number
|
||||
local seq = 0
|
||||
local function newjob(connection)
|
||||
seq = seq + 1
|
||||
return math.floor(socket.gettime() * 1000 + seq)%1000
|
||||
end
|
||||
|
||||
|
||||
local format_codes = {
|
||||
binary = 'l',
|
||||
text = 'f',
|
||||
ps = 'o',
|
||||
pr = 'p',
|
||||
fortran = 'r',
|
||||
l = 'l',
|
||||
r = 'r',
|
||||
o = 'o',
|
||||
p = 'p',
|
||||
f = 'f'
|
||||
}
|
||||
|
||||
-- lp.send{option}
|
||||
-- requires option.file
|
||||
|
||||
send = socket.protect(function(option)
|
||||
socket.try(option and base.type(option) == "table", "invalid options")
|
||||
local file = option.file
|
||||
socket.try(file, "invalid file name")
|
||||
local fh = socket.try(io.open(file,"rb"))
|
||||
local datafile_size = fh:seek("end") -- get total size
|
||||
fh:seek("set") -- go back to start of file
|
||||
local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME")
|
||||
or "localhost"
|
||||
local con = connect(localhost, option)
|
||||
-- format the control file
|
||||
local jobno = newjob()
|
||||
local localip = socket.dns.toip(localhost)
|
||||
localhost = string.sub(localhost,1,31)
|
||||
local user = string.sub(option.user or os.getenv("LPRUSER") or
|
||||
os.getenv("USERNAME") or os.getenv("USER") or "anonymous", 1,31)
|
||||
local lpfile = string.format("dfA%3.3d%-s", jobno, localhost);
|
||||
local fmt = format_codes[option.format] or 'l'
|
||||
local class = string.sub(option.class or localip or localhost,1,31)
|
||||
local _,_,ctlfn = string.find(file,".*[%/%\\](.*)")
|
||||
ctlfn = string.sub(ctlfn or file,1,131)
|
||||
local cfile =
|
||||
string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n",
|
||||
localhost,
|
||||
class,
|
||||
option.job or "LuaSocket",
|
||||
user,
|
||||
fmt, lpfile,
|
||||
lpfile,
|
||||
ctlfn); -- mandatory part of ctl file
|
||||
if (option.banner) then cfile = cfile .. 'L'..user..'\10' end
|
||||
if (option.indent) then cfile = cfile .. 'I'..base.tonumber(option.indent)..'\10' end
|
||||
if (option.mail) then cfile = cfile .. 'M'..string.sub((option.mail),1,128)..'\10' end
|
||||
if (fmt == 'p' and option.title) then cfile = cfile .. 'T'..string.sub((option.title),1,79)..'\10' end
|
||||
if ((fmt == 'p' or fmt == 'l' or fmt == 'f') and option.width) then
|
||||
cfile = cfile .. 'W'..base.tonumber(option,width)..'\10'
|
||||
end
|
||||
|
||||
con.skt:settimeout(option.timeout or 65)
|
||||
-- send the queue header
|
||||
send_queue(con, option.queue)
|
||||
-- send the control file header
|
||||
local cfilecmd = string.format("\2%d cfA%3.3d%-s\n",string.len(cfile), jobno, localhost);
|
||||
send_hdr(con,cfilecmd)
|
||||
|
||||
-- send the control file
|
||||
send_control(con,cfile)
|
||||
|
||||
-- send the data file header
|
||||
local dfilecmd = string.format("\3%d dfA%3.3d%-s\n",datafile_size, jobno, localhost);
|
||||
send_hdr(con,dfilecmd)
|
||||
|
||||
-- send the data file
|
||||
send_data(con,fh,datafile_size)
|
||||
fh:close()
|
||||
con.skt:close();
|
||||
return jobno, datafile_size
|
||||
end)
|
||||
|
||||
--
|
||||
-- lp.query({host=,queue=printer|'*', format='l'|'s', list=})
|
||||
--
|
||||
query = socket.protect(function(p)
|
||||
p = p or {}
|
||||
local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME")
|
||||
or "localhost"
|
||||
local con = connect(localhost,p)
|
||||
local fmt
|
||||
if string.sub(p.format or 's',1,1) == 's' then fmt = 3 else fmt = 4 end
|
||||
con.try(con.skt:send(string.format("%c%s %s\n", fmt, p.queue or "*",
|
||||
p.list or "")))
|
||||
local data = con.try(con.skt:receive("*a"))
|
||||
con.skt:close()
|
||||
return data
|
||||
end)
|
@ -1,24 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to convert to and from Quoted-Printable
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: qp.lua,v 1.5 2004/06/17 21:46:22 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
local ltn12 = require("ltn12")
|
||||
local mime = require("mime")
|
||||
local convert
|
||||
arg = arg or {}
|
||||
local mode = arg and arg[1] or "-et"
|
||||
if mode == "-et" then
|
||||
local normalize = mime.normalize()
|
||||
local qp = mime.encode("quoted-printable")
|
||||
local wrap = mime.wrap("quoted-printable")
|
||||
convert = ltn12.filter.chain(normalize, qp, wrap)
|
||||
elseif mode == "-eb" then
|
||||
local qp = mime.encode("quoted-printable", "binary")
|
||||
local wrap = mime.wrap("quoted-printable")
|
||||
convert = ltn12.filter.chain(qp, wrap)
|
||||
else convert = mime.decode("quoted-printable") end
|
||||
local source = ltn12.source.chain(ltn12.source.file(io.stdin), convert)
|
||||
local sink = ltn12.sink.file(io.stdout)
|
||||
ltn12.pump.all(source, sink)
|
@ -1,155 +0,0 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TFTP support for the Lua language
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id: tftp.lua,v 1.16 2005/11/22 08:33:29 diego Exp $
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Load required files
|
||||
-----------------------------------------------------------------------------
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
local math = require("math")
|
||||
local string = require("string")
|
||||
local socket = require("socket")
|
||||
local ltn12 = require("ltn12")
|
||||
local url = require("socket.url")
|
||||
module("socket.tftp")
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Program constants
|
||||
-----------------------------------------------------------------------------
|
||||
local char = string.char
|
||||
local byte = string.byte
|
||||
|
||||
PORT = 69
|
||||
local OP_RRQ = 1
|
||||
local OP_WRQ = 2
|
||||
local OP_DATA = 3
|
||||
local OP_ACK = 4
|
||||
local OP_ERROR = 5
|
||||
local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"}
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Packet creation functions
|
||||
-----------------------------------------------------------------------------
|
||||
local function RRQ(source, mode)
|
||||
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
||||
end
|
||||
|
||||
local function WRQ(source, mode)
|
||||
return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0)
|
||||
end
|
||||
|
||||
local function ACK(block)
|
||||
local low, high
|
||||
low = math.mod(block, 256)
|
||||
high = (block - low)/256
|
||||
return char(0, OP_ACK, high, low)
|
||||
end
|
||||
|
||||
local function get_OP(dgram)
|
||||
local op = byte(dgram, 1)*256 + byte(dgram, 2)
|
||||
return op
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Packet analysis functions
|
||||
-----------------------------------------------------------------------------
|
||||
local function split_DATA(dgram)
|
||||
local block = byte(dgram, 3)*256 + byte(dgram, 4)
|
||||
local data = string.sub(dgram, 5)
|
||||
return block, data
|
||||
end
|
||||
|
||||
local function get_ERROR(dgram)
|
||||
local code = byte(dgram, 3)*256 + byte(dgram, 4)
|
||||
local msg
|
||||
_,_, msg = string.find(dgram, "(.*)\000", 5)
|
||||
return string.format("error code %d: %s", code, msg)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- The real work
|
||||
-----------------------------------------------------------------------------
|
||||
local function tget(gett)
|
||||
local retries, dgram, sent, datahost, dataport, code
|
||||
local last = 0
|
||||
socket.try(gett.host, "missing host")
|
||||
local con = socket.try(socket.udp())
|
||||
local try = socket.newtry(function() con:close() end)
|
||||
-- convert from name to ip if needed
|
||||
gett.host = try(socket.dns.toip(gett.host))
|
||||
con:settimeout(1)
|
||||
-- first packet gives data host/port to be used for data transfers
|
||||
local path = string.gsub(gett.path or "", "^/", "")
|
||||
path = url.unescape(path)
|
||||
retries = 0
|
||||
repeat
|
||||
sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port))
|
||||
dgram, datahost, dataport = con:receivefrom()
|
||||
retries = retries + 1
|
||||
until dgram or datahost ~= "timeout" or retries > 5
|
||||
try(dgram, datahost)
|
||||
-- associate socket with data host/port
|
||||
try(con:setpeername(datahost, dataport))
|
||||
-- default sink
|
||||
local sink = gett.sink or ltn12.sink.null()
|
||||
-- process all data packets
|
||||
while 1 do
|
||||
-- decode packet
|
||||
code = get_OP(dgram)
|
||||
try(code ~= OP_ERROR, get_ERROR(dgram))
|
||||
try(code == OP_DATA, "unhandled opcode " .. code)
|
||||
-- get data packet parts
|
||||
local block, data = split_DATA(dgram)
|
||||
-- if not repeated, write
|
||||
if block == last+1 then
|
||||
try(sink(data))
|
||||
last = block
|
||||
end
|
||||
-- last packet brings less than 512 bytes of data
|
||||
if string.len(data) < 512 then
|
||||
try(con:send(ACK(block)))
|
||||
try(con:close())
|
||||
try(sink(nil))
|
||||
return 1
|
||||
end
|
||||
-- get the next packet
|
||||
retries = 0
|
||||
repeat
|
||||
sent = try(con:send(ACK(last)))
|
||||
dgram, err = con:receive()
|
||||
retries = retries + 1
|
||||
until dgram or err ~= "timeout" or retries > 5
|
||||
try(dgram, err)
|
||||
end
|
||||
end
|
||||
|
||||
local default = {
|
||||
port = PORT,
|
||||
path ="/",
|
||||
scheme = "tftp"
|
||||
}
|
||||
|
||||
local function parse(u)
|
||||
local t = socket.try(url.parse(u, default))
|
||||
socket.try(t.scheme == "tftp", "invalid scheme '" .. t.scheme .. "'")
|
||||
socket.try(t.host, "invalid host")
|
||||
return t
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
local t = {}
|
||||
gett.sink = ltn12.sink.table(t)
|
||||
tget(gett)
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
get = socket.protect(function(gett)
|
||||
if base.type(gett) == "string" then return sget(gett)
|
||||
else return tget(gett) end
|
||||
end)
|
||||
|
@ -1,12 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# ONLY FOR MAINTAINER USE!!
|
||||
|
||||
cd "`dirname "$0"`";
|
||||
dir="`pwd`";
|
||||
cd ..;
|
||||
|
||||
"$dir/zipmod.sh";
|
||||
|
||||
echo cp -f dists/* ~/Dropbox/Public/minetest/mods/;
|
||||
cp -f dists/* ~/Dropbox/Public/minetest/mods/;
|
@ -1,7 +0,0 @@
|
||||
#! /bin/sh
|
||||
cd Build \
|
||||
&& cmake .. \
|
||||
&& make \
|
||||
&& make pack_mod \
|
||||
&& rm -fr ~/.minetest/games/testing/mods/irc \
|
||||
&& cp -fr irc ~/.minetest/games/testing/mods/
|
@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env lua
|
||||
|
||||
local irc = require 'irc'
|
||||
irc.DEBUG = true
|
||||
|
||||
local nick = "doylua"
|
||||
|
||||
local envs = {}
|
||||
|
||||
local function create_env()
|
||||
return {
|
||||
_VERSION = _VERSION,
|
||||
assert = assert,
|
||||
collectgarbage = collectgarbage,
|
||||
error = error,
|
||||
getfenv = getfenv,
|
||||
getmetatable = getmetatable,
|
||||
ipairs = ipairs,
|
||||
loadstring = loadstring,
|
||||
next = next,
|
||||
pairs = pairs,
|
||||
pcall = pcall,
|
||||
rawequal = rawequal,
|
||||
rawget = rawget,
|
||||
rawset = rawset,
|
||||
select = select,
|
||||
setfenv = setfenv,
|
||||
setmetatable = setmetatable,
|
||||
tonumber = tonumber,
|
||||
tostring = tostring,
|
||||
type = type,
|
||||
unpack = unpack,
|
||||
xpcall = xpcall,
|
||||
coroutine = coroutine,
|
||||
math = math,
|
||||
string = string,
|
||||
table = table,
|
||||
}
|
||||
end
|
||||
|
||||
local commands = {
|
||||
eval = function(target, from, code)
|
||||
code = code:gsub("^=", "return ")
|
||||
local fn, err = loadstring(code)
|
||||
if not fn then
|
||||
irc.say(target, from .. ": Error loading code: " .. code .. err:match(".*(:.-)$"))
|
||||
return
|
||||
else
|
||||
setfenv(fn, envs[from])
|
||||
local result = {pcall(fn)}
|
||||
local success = table.remove(result, 1)
|
||||
if not success then
|
||||
irc.say(target, from .. ": Error running code: " .. code .. result[1]:match(".*(:.-)$"))
|
||||
else
|
||||
if result[1] == nil then
|
||||
irc.say(target, from .. ": nil")
|
||||
else
|
||||
irc.say(target, from .. ": " .. table.concat(result, ", "))
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
clear = function(target, from)
|
||||
irc.say(target, from .. ": Clearing your environment")
|
||||
envs[from] = create_env()
|
||||
end,
|
||||
help = function(target, from, arg)
|
||||
if arg == "" or not arg then
|
||||
irc.say(target, from .. ": Commands: !clear, !eval, !help")
|
||||
elseif arg == "eval" then
|
||||
irc.say(target, from .. ": Evaluates a Lua statement in your own persistent environment")
|
||||
elseif arg == "clear" then
|
||||
irc.say(target, from .. ": Clears your personal environment")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
irc.register_callback("connect", function()
|
||||
irc.join("#doytest")
|
||||
end)
|
||||
|
||||
irc.register_callback("channel_msg", function(channel, from, message)
|
||||
message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
|
||||
local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
|
||||
if is_cmd and commands[cmd] then
|
||||
envs[from] = envs[from] or create_env()
|
||||
commands[cmd](channel.name, from, arg)
|
||||
end
|
||||
end)
|
||||
|
||||
irc.register_callback("private_msg", function(from, message)
|
||||
message = message:gsub("^" .. nick .. "[:,>] ", "!eval ")
|
||||
local is_cmd, cmd, arg = message:match("^(!)([%w_]+) ?(.-)$")
|
||||
envs[from] = envs[from] or create_env()
|
||||
if is_cmd and commands[cmd] then
|
||||
commands[cmd](from, from, arg)
|
||||
else
|
||||
commands["eval"](from, from, message)
|
||||
end
|
||||
end)
|
||||
|
||||
irc.register_callback("nick_change", function(from, old_nick)
|
||||
if envs[old_nick] and not envs[from] then
|
||||
envs[from] = envs[old_nick]
|
||||
envs[old_nick] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
irc.connect{network = "irc.freenode.net", nick = nick, pass = "doylua"}
|
@ -1,228 +0,0 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
local irc = require "irc"
|
||||
local dcc = require "irc.dcc"
|
||||
|
||||
irc.DEBUG = true
|
||||
|
||||
local ip_prog = io.popen("get_ip")
|
||||
local ip = ip_prog:read()
|
||||
ip_prog:close()
|
||||
irc.set_ip(ip)
|
||||
|
||||
local function print_state()
|
||||
for chan in irc.channels() do
|
||||
print(chan..": Channel ops: "..table.concat(chan:ops(), " "))
|
||||
print(chan..": Channel voices: "..table.concat(chan:voices(), " "))
|
||||
print(chan..": Channel normal users: "..table.concat(chan:users(), " "))
|
||||
print(chan..": All channel members: "..table.concat(chan:members(), " "))
|
||||
end
|
||||
end
|
||||
|
||||
local function on_connect()
|
||||
print("Joining channel #doytest...")
|
||||
irc.join("#doytest")
|
||||
print("Joining channel #doytest2...")
|
||||
irc.join("#doytest2")
|
||||
end
|
||||
irc.register_callback("connect", on_connect)
|
||||
|
||||
local function on_me_join(chan)
|
||||
print("Join to " .. chan .. " complete.")
|
||||
print(chan .. ": Channel type: " .. chan.chanmode)
|
||||
if chan.topic.text and chan.topic.text ~= "" then
|
||||
print(chan .. ": Channel topic: " .. chan.topic.text)
|
||||
print(" Set by " .. chan.topic.user ..
|
||||
" at " .. os.date("%c", chan.topic.time))
|
||||
end
|
||||
irc.act(chan.name, "is here")
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("me_join", on_me_join)
|
||||
|
||||
local function on_join(chan, user)
|
||||
print("I saw a join to " .. chan)
|
||||
if tostring(user) ~= "doylua" then
|
||||
irc.say(tostring(chan), "Hi, " .. user)
|
||||
end
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("join", on_join)
|
||||
|
||||
local function on_part(chan, user, part_msg)
|
||||
print("I saw a part from " .. chan .. " saying " .. part_msg)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("part", on_part)
|
||||
|
||||
local function on_nick_change(new_nick, old_nick)
|
||||
print("I saw a nick change: " .. old_nick .. " -> " .. new_nick)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("nick_change", on_nick_change)
|
||||
|
||||
local function on_kick(chan, user)
|
||||
print("I saw a kick in " .. chan)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("kick", on_kick)
|
||||
|
||||
local function on_quit(chan, user)
|
||||
print("I saw a quit from " .. chan)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("quit", on_quit)
|
||||
|
||||
local function whois_cb(cb_data)
|
||||
print("WHOIS data for " .. cb_data.nick)
|
||||
if cb_data.user then print("Username: " .. cb_data.user) end
|
||||
if cb_data.host then print("Host: " .. cb_data.host) end
|
||||
if cb_data.realname then print("Realname: " .. cb_data.realname) end
|
||||
if cb_data.server then print("Server: " .. cb_data.server) end
|
||||
if cb_data.serverinfo then print("Serverinfo: " .. cb_data.serverinfo) end
|
||||
if cb_data.away_msg then print("Awaymsg: " .. cb_data.away_msg) end
|
||||
if cb_data.is_oper then print(nick .. "is an IRCop") end
|
||||
if cb_data.idle_time then print("Idletime: " .. cb_data.idle_time) end
|
||||
if cb_data.channels then
|
||||
print("Channel list for " .. cb_data.nick .. ":")
|
||||
for _, channel in ipairs(cb_data.channels) do print(channel) end
|
||||
end
|
||||
end
|
||||
|
||||
local function serverversion_cb(cb_data)
|
||||
print("VERSION data for " .. cb_data.server)
|
||||
print("Version: " .. cb_data.version)
|
||||
print("Comments: " .. cb_data.comments)
|
||||
end
|
||||
|
||||
local function ping_cb(cb_data)
|
||||
print("CTCP PING for " .. cb_data.nick)
|
||||
print("Roundtrip time: " .. cb_data.time .. "s")
|
||||
end
|
||||
|
||||
local function time_cb(cb_data)
|
||||
print("CTCP TIME for " .. cb_data.nick)
|
||||
print("Localtime: " .. cb_data.time)
|
||||
end
|
||||
|
||||
local function version_cb(cb_data)
|
||||
print("CTCP VERSION for " .. cb_data.nick)
|
||||
print("Version: " .. cb_data.version)
|
||||
end
|
||||
|
||||
local function stime_cb(cb_data)
|
||||
print("TIME for " .. cb_data.server)
|
||||
print("Server time: " .. cb_data.time)
|
||||
end
|
||||
|
||||
local function on_channel_msg(chan, from, msg)
|
||||
if from == "doy" then
|
||||
if msg == "leave" then
|
||||
irc.part(chan.name)
|
||||
return
|
||||
elseif msg:sub(1, 3) == "op " then
|
||||
chan:op(msg:sub(4))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "deop " then
|
||||
chan:deop(msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 6) == "voice " then
|
||||
chan:voice(msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "devoice " then
|
||||
chan:devoice(msg:sub(9))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "kick " then
|
||||
chan:kick(msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "send " then
|
||||
dcc.send(from, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 6) == "whois " then
|
||||
irc.whois(whois_cb, msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "sversion" then
|
||||
irc.server_version(serverversion_cb)
|
||||
return
|
||||
elseif msg:sub(1, 5) == "ping " then
|
||||
irc.ctcp_ping(ping_cb, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "time " then
|
||||
irc.ctcp_time(time_cb, msg:sub(6))
|
||||
return
|
||||
elseif msg:sub(1, 8) == "version " then
|
||||
irc.ctcp_version(version_cb, msg:sub(9))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "stime" then
|
||||
irc.server_time(stime_cb)
|
||||
return
|
||||
elseif msg:sub(1, 6) == "trace " then
|
||||
irc.trace(trace_cb, msg:sub(7))
|
||||
return
|
||||
elseif msg:sub(1, 5) == "trace" then
|
||||
irc.trace(trace_cb)
|
||||
return
|
||||
end
|
||||
end
|
||||
if from ~= "doylua" then
|
||||
irc.say(chan.name, from .. ": " .. msg)
|
||||
end
|
||||
end
|
||||
irc.register_callback("channel_msg", on_channel_msg)
|
||||
|
||||
local function on_private_msg(from, msg)
|
||||
if from == "doy" then
|
||||
if msg == "leave" then
|
||||
irc.quit("gone")
|
||||
return
|
||||
elseif msg:sub(1, 5) == "send " then
|
||||
dcc.send(from, msg:sub(6))
|
||||
return
|
||||
end
|
||||
end
|
||||
if from ~= "doylua" then
|
||||
irc.say(from, msg)
|
||||
end
|
||||
end
|
||||
irc.register_callback("private_msg", on_private_msg)
|
||||
|
||||
local function on_channel_act(chan, from, msg)
|
||||
irc.act(chan.name, "jumps on " .. from)
|
||||
end
|
||||
irc.register_callback("channel_act", on_channel_act)
|
||||
|
||||
local function on_private_act(from, msg)
|
||||
irc.act(from, "jumps on you")
|
||||
end
|
||||
irc.register_callback("private_act", on_private_act)
|
||||
|
||||
local function on_op(chan, from, nick)
|
||||
print(nick .. " was opped in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("op", on_op)
|
||||
|
||||
local function on_deop(chan, from, nick)
|
||||
print(nick .. " was deopped in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("deop", on_deop)
|
||||
|
||||
local function on_voice(chan, from, nick)
|
||||
print(nick .. " was voiced in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("voice", on_voice)
|
||||
|
||||
local function on_devoice(chan, from, nick)
|
||||
print(nick .. " was devoiced in " .. chan .. " by " .. from)
|
||||
print_state()
|
||||
end
|
||||
irc.register_callback("devoice", on_devoice)
|
||||
|
||||
local function on_dcc_send()
|
||||
return true
|
||||
end
|
||||
irc.register_callback("dcc_send", on_dcc_send)
|
||||
|
||||
irc.connect{network = "irc.freenode.net", nick = "doylua"}
|
@ -1,12 +0,0 @@
|
||||
This provides the automated test scripts used to make sure the library
|
||||
is working properly.
|
||||
|
||||
The files provided are:
|
||||
|
||||
testsrvr.lua -- test server
|
||||
testclnt.lua -- test client
|
||||
|
||||
To run these tests, just run lua on the server and then on the client.
|
||||
|
||||
Good luck,
|
||||
Diego.
|
@ -1,655 +0,0 @@
|
||||
local socket = require"socket"
|
||||
|
||||
host = host or "localhost"
|
||||
port = port or "8383"
|
||||
|
||||
function pass(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write(s, "\n")
|
||||
end
|
||||
|
||||
function fail(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write("ERROR: ", s, "!\n")
|
||||
socket.sleep(3)
|
||||
os.exit()
|
||||
end
|
||||
|
||||
function warn(...)
|
||||
local s = string.format(unpack(arg))
|
||||
io.stderr:write("WARNING: ", s, "\n")
|
||||
end
|
||||
|
||||
function remote(...)
|
||||
local s = string.format(unpack(arg))
|
||||
s = string.gsub(s, "\n", ";")
|
||||
s = string.gsub(s, "%s+", " ")
|
||||
s = string.gsub(s, "^%s*", "")
|
||||
control:send(s .. "\n")
|
||||
control:receive()
|
||||
end
|
||||
|
||||
function test(test)
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"testing: ", test, "\n",
|
||||
"----------------------------------------------\n")
|
||||
end
|
||||
|
||||
function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
|
||||
if tm < sl then
|
||||
if opp == "send" then
|
||||
if not err then warn("must be buffered")
|
||||
elseif err == "timeout" then pass("proper timeout")
|
||||
else fail("unexpected error '%s'", err) end
|
||||
else
|
||||
if err ~= "timeout" then fail("should have timed out")
|
||||
else pass("proper timeout") end
|
||||
end
|
||||
else
|
||||
if mode == "total" then
|
||||
if elapsed > tm then
|
||||
if err ~= "timeout" then fail("should have timed out")
|
||||
else pass("proper timeout") end
|
||||
elseif elapsed < tm then
|
||||
if err then fail(err)
|
||||
else pass("ok") end
|
||||
else
|
||||
if alldone then
|
||||
if err then fail("unexpected error '%s'", err)
|
||||
else pass("ok") end
|
||||
else
|
||||
if err ~= "timeout" then fail(err)
|
||||
else pass("proper timeoutk") end
|
||||
end
|
||||
end
|
||||
else
|
||||
if err then fail(err)
|
||||
else pass("ok") end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not socket._DEBUG then
|
||||
fail("Please define LUASOCKET_DEBUG and recompile LuaSocket")
|
||||
end
|
||||
|
||||
io.stderr:write("----------------------------------------------\n",
|
||||
"LuaSocket Test Procedures\n",
|
||||
"----------------------------------------------\n")
|
||||
|
||||
start = socket.gettime()
|
||||
|
||||
function reconnect()
|
||||
io.stderr:write("attempting data connection... ")
|
||||
if data then data:close() end
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
data = server:accept()
|
||||
data:setoption("tcp-nodelay", true)
|
||||
]]
|
||||
data, err = socket.connect(host, port)
|
||||
if not data then fail(err)
|
||||
else pass("connected!") end
|
||||
data:setoption("tcp-nodelay", true)
|
||||
end
|
||||
|
||||
pass("attempting control connection...")
|
||||
control, err = socket.connect(host, port)
|
||||
if err then fail(err)
|
||||
else pass("connected!") end
|
||||
control:setoption("tcp-nodelay", true)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_methods(sock, methods)
|
||||
for _, v in methods do
|
||||
if type(sock[v]) ~= "function" then
|
||||
fail(sock.class .. " method '" .. v .. "' not registered")
|
||||
end
|
||||
end
|
||||
pass(sock.class .. " methods are ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_mixed(len)
|
||||
reconnect()
|
||||
local inter = math.ceil(len/4)
|
||||
local p1 = "unix " .. string.rep("x", inter) .. "line\n"
|
||||
local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
|
||||
local p3 = "raw " .. string.rep("z", inter) .. "bytes"
|
||||
local p4 = "end" .. string.rep("w", inter) .. "bytes"
|
||||
local bp1, bp2, bp3, bp4
|
||||
remote (string.format("str = data:receive(%d)",
|
||||
string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
|
||||
sent, err = data:send(p1..p2..p3..p4)
|
||||
if err then fail(err) end
|
||||
remote "data:send(str); data:close()"
|
||||
bp1, err = data:receive()
|
||||
if err then fail(err) end
|
||||
bp2, err = data:receive()
|
||||
if err then fail(err) end
|
||||
bp3, err = data:receive(string.len(p3))
|
||||
if err then fail(err) end
|
||||
bp4, err = data:receive("*a")
|
||||
if err then fail(err) end
|
||||
if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 and bp4 == p4 then
|
||||
pass("patterns match")
|
||||
else fail("patterns don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_asciiline(len)
|
||||
reconnect()
|
||||
local str, str10, back, err
|
||||
str = string.rep("x", math.mod(len, 10))
|
||||
str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
|
||||
str = str .. str10
|
||||
remote "str = data:receive()"
|
||||
sent, err = data:send(str.."\n")
|
||||
if err then fail(err) end
|
||||
remote "data:send(str ..'\\n')"
|
||||
back, err = data:receive()
|
||||
if err then fail(err) end
|
||||
if back == str then pass("lines match")
|
||||
else fail("lines don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_rawline(len)
|
||||
reconnect()
|
||||
local str, str10, back, err
|
||||
str = string.rep(string.char(47), math.mod(len, 10))
|
||||
str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
|
||||
math.floor(len/10))
|
||||
str = str .. str10
|
||||
remote "str = data:receive()"
|
||||
sent, err = data:send(str.."\n")
|
||||
if err then fail(err) end
|
||||
remote "data:send(str..'\\n')"
|
||||
back, err = data:receive()
|
||||
if err then fail(err) end
|
||||
if back == str then pass("lines match")
|
||||
else fail("lines don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_raw(len)
|
||||
reconnect()
|
||||
local half = math.floor(len/2)
|
||||
local s1, s2, back, err
|
||||
s1 = string.rep("x", half)
|
||||
s2 = string.rep("y", len-half)
|
||||
remote (string.format("str = data:receive(%d)", len))
|
||||
sent, err = data:send(s1)
|
||||
if err then fail(err) end
|
||||
sent, err = data:send(s2)
|
||||
if err then fail(err) end
|
||||
remote "data:send(str)"
|
||||
back, err = data:receive(len)
|
||||
if err then fail(err) end
|
||||
if back == s1..s2 then pass("blocks match")
|
||||
else fail("blocks don't match") end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_totaltimeoutreceive(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, partial
|
||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = string.rep('a', %d)
|
||||
data:send(str)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
data:send(str)
|
||||
]], 2*tm, len, sl, sl))
|
||||
data:settimeout(tm, "total")
|
||||
local t = socket.gettime()
|
||||
str, err, partial, elapsed = data:receive(2*len)
|
||||
check_timeout(tm, sl, elapsed, err, "receive", "total",
|
||||
string.len(str or partial) == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_totaltimeoutsend(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, total
|
||||
pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = data:receive(%d)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
str = data:receive(%d)
|
||||
]], 2*tm, len, sl, sl, len))
|
||||
data:settimeout(tm, "total")
|
||||
str = string.rep("a", 2*len)
|
||||
total, err, partial, elapsed = data:send(str)
|
||||
check_timeout(tm, sl, elapsed, err, "send", "total",
|
||||
total == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_blockingtimeoutreceive(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, partial
|
||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = string.rep('a', %d)
|
||||
data:send(str)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
data:send(str)
|
||||
]], 2*tm, len, sl, sl))
|
||||
data:settimeout(tm)
|
||||
str, err, partial, elapsed = data:receive(2*len)
|
||||
check_timeout(tm, sl, elapsed, err, "receive", "blocking",
|
||||
string.len(str or partial) == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_blockingtimeoutsend(len, tm, sl)
|
||||
reconnect()
|
||||
local str, err, total
|
||||
pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl)
|
||||
remote (string.format ([[
|
||||
data:settimeout(%d)
|
||||
str = data:receive(%d)
|
||||
print('server: sleeping for %ds')
|
||||
socket.sleep(%d)
|
||||
print('server: woke up')
|
||||
str = data:receive(%d)
|
||||
]], 2*tm, len, sl, sl, len))
|
||||
data:settimeout(tm)
|
||||
str = string.rep("a", 2*len)
|
||||
total, err, partial, elapsed = data:send(str)
|
||||
check_timeout(tm, sl, elapsed, err, "send", "blocking",
|
||||
total == 2*len)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function empty_connect()
|
||||
reconnect()
|
||||
if data then data:close() data = nil end
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
data = server:accept()
|
||||
]]
|
||||
data, err = socket.connect("", port)
|
||||
if not data then
|
||||
pass("ok")
|
||||
data = socket.connect(host, port)
|
||||
else
|
||||
pass("gethostbyname returns localhost on empty string...")
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function isclosed(c)
|
||||
return c:getfd() == -1 or c:getfd() == (2^32-1)
|
||||
end
|
||||
|
||||
function active_close()
|
||||
reconnect()
|
||||
if isclosed(data) then fail("should not be closed") end
|
||||
data:close()
|
||||
if not isclosed(data) then fail("should be closed") end
|
||||
data = nil
|
||||
local udp = socket.udp()
|
||||
if isclosed(udp) then fail("should not be closed") end
|
||||
udp:close()
|
||||
if not isclosed(udp) then fail("should be closed") end
|
||||
pass("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_closed()
|
||||
local back, partial, err
|
||||
local str = 'little string'
|
||||
reconnect()
|
||||
pass("trying read detection")
|
||||
remote (string.format ([[
|
||||
data:send('%s')
|
||||
data:close()
|
||||
data = nil
|
||||
]], str))
|
||||
-- try to get a line
|
||||
back, err, partial = data:receive()
|
||||
if not err then fail("should have gotten 'closed'.")
|
||||
elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
|
||||
elseif str ~= partial then fail("didn't receive partial result.")
|
||||
else pass("graceful 'closed' received") end
|
||||
reconnect()
|
||||
pass("trying write detection")
|
||||
remote [[
|
||||
data:close()
|
||||
data = nil
|
||||
]]
|
||||
total, err, partial = data:send(string.rep("ugauga", 100000))
|
||||
if not err then
|
||||
pass("failed: output buffer is at least %d bytes long!", total)
|
||||
elseif err ~= "closed" then
|
||||
fail("got '"..err.."' instead of 'closed'.")
|
||||
else
|
||||
pass("graceful 'closed' received after %d bytes were sent", partial)
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_selectbugs()
|
||||
local r, s, e = socket.select(nil, nil, 0.1)
|
||||
assert(type(r) == "table" and type(s) == "table" and
|
||||
(e == "timeout" or e == "error"))
|
||||
pass("both nil: ok")
|
||||
local udp = socket.udp()
|
||||
udp:close()
|
||||
r, s, e = socket.select({ udp }, { udp }, 0.1)
|
||||
assert(type(r) == "table" and type(s) == "table" and
|
||||
(e == "timeout" or e == "error"))
|
||||
pass("closed sockets: ok")
|
||||
e = pcall(socket.select, "wrong", 1, 0.1)
|
||||
assert(e == false)
|
||||
e = pcall(socket.select, {}, 1, 0.1)
|
||||
assert(e == false)
|
||||
pass("invalid input: ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_timeout()
|
||||
io.stderr:write("accept with timeout (if it hangs, it failed): ")
|
||||
local s, e = socket.bind("*", 0, 0)
|
||||
assert(s, e)
|
||||
local t = socket.gettime()
|
||||
s:settimeout(1)
|
||||
local c, e = s:accept()
|
||||
assert(not c, "should not accept")
|
||||
assert(e == "timeout", string.format("wrong error message (%s)", e))
|
||||
t = socket.gettime() - t
|
||||
assert(t < 2, string.format("took to long to give up (%gs)", t))
|
||||
s:close()
|
||||
pass("good")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_timeout()
|
||||
io.stderr:write("connect with timeout (if it hangs, it failed!): ")
|
||||
local t = socket.gettime()
|
||||
local c, e = socket.tcp()
|
||||
assert(c, e)
|
||||
c:settimeout(0.1)
|
||||
local t = socket.gettime()
|
||||
local r, e = c:connect("10.0.0.1", 81)
|
||||
print(r, e)
|
||||
assert(not r, "should not connect")
|
||||
assert(socket.gettime() - t < 2, "took too long to give up.")
|
||||
c:close()
|
||||
print("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function accept_errors()
|
||||
io.stderr:write("not listening: ")
|
||||
local d, e = socket.bind("*", 0)
|
||||
assert(d, e);
|
||||
local c, e = socket.tcp();
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
d:settimeout(2)
|
||||
local r, e = d:accept()
|
||||
assert(not r and e)
|
||||
print("ok: ", e)
|
||||
io.stderr:write("not supported: ")
|
||||
local c, e = socket.udp()
|
||||
assert(c, e);
|
||||
d:setfd(c:getfd())
|
||||
local r, e = d:accept()
|
||||
assert(not r and e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function connect_errors()
|
||||
io.stderr:write("connection refused: ")
|
||||
local c, e = socket.connect("localhost", 1);
|
||||
assert(not c and e)
|
||||
print("ok: ", e)
|
||||
io.stderr:write("host not found: ")
|
||||
local c, e = socket.connect("host.is.invalid", 1);
|
||||
assert(not c and e, e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function rebind_test()
|
||||
local c = socket.bind("localhost", 0)
|
||||
local i, p = c:getsockname()
|
||||
local s, e = socket.tcp()
|
||||
assert(s, e)
|
||||
s:setoption("reuseaddr", false)
|
||||
r, e = s:bind("localhost", p)
|
||||
assert(not r, "managed to rebind!")
|
||||
assert(e)
|
||||
print("ok: ", e)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function getstats_test()
|
||||
reconnect()
|
||||
local t = 0
|
||||
for i = 1, 25 do
|
||||
local c = math.random(1, 100)
|
||||
remote (string.format ([[
|
||||
str = data:receive(%d)
|
||||
data:send(str)
|
||||
]], c))
|
||||
data:send(string.rep("a", c))
|
||||
data:receive(c)
|
||||
t = t + c
|
||||
local r, s, a = data:getstats()
|
||||
assert(r == t, "received count failed" .. tostring(r)
|
||||
.. "/" .. tostring(t))
|
||||
assert(s == t, "sent count failed" .. tostring(s)
|
||||
.. "/" .. tostring(t))
|
||||
end
|
||||
print("ok")
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
function test_nonblocking(size)
|
||||
reconnect()
|
||||
print("Testing " .. 2*size .. " bytes")
|
||||
remote(string.format([[
|
||||
data:send(string.rep("a", %d))
|
||||
socket.sleep(0.5)
|
||||
data:send(string.rep("b", %d) .. "\n")
|
||||
]], size, size))
|
||||
local err = "timeout"
|
||||
local part = ""
|
||||
local str
|
||||
data:settimeout(0)
|
||||
while 1 do
|
||||
str, err, part = data:receive("*l", part)
|
||||
if err ~= "timeout" then break end
|
||||
end
|
||||
assert(str == (string.rep("a", size) .. string.rep("b", size)))
|
||||
reconnect()
|
||||
remote(string.format([[
|
||||
str = data:receive(%d)
|
||||
socket.sleep(0.5)
|
||||
str = data:receive(2*%d, str)
|
||||
data:send(str)
|
||||
]], size, size))
|
||||
data:settimeout(0)
|
||||
local start = 0
|
||||
while 1 do
|
||||
ret, err, start = data:send(str, start+1)
|
||||
if err ~= "timeout" then break end
|
||||
end
|
||||
data:send("\n")
|
||||
data:settimeout(-1)
|
||||
local back = data:receive(2*size)
|
||||
assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
|
||||
print("ok")
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
|
||||
test("method registration")
|
||||
test_methods(socket.tcp(), {
|
||||
"accept",
|
||||
"bind",
|
||||
"close",
|
||||
"connect",
|
||||
"dirty",
|
||||
"getfd",
|
||||
"getpeername",
|
||||
"getsockname",
|
||||
"getstats",
|
||||
"setstats",
|
||||
"listen",
|
||||
"receive",
|
||||
"send",
|
||||
"setfd",
|
||||
"setoption",
|
||||
"setpeername",
|
||||
"setsockname",
|
||||
"settimeout",
|
||||
"shutdown",
|
||||
})
|
||||
|
||||
test_methods(socket.udp(), {
|
||||
"close",
|
||||
"getpeername",
|
||||
"dirty",
|
||||
"getfd",
|
||||
"getpeername",
|
||||
"getsockname",
|
||||
"receive",
|
||||
"receivefrom",
|
||||
"send",
|
||||
"sendto",
|
||||
"setfd",
|
||||
"setoption",
|
||||
"setpeername",
|
||||
"setsockname",
|
||||
"settimeout"
|
||||
})
|
||||
|
||||
test("select function")
|
||||
test_selectbugs()
|
||||
|
||||
test("connect function")
|
||||
connect_timeout()
|
||||
empty_connect()
|
||||
connect_errors()
|
||||
|
||||
test("rebinding: ")
|
||||
rebind_test()
|
||||
|
||||
test("active close: ")
|
||||
active_close()
|
||||
|
||||
test("closed connection detection: ")
|
||||
test_closed()
|
||||
|
||||
test("accept function: ")
|
||||
accept_timeout()
|
||||
accept_errors()
|
||||
|
||||
test("getstats test")
|
||||
getstats_test()
|
||||
|
||||
test("character line")
|
||||
test_asciiline(1)
|
||||
test_asciiline(17)
|
||||
test_asciiline(200)
|
||||
test_asciiline(4091)
|
||||
test_asciiline(80199)
|
||||
test_asciiline(8000000)
|
||||
test_asciiline(80199)
|
||||
test_asciiline(4091)
|
||||
test_asciiline(200)
|
||||
test_asciiline(17)
|
||||
test_asciiline(1)
|
||||
|
||||
test("mixed patterns")
|
||||
test_mixed(1)
|
||||
test_mixed(17)
|
||||
test_mixed(200)
|
||||
test_mixed(4091)
|
||||
test_mixed(801990)
|
||||
test_mixed(4091)
|
||||
test_mixed(200)
|
||||
test_mixed(17)
|
||||
test_mixed(1)
|
||||
|
||||
test("binary line")
|
||||
test_rawline(1)
|
||||
test_rawline(17)
|
||||
test_rawline(200)
|
||||
test_rawline(4091)
|
||||
test_rawline(80199)
|
||||
test_rawline(8000000)
|
||||
test_rawline(80199)
|
||||
test_rawline(4091)
|
||||
test_rawline(200)
|
||||
test_rawline(17)
|
||||
test_rawline(1)
|
||||
|
||||
test("raw transfer")
|
||||
test_raw(1)
|
||||
test_raw(17)
|
||||
test_raw(200)
|
||||
test_raw(4091)
|
||||
test_raw(80199)
|
||||
test_raw(8000000)
|
||||
test_raw(80199)
|
||||
test_raw(4091)
|
||||
test_raw(200)
|
||||
test_raw(17)
|
||||
test_raw(1)
|
||||
|
||||
test("non-blocking transfer")
|
||||
test_nonblocking(1)
|
||||
test_nonblocking(17)
|
||||
test_nonblocking(200)
|
||||
test_nonblocking(4091)
|
||||
test_nonblocking(80199)
|
||||
test_nonblocking(800000)
|
||||
test_nonblocking(80199)
|
||||
test_nonblocking(4091)
|
||||
test_nonblocking(200)
|
||||
test_nonblocking(17)
|
||||
test_nonblocking(1)
|
||||
|
||||
test("total timeout on send")
|
||||
test_totaltimeoutsend(800091, 1, 3)
|
||||
test_totaltimeoutsend(800091, 2, 3)
|
||||
test_totaltimeoutsend(800091, 5, 2)
|
||||
test_totaltimeoutsend(800091, 3, 1)
|
||||
|
||||
test("total timeout on receive")
|
||||
test_totaltimeoutreceive(800091, 1, 3)
|
||||
test_totaltimeoutreceive(800091, 2, 3)
|
||||
test_totaltimeoutreceive(800091, 3, 2)
|
||||
test_totaltimeoutreceive(800091, 3, 1)
|
||||
|
||||
test("blocking timeout on send")
|
||||
test_blockingtimeoutsend(800091, 1, 3)
|
||||
test_blockingtimeoutsend(800091, 2, 3)
|
||||
test_blockingtimeoutsend(800091, 3, 2)
|
||||
test_blockingtimeoutsend(800091, 3, 1)
|
||||
|
||||
test("blocking timeout on receive")
|
||||
test_blockingtimeoutreceive(800091, 1, 3)
|
||||
test_blockingtimeoutreceive(800091, 2, 3)
|
||||
test_blockingtimeoutreceive(800091, 3, 2)
|
||||
test_blockingtimeoutreceive(800091, 3, 1)
|
||||
|
||||
test(string.format("done in %.2fs", socket.gettime() - start))
|
@ -1,15 +0,0 @@
|
||||
socket = require("socket");
|
||||
host = host or "localhost";
|
||||
port = port or "8383";
|
||||
server = assert(socket.bind(host, port));
|
||||
ack = "\n";
|
||||
while 1 do
|
||||
print("server: waiting for client connection...");
|
||||
control = assert(server:accept());
|
||||
while 1 do
|
||||
command = assert(control:receive());
|
||||
assert(control:send(ack));
|
||||
print(command);
|
||||
(loadstring(command))();
|
||||
end
|
||||
end
|
@ -1,37 +0,0 @@
|
||||
function readfile(name)
|
||||
local f = io.open(name, "rb")
|
||||
if not f then return nil end
|
||||
local s = f:read("*a")
|
||||
f:close()
|
||||
return s
|
||||
end
|
||||
|
||||
function similar(s1, s2)
|
||||
return string.lower(string.gsub(s1 or "", "%s", "")) ==
|
||||
string.lower(string.gsub(s2 or "", "%s", ""))
|
||||
end
|
||||
|
||||
function fail(msg)
|
||||
msg = msg or "failed"
|
||||
error(msg, 2)
|
||||
end
|
||||
|
||||
function compare(input, output)
|
||||
local original = readfile(input)
|
||||
local recovered = readfile(output)
|
||||
if original ~= recovered then fail("comparison failed")
|
||||
else print("ok") end
|
||||
end
|
||||
|
||||
local G = _G
|
||||
local set = rawset
|
||||
local warn = print
|
||||
|
||||
local setglobal = function(table, key, value)
|
||||
warn("changed " .. key)
|
||||
set(table, key, value)
|
||||
end
|
||||
|
||||
setmetatable(G, {
|
||||
__newindex = setglobal
|
||||
})
|
@ -1,45 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
# ONLY FOR MAINTAINER USE!!
|
||||
|
||||
t="`pwd`";
|
||||
cd "`dirname "$0"`/..";
|
||||
basedir="`pwd`";
|
||||
cd "$t";
|
||||
|
||||
ver=0.1.2;
|
||||
|
||||
do_make() # [PLATFORM]
|
||||
{
|
||||
|
||||
TC_FILE='';
|
||||
BLD_SFX='';
|
||||
|
||||
if [ "$1" ]; then
|
||||
TC_FILE="-DCMAKE_TOOLCHAIN_FILE=cmake/x-$1.cmake";
|
||||
BLD_SFX="-$1";
|
||||
fi
|
||||
|
||||
cd "$basedir";
|
||||
mkdir -p Build$BLD_SFX;
|
||||
cd Build$BLD_SFX;
|
||||
cmake $TC_FILE .. || exit;
|
||||
make || exit;
|
||||
make pack_mod || exit;
|
||||
cd ..;
|
||||
|
||||
}
|
||||
|
||||
mkdir -p "$basedir/dists"
|
||||
|
||||
# Native Version
|
||||
(do_make \
|
||||
&& cd Build \
|
||||
&& tar cfz "$basedir/dists/Kaeza-irc-$ver-`uname -s`-`uname -p`.tar.gz" irc \
|
||||
) || exit;
|
||||
|
||||
# Linux -> MinGW32 Crosscompiler
|
||||
(do_make i586-mingw32msvc \
|
||||
&& cd Build-i586-mingw32msvc \
|
||||
&& zip -r "$basedir/dists/Kaeza-irc-$ver-Win32.zip" irc \
|
||||
) || exit;
|
8
quick_install.sh
Executable file
8
quick_install.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#! /bin/sh
|
||||
|
||||
mkdir -p Build \
|
||||
&& cd Build \
|
||||
&& cmake .. \
|
||||
&& make \
|
||||
&& cd .. \
|
||||
&& cp -r Build/irc $1
|
87
src/API.txt
Normal file
87
src/API.txt
Normal file
@ -0,0 +1,87 @@
|
||||
IRC Mod API
|
||||
-----------
|
||||
This file documents the Minetest IRC mod API.
|
||||
|
||||
BASICS
|
||||
------
|
||||
In order to allow your mod to interface with this mod, you must add 'irc'
|
||||
(without the quotes) to your mod's 'depends.txt' file.
|
||||
|
||||
|
||||
REFERENCE
|
||||
---------
|
||||
|
||||
mt_irc:say([name, ]message)
|
||||
Sends <message> to either the channel (if <name> is nil or not specified),
|
||||
or to the given user (if <name> is specified).
|
||||
Example:
|
||||
mt_irc:say("Hello, Channel!")
|
||||
mt_irc:say("john1234", "How are you?")
|
||||
|
||||
mt_irc:register_bot_command(name, cmdDef)
|
||||
Registers a new bot command named <name>.
|
||||
When an user sends a private message to the bot with the command name, the
|
||||
command's function is called.
|
||||
Here's the format of a command definition (<cmdDef>):
|
||||
cmdDef = {
|
||||
params = "<param1> ...", -- A description of the command's parameters
|
||||
description = "My command", -- A description of what the command does. (one-liner)
|
||||
func = function(user, param)
|
||||
-- This function gets called when the command is invoked.
|
||||
-- <user> is a user table for the user that ran the command.
|
||||
-- (See the LuaIRC documentation for details.)
|
||||
-- It contains fields such as 'nick' and 'ident'
|
||||
-- <param> is a string of parameters to the command (may be "")
|
||||
end,
|
||||
};
|
||||
Example:
|
||||
mt_irc:register_bot_command("hello", {
|
||||
params = "",
|
||||
description = "Greet user",
|
||||
func = function(user, param)
|
||||
mt_irc:say(user.nick, "Hello!")
|
||||
end,
|
||||
});
|
||||
|
||||
mt_irc.joined_players[name]
|
||||
This table holds the players who are currently on the channel (may be less
|
||||
than the players in the game). It is modified by the /part and /join chat
|
||||
commands.
|
||||
Example:
|
||||
if mt_irc.joined_players["joe"] then
|
||||
-- Joe is talking on IRC
|
||||
end
|
||||
|
||||
mt_irc:register_hook(name, func)
|
||||
Registers a function to be called when an event happens. <name> is the name
|
||||
of the event, and <func> is the function to be called. See HOOKS below
|
||||
for more information
|
||||
Example:
|
||||
mt_irc:register_hook("OnSend", function(line)
|
||||
print("SEND: "..line)
|
||||
end)
|
||||
|
||||
This mod also supplies some utility functions:
|
||||
|
||||
string.expandvars(string, vars)
|
||||
Expands all occurrences of the pattern "$(varname)" with the value of
|
||||
'varname' in the <vars> table. Variable names not found on the table
|
||||
are left verbatim in the string.
|
||||
Example:
|
||||
local tpl = "$(foo) $(bar) $(baz)"
|
||||
local s = tpl:expandvars({ foo=1, bar="Hello" })
|
||||
assert(s == "1 Hello $(baz)")
|
||||
|
||||
In addition, all the configuration options decribed in `README.txt' are
|
||||
available to other mods, though they should be considered "read only". Do
|
||||
not modify these settings at runtime or you will most likely crash the
|
||||
server!
|
||||
|
||||
|
||||
HOOKS
|
||||
---------
|
||||
The 'mt_irc:register_hook' function can register functions to be called
|
||||
when some events happen. The events supported are the same as the LuaIRC
|
||||
ones with a few added (mostly for internal use).
|
||||
See src/LuaIRC/doc/irc.luadoc for more information.
|
||||
|
22
src/LICENSE.txt
Normal file
22
src/LICENSE.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Copyright (c) 2013, Diego Martinez (kaeza)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
1
src/LuaIRC
Submodule
1
src/LuaIRC
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8a2e47a326e097102533dfd90c67193614e7a479
|
165
src/botcmds.lua
165
src/botcmds.lua
@ -1,91 +1,106 @@
|
||||
mt_irc.bot_commands = {}
|
||||
|
||||
mt_irc.bot_commands = { };
|
||||
|
||||
mt_irc.bot_help = function ( from, cmdname )
|
||||
local cmd = mt_irc.bot_commands[cmdname];
|
||||
if (not cmd) then
|
||||
irc.say(from, "Unknown command `"..cmdname.."'");
|
||||
return;
|
||||
end
|
||||
local usage = "Usage: !"..cmdname;
|
||||
if (cmd.params) then usage = usage.." "..cmd.params; end
|
||||
irc.say(from, usage);
|
||||
if (cmd.description) then irc.say(from, " "..cmd.description); end
|
||||
end
|
||||
|
||||
mt_irc.register_bot_command = function ( name, def )
|
||||
if ((not def.func) or (type(def.func) ~= "function")) then
|
||||
error("Wrong bot command definition", 2);
|
||||
end
|
||||
mt_irc.bot_commands[name] = def;
|
||||
end
|
||||
|
||||
mt_irc.register_bot_command("help", {
|
||||
params = "[<command>]";
|
||||
description = "Get help about a command";
|
||||
func = function ( from, args )
|
||||
if (args ~= "") then
|
||||
mt_irc.bot_help(from, args);
|
||||
function mt_irc:bot_command(user, message)
|
||||
local pos = message:find(" ", 1, true)
|
||||
local cmd, args
|
||||
if pos then
|
||||
cmd = message:sub(1, pos - 1)
|
||||
args = message:sub(pos + 1)
|
||||
else
|
||||
local cmdlist = "Available commands:";
|
||||
cmd = message
|
||||
args = ""
|
||||
end
|
||||
|
||||
if not self.bot_commands[cmd] then
|
||||
self:say(user.nick, "Unknown command '"..cmd.."'. Try `!help'."
|
||||
.." Or use @playername <message> to send a private message")
|
||||
return
|
||||
end
|
||||
|
||||
self.bot_commands[cmd].func(user, args)
|
||||
end
|
||||
|
||||
|
||||
function mt_irc:register_bot_command(name, def)
|
||||
if (not def.func) or (type(def.func) ~= "function") then
|
||||
error("Erroneous bot command definition. def.func missing.", 2)
|
||||
end
|
||||
self.bot_commands[name] = def
|
||||
end
|
||||
|
||||
|
||||
mt_irc:register_bot_command("help", {
|
||||
params = "<command>",
|
||||
description = "Get help about a command",
|
||||
func = function(user, args)
|
||||
if args == "" then
|
||||
mt_irc:say(user.nick, "No command name specified. Use 'list' for a list of cammands")
|
||||
return
|
||||
end
|
||||
|
||||
local cmd = mt_irc.bot_commands[args]
|
||||
if not cmd then
|
||||
mt_irc:say(user.nick, "Unknown command '"..cmdname.."'.")
|
||||
return
|
||||
end
|
||||
|
||||
local usage = ("Usage: %c%s %s -- %s"):format(
|
||||
mt_irc.config.command_prefix,
|
||||
args,
|
||||
cmd.params or "<no parameters>",
|
||||
cmd.description or "<no description>")
|
||||
mt_irc:say(user.nick, usage)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
mt_irc:register_bot_command("list", {
|
||||
params = "",
|
||||
description = "List available commands.",
|
||||
func = function(user, args)
|
||||
local cmdlist = "Available commands: "
|
||||
for name, cmd in pairs(mt_irc.bot_commands) do
|
||||
cmdlist = cmdlist.." "..name;
|
||||
cmdlist = cmdlist..name..", "
|
||||
end
|
||||
irc.say(from, cmdlist);
|
||||
irc.say(from, "Use `!help <command name>' to get help about a specific command.");
|
||||
mt_irc:say(user.nick, cmdlist
|
||||
.." -- Use 'help <command name>' to get help about a specific command.")
|
||||
end
|
||||
end;
|
||||
});
|
||||
})
|
||||
|
||||
mt_irc.register_bot_command("who", {
|
||||
params = nil;
|
||||
description = "Tell who is playing";
|
||||
func = function ( from, args )
|
||||
local s = "";
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then
|
||||
s = s.." "..k;
|
||||
end
|
||||
end
|
||||
irc.say(from, "Players On Channel:"..s);
|
||||
end;
|
||||
});
|
||||
|
||||
mt_irc.register_bot_command("whereis", {
|
||||
params = "<player>";
|
||||
description = "Tell the location of <player>";
|
||||
func = function ( from, args )
|
||||
if (args == "") then
|
||||
mt_irc.bot_help(from, "whereis");
|
||||
return;
|
||||
mt_irc:register_bot_command("whereis", {
|
||||
params = "<player>",
|
||||
description = "Tell the location of <player>",
|
||||
func = function(user, args)
|
||||
if args == "" then
|
||||
mt_irc:bot_help(user, "whereis")
|
||||
return
|
||||
end
|
||||
local list = minetest.env:get_objects_inside_radius({x=0,y=0,z=0}, 100000);
|
||||
for _, obj in ipairs(list) do
|
||||
if (obj:is_player() and (obj:get_player_name() == args)) then
|
||||
local fmt = "Player %s is at (%.2f,%.2f,%.2f)";
|
||||
local pos = obj:getpos();
|
||||
irc.say(from, fmt:format(args, pos.x, pos.y, pos.z));
|
||||
return;
|
||||
local player = minetest.env:get_player_by_name(args)
|
||||
if player then
|
||||
local fmt = "Player %s is at (%.2f,%.2f,%.2f)"
|
||||
local pos = player:getpos()
|
||||
mt_irc:say(user.nick, fmt:format(args, pos.x, pos.y, pos.z))
|
||||
return
|
||||
end
|
||||
mt_irc:say(user.nick, "There is No player named '"..args.."'")
|
||||
end
|
||||
irc.say(from, "There's No player named `"..args.."'");
|
||||
end;
|
||||
});
|
||||
})
|
||||
|
||||
local starttime = os.time();
|
||||
|
||||
mt_irc.register_bot_command("uptime", {
|
||||
params = "";
|
||||
description = "Tell how much time the server has been up";
|
||||
privs = { shout=true; };
|
||||
func = function ( name, param )
|
||||
local t = os.time();
|
||||
local diff = os.difftime(t, starttime);
|
||||
local fmt = "Server has been running for %d:%02d:%02d";
|
||||
irc.say(name, fmt:format(
|
||||
local starttime = os.time()
|
||||
mt_irc:register_bot_command("uptime", {
|
||||
description = "Tell how much time the server has been up",
|
||||
func = function(user, args)
|
||||
local cur_time = os.time()
|
||||
local diff = os.difftime(cur_time, starttime)
|
||||
local fmt = "Server has been running for %d:%02d:%02d"
|
||||
mt_irc:say(user.nick, fmt:format(
|
||||
math.floor(diff / 60 / 60),
|
||||
math.mod(math.floor(diff / 60), 60),
|
||||
math.mod(math.floor(diff), 60)
|
||||
));
|
||||
end;
|
||||
});
|
||||
))
|
||||
end
|
||||
})
|
||||
|
||||
|
239
src/callback.lua
239
src/callback.lua
@ -1,232 +1,35 @@
|
||||
-- IRC Mod for Minetest
|
||||
-- By Diego Martínez <kaeza@users.sf.net>
|
||||
--
|
||||
-- This mod allows to tie a Minetest server to an IRC channel.
|
||||
--
|
||||
-- This program is free software. It comes without any warranty, to
|
||||
-- the extent permitted by applicable law. You can redistribute it
|
||||
-- and/or modify it under the terms of the Do What The Fuck You Want
|
||||
-- To Public License, Version 2, as published by Sam Hocevar. See
|
||||
-- http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
--
|
||||
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||
-- See LICENSE.txt for details.
|
||||
|
||||
local irc = require("irc");
|
||||
|
||||
mt_irc.callbacks = { };
|
||||
|
||||
mt_irc._callback = function ( name, breakonreturn, ... )
|
||||
local list = mt_irc.callbacks[name];
|
||||
if (not list) then return; end
|
||||
for n = 1, #list do
|
||||
local r = list[n](...);
|
||||
if (breakonreturn and (r ~= nil)) then return r; end
|
||||
end
|
||||
end
|
||||
|
||||
mt_irc.register_callback = function ( name, func )
|
||||
local list = mt_irc.callbacks[name];
|
||||
if (not list) then
|
||||
list = { };
|
||||
mt_irc.callbacks[name] = list;
|
||||
end
|
||||
list[#list + 1] = func;
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name();
|
||||
mt_irc.connected_players[name] = mt_irc.auto_join;
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
mt_irc.say("*** "..name.." joined the game");
|
||||
end);
|
||||
local name = player:get_player_name()
|
||||
if mt_irc.connected then
|
||||
mt_irc:say("*** "..name.." joined the game")
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name();
|
||||
mt_irc.connected_players[name] = nil;
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
mt_irc.say("*** "..name.." left the game");
|
||||
end);
|
||||
|
||||
irc.register_callback("connect", function ( )
|
||||
mt_irc.got_motd = true;
|
||||
irc.join(mt_irc.channel);
|
||||
end);
|
||||
|
||||
irc.register_callback("channel_msg", function ( channel, from, message )
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
local t = {
|
||||
name=(from or "<BUG:no one is saying this>");
|
||||
message=(message or "<BUG:there is no message>");
|
||||
server=mt_irc.server;
|
||||
port=mt_irc.port;
|
||||
channel=mt_irc.channel;
|
||||
};
|
||||
local text = mt_irc.message_format_in:gsub("%$%(([^)]+)%)", t)
|
||||
if (mt_irc._callback("channel_msg", from, message, text)) then return; end
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, text); end
|
||||
local name = player:get_player_name()
|
||||
if mt_irc.connected then
|
||||
mt_irc:say("*** "..name.." left the game")
|
||||
end
|
||||
end);
|
||||
end)
|
||||
|
||||
local function bot_command ( from, message )
|
||||
|
||||
local pos = message:find(" ", 1, true);
|
||||
local cmd, args;
|
||||
if (pos) then
|
||||
cmd = message:sub(1, pos - 1);
|
||||
args = message:sub(pos + 1);
|
||||
else
|
||||
cmd = message;
|
||||
args = "";
|
||||
end
|
||||
|
||||
if (not mt_irc.bot_commands[cmd]) then
|
||||
mt_irc.say(from, "Unknown command `"..cmd.."'. Try `!help'.");
|
||||
return;
|
||||
end
|
||||
|
||||
mt_irc.bot_commands[cmd].func(from, args);
|
||||
|
||||
end
|
||||
|
||||
irc.register_callback("private_msg", function ( from, message )
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
local player_to;
|
||||
local msg;
|
||||
if (message:sub(1, 1) == "@") then
|
||||
local pos = message:find(" ", 1, true);
|
||||
if (not pos) then return; end
|
||||
player_to = message:sub(2, pos - 1);
|
||||
msg = message:sub(pos + 1);
|
||||
elseif (message:sub(1, 1) == "!") then
|
||||
bot_command(from, message:sub(2));
|
||||
return;
|
||||
else
|
||||
irc.say(from, 'Message not sent! Please use "!help" to see possible commands.');
|
||||
irc.say(from, ' Or use the "@playername Message" syntax to send a private message.');
|
||||
return;
|
||||
end
|
||||
if (not mt_irc.connected_players[player_to]) then
|
||||
irc.say(from, "User `"..player_to.."' is not connected to IRC.");
|
||||
return;
|
||||
end
|
||||
local t = {
|
||||
name=(from or "<BUG:no one is saying this>");
|
||||
message=(msg or "<BUG:there is no message>");
|
||||
server=mt_irc.server;
|
||||
port=mt_irc.port;
|
||||
channel=mt_irc.channel;
|
||||
};
|
||||
local text = mt_irc.message_format_in:expandvars(t);
|
||||
if (mt_irc._callback("private_msg", from, player_to, message, text)) then return; end
|
||||
minetest.chat_send_player(player_to, "PRIVATE: "..text);
|
||||
mt_irc.say(from, "Message sent!")
|
||||
end);
|
||||
|
||||
irc.register_callback("kick", function(chaninfo, nick, kicker)
|
||||
if nick == mt_irc.server_nick then
|
||||
minetest.chat_send_all("IRC: Bot was kicked by "..kicker..".");
|
||||
mt_irc.got_motd = false;
|
||||
mt_irc.connect_ok = false;
|
||||
irc.quit("Kicked");
|
||||
end
|
||||
end);
|
||||
|
||||
irc.register_callback("nick_change", function ( from, old_nick )
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
mt_irc._callback("nick_change", false, old_nick, from);
|
||||
local text = "["..old_nick.." changed his nick to "..from.."]";
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, text); end
|
||||
end
|
||||
end);
|
||||
|
||||
irc.register_callback("join", function ( servinfo, from )
|
||||
local text = "*** "..from.." joined "..mt_irc.channel;
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, text); end
|
||||
end
|
||||
end);
|
||||
|
||||
irc.register_callback("part", function ( servinfo, from, part_msg )
|
||||
mt_irc._callback("part", false, from, part_msg);
|
||||
local text
|
||||
if part_msg then
|
||||
text = "*** "..from.." left "..mt_irc.channel.." ("..part_msg..")";
|
||||
else
|
||||
text = "*** "..from.." left "..mt_irc.channel;
|
||||
end
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, text); end
|
||||
end
|
||||
end);
|
||||
|
||||
irc.register_callback("channel_act", function ( servinfo, from, message)
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
local text = "*** "..from.." "..message;
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, text); end
|
||||
end
|
||||
end);
|
||||
|
||||
minetest.register_on_chat_message(function(name, message)
|
||||
if (not mt_irc.connect_ok) then return; end
|
||||
if (message:sub(1, 1) == "/") then return; end
|
||||
if (not mt_irc.connected_players[name]) then return; end
|
||||
if (not minetest.check_player_privs(name, {shout=true})) then
|
||||
return;
|
||||
if not mt_irc.connected
|
||||
or message:sub(1, 1) == "/"
|
||||
or not mt_irc.joined_players[name]
|
||||
or (not minetest.check_player_privs(name, {shout=true})) then
|
||||
return
|
||||
end
|
||||
if (not mt_irc.buffered_messages) then
|
||||
mt_irc.buffered_messages = { };
|
||||
end
|
||||
mt_irc.buffered_messages[#mt_irc.buffered_messages + 1] = {
|
||||
name = name;
|
||||
message = message;
|
||||
};
|
||||
end);
|
||||
mt_irc:queueMsg(mt_irc.msgs.playerMessage(mt_irc.config.channel, name, message))
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
irc.quit("Game shutting down.");
|
||||
for n = 1, 5 do
|
||||
irc.poll();
|
||||
end
|
||||
end);
|
||||
|
||||
irc.handlers.on_error = function (...) --( from, respond_to )
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then minetest.chat_send_player(k, "IRC: Bot had a network error. Reconnecting in 5 seconds..."); end
|
||||
end
|
||||
for _, v in ipairs({...}) do
|
||||
minetest.chat_send_all(dump(v));
|
||||
end
|
||||
irc.quit("Network error");
|
||||
for n = 1, 5 do
|
||||
irc.poll();
|
||||
end
|
||||
mt_irc.got_motd = false;
|
||||
mt_irc.connect_ok = false;
|
||||
minetest.after(5, mt_irc.connect);
|
||||
end
|
||||
|
||||
irc.handlers.on_err_nicknameinuse = function ( from, respond_to )
|
||||
irc.quit("Nick in use");
|
||||
for n = 1, 5 do
|
||||
irc.poll();
|
||||
end
|
||||
mt_irc.got_motd = false;
|
||||
mt_irc.connect_ok = false;
|
||||
local n = (tonumber(mt_irc.server_nick:sub(-1)) or 0) + 1;
|
||||
if (n == 10) then n = 1; end
|
||||
mt_irc.server_nick = mt_irc.server_nick:sub(1, -2)..n;
|
||||
mt_irc.connect();
|
||||
end
|
||||
|
||||
-- TESTING
|
||||
--[[
|
||||
mt_irc.register_callback("part", function ( nick, part_msg )
|
||||
mt_irc.say("TEST: "..nick.." has left the building!");
|
||||
mt_irc:disconnect("Game shutting down.")
|
||||
end)
|
||||
|
||||
mt_irc.register_callback("nick_change", function ( old_nick, new_nick )
|
||||
mt_irc.say("TEST: "..old_nick.." -> "..new_nick);
|
||||
end)
|
||||
]]
|
||||
|
198
src/chatcmds.lua
198
src/chatcmds.lua
@ -1,124 +1,104 @@
|
||||
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||
-- See LICENSE.txt for details.
|
||||
|
||||
-- IRC Mod for Minetest
|
||||
-- By Diego Martínez <kaeza@users.sf.net>
|
||||
--
|
||||
-- This mod allows to tie a Minetest server to an IRC channel.
|
||||
--
|
||||
-- This program is free software. It comes without any warranty, to
|
||||
-- the extent permitted by applicable law. You can redistribute it
|
||||
-- and/or modify it under the terms of the Do What The Fuck You Want
|
||||
-- To Public License, Version 2, as published by Sam Hocevar. See
|
||||
-- http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
--
|
||||
-- Note: This file does NOT conatin every chat command, only general ones.
|
||||
-- Feature-specific commands (like /join) are in their own files.
|
||||
|
||||
local irc = require("irc");
|
||||
|
||||
minetest.register_chatcommand("irc_msg", {
|
||||
params = "<name> <message>";
|
||||
description = "Send a private message to an IRC user";
|
||||
privs = { shout=true; };
|
||||
params = "<name> <message>",
|
||||
description = "Send a private message to an IRC user",
|
||||
privs = {shout=true},
|
||||
func = function(name, param)
|
||||
if (not mt_irc.connect_ok) then
|
||||
minetest.chat_send_player(name, "IRC: You are not connected, use /irc_connect.");
|
||||
return;
|
||||
if not mt_irc.connected then
|
||||
minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.")
|
||||
return
|
||||
end
|
||||
local found, _, toname, msg = param:find("^([^%s#]+)%s(.+)");
|
||||
local found, _, toname, message = param:find("^([^%s]+)%s(.+)")
|
||||
if not found then
|
||||
minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.");
|
||||
return;
|
||||
minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.")
|
||||
return
|
||||
end
|
||||
local t = {name=name, message=msg};
|
||||
local text = mt_irc.message_format_out:expandvars(t);
|
||||
mt_irc.say(toname, text);
|
||||
local validNick = false
|
||||
for nick, user in pairs(mt_irc.conn.channels[mt_irc.config.channel].users) do
|
||||
if nick:lower() == toname:lower() then
|
||||
validNick = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if toname:find("Serv|Bot") then
|
||||
validNick = false
|
||||
end
|
||||
if not validNick then
|
||||
minetest.chat_send_player(name,
|
||||
"You can not message that user. (Hint: They have to be in the channel)")
|
||||
return
|
||||
end
|
||||
mt_irc:queueMsg(mt_irc.msgs.playerMessage(toname, name, message))
|
||||
minetest.chat_send_player(name, "Message sent!")
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("irc_connect", {
|
||||
params = "";
|
||||
description = "Connect to the IRC server";
|
||||
privs = { irc_admin=true; };
|
||||
func = function ( name, param )
|
||||
if (mt_irc.connect_ok) then
|
||||
minetest.chat_send_player(name, "IRC: You are already connected.");
|
||||
return;
|
||||
end
|
||||
mt_irc.connect();
|
||||
minetest.chat_send_player(name, "IRC: You are now connected.");
|
||||
irc.say(mt_irc.channel, name.." joined the channel.");
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("irc_disconnect", {
|
||||
params = "";
|
||||
description = "Disconnect from the IRC server";
|
||||
privs = { irc_admin=true; };
|
||||
func = function ( name, param )
|
||||
if (not mt_irc.connect_ok) then
|
||||
minetest.chat_send_player(name, "IRC: You are not connected.");
|
||||
return;
|
||||
end
|
||||
irc.quit("Manual BOT Disconnection");
|
||||
minetest.chat_send_player(name, "IRC: You are now disconnected.");
|
||||
mt_irc.connect_ok = false;
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("irc_reconnect", {
|
||||
params = "";
|
||||
description = "Reconnect to the IRC server";
|
||||
privs = { irc_admin=true; };
|
||||
func = function ( name, param )
|
||||
if (mt_irc.connect_ok) then
|
||||
irc.quit("Reconnecting BOT...");
|
||||
minetest.chat_send_player(name, "IRC: Reconnecting bot...");
|
||||
mt_irc.got_motd = true;
|
||||
mt_irc.connect_ok = false;
|
||||
end
|
||||
mt_irc.connect();
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("join", {
|
||||
params = "";
|
||||
description = "Join the IRC channel";
|
||||
privs = { shout=true; };
|
||||
func = function ( name, param )
|
||||
mt_irc.join(name);
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("part", {
|
||||
params = "";
|
||||
description = "Part the IRC channel";
|
||||
privs = { shout=true; };
|
||||
func = function ( name, param )
|
||||
mt_irc.part(name);
|
||||
end;
|
||||
});
|
||||
|
||||
minetest.register_chatcommand("me", {
|
||||
params = "<action>";
|
||||
description = "chat action (eg. /me orders a pizza)";
|
||||
privs = { shout=true };
|
||||
func = function(name, param)
|
||||
minetest.chat_send_all("* "..name.." "..param);
|
||||
irc.say(mt_irc.channel, "* "..name.." "..param);
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("who", {
|
||||
-- TODO: This duplicates code from !who
|
||||
params = "";
|
||||
description = "Tell who is currently on the channel";
|
||||
privs = { shout=true; };
|
||||
|
||||
minetest.register_chatcommand("irc_connect", {
|
||||
description = "Connect to the IRC server.",
|
||||
privs = {irc_admin=true},
|
||||
func = function(name, param)
|
||||
local s = "";
|
||||
for k, v in pairs(mt_irc.connected_players) do
|
||||
if (v) then
|
||||
s = s.." "..k;
|
||||
if mt_irc.connected then
|
||||
minetest.chat_send_player(name, "You are already connected to IRC.")
|
||||
return
|
||||
end
|
||||
minetest.chat_send_player(name, "IRC: Connecting...")
|
||||
mt_irc:connect()
|
||||
end
|
||||
minetest.chat_send_player(name, "Players On Channel:"..s);
|
||||
end;
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("irc_disconnect", {
|
||||
description = "Disconnect from the IRC server.",
|
||||
privs = {irc_admin=true},
|
||||
func = function(name, param)
|
||||
if not mt_irc.connected then
|
||||
minetest.chat_send_player(name, "You are not connected to IRC.")
|
||||
return
|
||||
end
|
||||
mt_irc:disconnect("Manual disconnect.")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("irc_reconnect", {
|
||||
description = "Reconnect to the IRC server.",
|
||||
privs = {irc_admin=true},
|
||||
func = function(name, param)
|
||||
if not mt_irc.connected then
|
||||
minetest.chat_send_player(name, "You are not connected to IRC.")
|
||||
return
|
||||
end
|
||||
mt_irc:disconnect("Reconnecting...")
|
||||
mt_irc:connect()
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("irc_quote", {
|
||||
params = "<command>",
|
||||
description = "Send a raw command to the IRC server.",
|
||||
privs = {irc_admin=true},
|
||||
func = function(name, param)
|
||||
if not mt_irc.connected then
|
||||
minetest.chat_send_player(name, "You are not connected to IRC.")
|
||||
return
|
||||
end
|
||||
mt_irc:queueMsg(param)
|
||||
minetest.chat_send_player(name, "Command sent!")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
local oldme = minetest.chatcommands["me"].func
|
||||
minetest.chatcommands["me"].func = function(name, param)
|
||||
oldme(name, param)
|
||||
mt_irc:say(("* %s %s"):format(name, param))
|
||||
end
|
||||
|
||||
|
@ -1,72 +1,91 @@
|
||||
-- IRC Mod for Minetest
|
||||
-- By Diego Martínez <kaeza@users.sf.net>
|
||||
--
|
||||
-- This mod allows to tie a Minetest server to an IRC channel.
|
||||
--
|
||||
-- This program is free software. It comes without any warranty, to
|
||||
-- the extent permitted by applicable law. You can redistribute it
|
||||
-- and/or modify it under the terms of the Do What The Fuck You Want
|
||||
-- To Public License, Version 2, as published by Sam Hocevar. See
|
||||
-- http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
--
|
||||
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||
-- See LICENSE.txt for details.
|
||||
|
||||
-- *************************
|
||||
-- ** BASIC USER SETTINGS **
|
||||
-- *************************
|
||||
|
||||
local config = {}
|
||||
|
||||
-------------------------
|
||||
-- BASIC USER SETTINGS --
|
||||
-------------------------
|
||||
|
||||
-- Nickname (string, default "minetest-"..<server-id>)
|
||||
-- (<server-id> is a random string of 6 hexidecimal numbers).
|
||||
config.nick = minetest.setting_get("irc.nick")
|
||||
|
||||
-- Server to connect on joinplayer (string, default "irc.freenode.net")
|
||||
mt_irc.server = minetest.setting_get("mt_irc.server") or "irc.freenode.net";
|
||||
config.server = minetest.setting_get("irc.server") or "irc.freenode.net"
|
||||
|
||||
-- Port to connect on joinplayer (number, default 6667)
|
||||
mt_irc.port = tonumber(minetest.setting_get("mt_irc.port")) or 6667;
|
||||
config.port = tonumber(minetest.setting_get("irc.port")) or 6667
|
||||
|
||||
-- NickServ password
|
||||
config.NSPass = minetest.setting_get("irc.NSPass")
|
||||
|
||||
-- SASL password (Blank to disable SASL authentication)
|
||||
config.SASLPass = minetest.setting_get("irc.SASLPass")
|
||||
|
||||
-- Channel to connect on joinplayer (string, default "##mt-irc-mod")
|
||||
mt_irc.channel = minetest.setting_get("mt_irc.channel") or "##mt-irc-mod";
|
||||
config.channel = minetest.setting_get("irc.channel") or "##mt-irc-mod"
|
||||
|
||||
-- ***********************
|
||||
-- ** ADVANCED SETTINGS **
|
||||
-- ***********************
|
||||
-- Key for the channel (string, default nil)
|
||||
config.key = minetest.setting_get("irc.key")
|
||||
|
||||
-- Time between chat updates in seconds (number, default 0.2).
|
||||
mt_irc.dtime = tonumber(minetest.setting_get("mt_irc.dtime")) or 0.2;
|
||||
|
||||
-----------------------
|
||||
-- ADVANCED SETTINGS --
|
||||
-----------------------
|
||||
|
||||
-- Server password (string, default "")
|
||||
config.password = minetest.setting_get("irc.password")
|
||||
|
||||
-- SASL username
|
||||
config.SASLUser = minetest.setting_get("irc.SASLUser") or config.nick
|
||||
|
||||
-- Enable a TLS connection, requires LuaSEC (bool, default false)
|
||||
config.secure = minetest.setting_getbool("irc.secure")
|
||||
|
||||
-- Time between chat updates in seconds (number, default 2.1). Setting this too low can cause "Excess flood" disconnects.
|
||||
config.interval = tonumber(minetest.setting_get("irc.interval")) or 2.0
|
||||
|
||||
-- Underlying socket timeout in seconds (number, default 60.0).
|
||||
mt_irc.timeout = tonumber(minetest.setting_get("mt_irc.timeout")) or 60.0;
|
||||
config.timeout = tonumber(minetest.setting_get("irc.timeout")) or 60.0
|
||||
|
||||
-- Nickname when using single conection (string, default "minetest-"..<server-id>);
|
||||
-- (<server-id> is a random string of 6 hexidecimal numbers).
|
||||
mt_irc.server_nick = minetest.setting_get("mt_irc.server_nick");
|
||||
|
||||
-- Password to use when using single connection (string, default "")
|
||||
mt_irc.password = minetest.setting_get("mt_irc.password");
|
||||
-- Prefix to use for bot commands (char, default '!')
|
||||
config.command_prefix = minetest.setting_get("irc.command_prefix") or '!'
|
||||
config.command_prefix = config.command_prefix:sub(1, 1)
|
||||
|
||||
-- The format of messages sent to IRC server (string, default "<$(name)> $(message)")
|
||||
-- See `README.txt' for the macros supported here.
|
||||
mt_irc.message_format_out = minetest.setting_get("mt_irc.message_format_out") or "<$(name)> $(message)";
|
||||
config.format_out = minetest.setting_get("irc.format_out") or "<$(name)> $(message)"
|
||||
|
||||
-- The format of messages sent to IRC server (string, default "<$(name)@IRC> $(message)")
|
||||
-- See `README.txt' for the macros supported here.
|
||||
mt_irc.message_format_in = minetest.setting_get("mt_irc.message_format_in") or "<$(name)@IRC> $(message)";
|
||||
config.format_in = minetest.setting_get("irc.format_in") or "<$(name)@IRC> $(message)"
|
||||
|
||||
-- Enable debug output (boolean, default false)
|
||||
mt_irc.debug = not minetest.setting_getbool("mt_irc.disable_debug");
|
||||
config.debug = minetest.setting_getbool("irc.debug")
|
||||
|
||||
-- Whether to automatically join the channed when player joins
|
||||
-- Whether to enable players joining and parting the channel
|
||||
config.enable_player_part = not minetest.setting_getbool("irc.disable_player_part")
|
||||
|
||||
-- Whether to automatically join the channel when player joins
|
||||
-- (boolean, default true)
|
||||
mt_irc.auto_join = not minetest.setting_getbool("mt_irc.disable_auto_join");
|
||||
config.auto_join = not minetest.setting_getbool("irc.disable_auto_join")
|
||||
|
||||
-- Whether to automatically connect to the server on mod load
|
||||
-- (boolean, default true)
|
||||
mt_irc.auto_connect = not minetest.setting_getbool("mt_irc.disable_auto_connect");
|
||||
config.auto_connect = not minetest.setting_getbool("irc.disable_auto_connect")
|
||||
|
||||
-- Set default server nick if not specified.
|
||||
if (not mt_irc.server_nick) then
|
||||
local pr = PseudoRandom(os.time());
|
||||
if not config.nick then
|
||||
local pr = PseudoRandom(os.time())
|
||||
-- Workaround for bad distribution in minetest PRNG implementation.
|
||||
local fmt = "minetest-%02X%02X%02X";
|
||||
mt_irc.server_nick = fmt:format(
|
||||
config.nick = ("MT-%02X%02X%02X"):format(
|
||||
pr:next(0, 255),
|
||||
pr:next(0, 255),
|
||||
pr:next(0, 255)
|
||||
);
|
||||
)
|
||||
end
|
||||
|
||||
mt_irc.config = config
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
|
||||
-- IRC Mod for Minetest
|
||||
-- By Diego Martínez <kaeza@users.sf.net>
|
||||
--
|
||||
-- This mod allows to tie a Minetest server to an IRC channel.
|
||||
--
|
||||
-- This program is free software. It comes without any warranty, to
|
||||
-- the extent permitted by applicable law. You can redistribute it
|
||||
-- and/or modify it under the terms of the Do What The Fuck You Want
|
||||
-- To Public License, Version 2, as published by Sam Hocevar. See
|
||||
-- http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
--
|
||||
|
||||
-- TODO
|
||||
|
||||
--[[
|
||||
local MODPATH = mt_irc.modpath;
|
||||
|
||||
local function load_friends_list ( )
|
||||
|
||||
end
|
||||
]]
|
211
src/hooks.lua
Normal file
211
src/hooks.lua
Normal file
@ -0,0 +1,211 @@
|
||||
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||
-- See LICENSE.txt for details.
|
||||
|
||||
|
||||
mt_irc.hooks = {}
|
||||
mt_irc.registered_hooks = {}
|
||||
|
||||
|
||||
function mt_irc:doHook(conn)
|
||||
for name, hook in pairs(self.registered_hooks) do
|
||||
for _, func in pairs(hook) do
|
||||
conn:hook(name, func)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc:register_hook(name, func)
|
||||
self.registered_hooks[name] = self.registered_hooks[name] or {}
|
||||
table.insert(self.registered_hooks[name], func)
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.raw(line)
|
||||
if mt_irc.config.debug then
|
||||
print("RECV: "..line)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.send(line)
|
||||
if mt_irc.config.debug then
|
||||
print("SEND: "..line)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.chat(user, channel, message)
|
||||
-- Strip bold, underline, and colors
|
||||
message = message:gsub('\2', '')
|
||||
message = message:gsub('\31', '')
|
||||
message = message:gsub('\3[0-9][0-9,]*', '')
|
||||
if channel == mt_irc.conn.nick then
|
||||
mt_irc.conn:invoke("PrivateMessage", user, message)
|
||||
else
|
||||
local c = string.char(1)
|
||||
local found, _, action = message:find(("^%sACTION ([^%s]*)%s$"):format(c, c, c))
|
||||
if found then
|
||||
mt_irc.conn:invoke("OnChannelAction", user, channel, action)
|
||||
else
|
||||
mt_irc.conn:invoke("OnChannelChat", user, channel, message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.channelChat(user, channel, message)
|
||||
local t = {
|
||||
access=user.access,
|
||||
name=user.nick,
|
||||
message=message,
|
||||
server=mt_irc.conn.host,
|
||||
port=mt_irc.conn.port,
|
||||
channel=channel
|
||||
}
|
||||
local text = mt_irc.config.format_in:expandvars(t)
|
||||
mt_irc:sendLocal(text)
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.pm(user, message)
|
||||
local player_to
|
||||
local msg
|
||||
if message:sub(1, 1) == "@" then
|
||||
local found, _, player_to, message = message:find("^.([^%s]+)%s(.+)$")
|
||||
if not mt_irc.joined_players[player_to] then
|
||||
mt_irc:say(user.nick, "User '"..player_to.."' has parted.")
|
||||
return
|
||||
elseif not minetest.get_player_by_name(player_to) then
|
||||
mt_irc:say(user.nick, "User '"..player_to.."' is not in the game.")
|
||||
return
|
||||
end
|
||||
local t = {
|
||||
name=user.nick,
|
||||
message=message,
|
||||
server=mt_irc.server,
|
||||
port=mt_irc.port,
|
||||
channel=mt_irc.channel
|
||||
}
|
||||
local text = mt_irc.config.format_in:expandvars(t)
|
||||
minetest.chat_send_player(player_to, "PM: "..text, false)
|
||||
mt_irc:say(user.nick, "Message sent!")
|
||||
elseif message:sub(1, 1) == "!" then
|
||||
mt_irc:bot_command(user, message:sub(2))
|
||||
return
|
||||
else
|
||||
mt_irc:say(user.nick, "Invalid command. Use '"
|
||||
..mt_irc.config.command_prefix
|
||||
.."list' to see possible commands.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.kick(channel, target, prefix, reason)
|
||||
if target == mt_irc.conn.nick then
|
||||
minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".")
|
||||
mt_irc:disconnect("Kicked")
|
||||
else
|
||||
mt_irc:sendLocal(("-!- %s was kicked from %s by %s [%s]")
|
||||
:format(target, channel, prefix.nick, reason))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.notice(user, target, message)
|
||||
if not user.nick then return end --Server NOTICEs
|
||||
if target == mt_irc.conn.nick then return end
|
||||
mt_irc:sendLocal("--"..user.nick.."@IRC-- "..message)
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.mode(user, target, modes, ...)
|
||||
local by = ""
|
||||
if user.nick then
|
||||
by = " by "..user.nick
|
||||
end
|
||||
local options = ""
|
||||
for _, option in pairs({...}) do
|
||||
options = options.." "..option
|
||||
end
|
||||
minetest.chat_send_all(("-!- mode/%s [%s%s]%s")
|
||||
:format(target, modes, options, by))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.nick(user, newNick)
|
||||
mt_irc:sendLocal(("-!- %s is now known as %s")
|
||||
:format(user.nick, newNick))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.join(user, channel)
|
||||
mt_irc:sendLocal(("-!- %s joined %s")
|
||||
:format(user.nick, channel))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.part(user, channel, reason)
|
||||
reason = reason or ""
|
||||
mt_irc:sendLocal(("-!- %s has left %s [%s]")
|
||||
:format(user.nick, channel, reason))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.quit(user, reason)
|
||||
mt_irc:sendLocal(("-!- %s has quit [%s]")
|
||||
:format(user.nick, reason))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.action(user, channel, message)
|
||||
mt_irc:sendLocal(("* %s@IRC %s")
|
||||
:format(user.nick, message))
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.disconnect(message, isError)
|
||||
mt_irc.connected = false
|
||||
if isError then
|
||||
minetest.log("error", "IRC: Error: Disconnected, reconnecting in one minute.")
|
||||
minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.")
|
||||
minetest.after(60, mt_irc.connect)
|
||||
else
|
||||
minetest.log("action", "IRC: Disconnected.")
|
||||
minetest.chat_send_all("IRC: Disconnected.")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc.hooks.preregister(conn)
|
||||
if not (mt_irc.config.SASLUser and mt_irc.config.SASLPass) then return end
|
||||
local authString = mt_irc.b64e(
|
||||
("%s\x00%s\x00%s"):format(
|
||||
mt_irc.config.SASLUser,
|
||||
mt_irc.config.SASLUser,
|
||||
mt_irc.config.SASLPass)
|
||||
)
|
||||
conn:send("CAP REQ sasl")
|
||||
conn:send("AUTHENTICATE PLAIN")
|
||||
conn:send("AUTHENTICATE "..authString)
|
||||
--LuaIRC will send CAP END
|
||||
end
|
||||
|
||||
|
||||
mt_irc:register_hook("PreRegister", mt_irc.hooks.preregister)
|
||||
mt_irc:register_hook("OnRaw", mt_irc.hooks.raw)
|
||||
mt_irc:register_hook("OnSend", mt_irc.hooks.send)
|
||||
mt_irc:register_hook("OnChat", mt_irc.hooks.chat)
|
||||
mt_irc:register_hook("OnPart", mt_irc.hooks.part)
|
||||
mt_irc:register_hook("OnKick", mt_irc.hooks.kick)
|
||||
mt_irc:register_hook("OnJoin", mt_irc.hooks.join)
|
||||
mt_irc:register_hook("OnQuit", mt_irc.hooks.quit)
|
||||
mt_irc:register_hook("NickChange", mt_irc.hooks.nick)
|
||||
mt_irc:register_hook("OnChannelAction", mt_irc.hooks.action)
|
||||
mt_irc:register_hook("PrivateMessage", mt_irc.hooks.pm)
|
||||
mt_irc:register_hook("OnNotice", mt_irc.hooks.notice)
|
||||
mt_irc:register_hook("OnChannelChat", mt_irc.hooks.channelChat)
|
||||
mt_irc:register_hook("OnModeChange", mt_irc.hooks.mode)
|
||||
mt_irc:register_hook("OnDisconnect", mt_irc.hooks.disconnect)
|
||||
|
213
src/init.lua
213
src/init.lua
@ -1,127 +1,144 @@
|
||||
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||
-- See LICENSE.txt for details.
|
||||
|
||||
-- IRC Mod for Minetest
|
||||
-- By Diego Martínez <kaeza@users.sf.net>
|
||||
--
|
||||
-- This mod allows to tie a Minetest server to an IRC channel.
|
||||
--
|
||||
-- This program is free software. It comes without any warranty, to
|
||||
-- the extent permitted by applicable law. You can redistribute it
|
||||
-- and/or modify it under the terms of the Do What The Fuck You Want
|
||||
-- To Public License, Version 2, as published by Sam Hocevar. See
|
||||
-- http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
--
|
||||
|
||||
local MODPATH = minetest.get_modpath("irc");
|
||||
mt_irc = {
|
||||
connected = false,
|
||||
cur_time = 0,
|
||||
message_buffer = {},
|
||||
recent_message_count = 0,
|
||||
joined_players = {},
|
||||
modpath = minetest.get_modpath("irc")
|
||||
}
|
||||
|
||||
mt_irc = { };
|
||||
-- To find LuaIRC and LuaSocket
|
||||
package.path = mt_irc.modpath.."/?/init.lua;"
|
||||
..mt_irc.modpath.."/irc/?.lua;"
|
||||
..mt_irc.modpath.."/?.lua;"
|
||||
..package.path
|
||||
package.cpath = mt_irc.modpath.."/lib?.so;"
|
||||
..mt_irc.modpath.."/?.dll;"
|
||||
..package.cpath
|
||||
|
||||
dofile(MODPATH.."/config.lua");
|
||||
local irc = require('irc')
|
||||
|
||||
mt_irc.cur_time = 0;
|
||||
mt_irc.buffered_messages = { };
|
||||
mt_irc.connected_players = { };
|
||||
mt_irc.modpath = MODPATH;
|
||||
|
||||
package.path = MODPATH.."/?.lua;"..package.path;
|
||||
package.cpath = MODPATH.."/lib?.so;"..MODPATH.."/?.dll;"..package.cpath;
|
||||
|
||||
local irc = require 'irc';
|
||||
|
||||
irc.DEBUG = ((mt_irc.debug and true) or false);
|
||||
dofile(mt_irc.modpath.."/config.lua")
|
||||
dofile(mt_irc.modpath.."/messages.lua")
|
||||
dofile(mt_irc.modpath.."/hooks.lua")
|
||||
dofile(mt_irc.modpath.."/callback.lua")
|
||||
dofile(mt_irc.modpath.."/chatcmds.lua")
|
||||
dofile(mt_irc.modpath.."/botcmds.lua")
|
||||
dofile(mt_irc.modpath.."/util.lua")
|
||||
if mt_irc.config.enable_player_part then
|
||||
dofile(mt_irc.modpath.."/player_part.lua")
|
||||
else
|
||||
setmetatable(mt_irc.joined_players, {__index = function(index) return true end})
|
||||
end
|
||||
|
||||
minetest.register_privilege("irc_admin", {
|
||||
description = "Allow IRC administrative tasks to be performed.";
|
||||
give_to_singleplayer = true;
|
||||
});
|
||||
description = "Allow IRC administrative tasks to be performed.",
|
||||
give_to_singleplayer = true
|
||||
})
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if (not mt_irc.connect_ok) then return end
|
||||
mt_irc.cur_time = mt_irc.cur_time + dtime
|
||||
if (mt_irc.cur_time >= mt_irc.dtime) then
|
||||
if (mt_irc.buffered_messages) then
|
||||
for _, msg in ipairs(mt_irc.buffered_messages) do
|
||||
local t = {
|
||||
name=(msg.name or "<BUG:no one is saying this>"),
|
||||
message=(msg.message or "<BUG:there is no message>")
|
||||
}
|
||||
local text = mt_irc.message_format_out:expandvars(t)
|
||||
irc.say(mt_irc.channel, text)
|
||||
|
||||
minetest.register_globalstep(function(dtime) return mt_irc:step(dtime) end)
|
||||
|
||||
function mt_irc:step(dtime)
|
||||
if not self.connected then return end
|
||||
|
||||
-- Tick down the recent message count
|
||||
self.cur_time = self.cur_time + dtime
|
||||
if self.cur_time >= self.config.interval then
|
||||
if self.recent_message_count > 0 then
|
||||
self.recent_message_count = self.recent_message_count - 1
|
||||
end
|
||||
mt_irc.buffered_messages = nil
|
||||
self.cur_time = self.cur_time - self.config.interval
|
||||
end
|
||||
irc.poll()
|
||||
mt_irc.cur_time = mt_irc.cur_time - mt_irc.dtime
|
||||
|
||||
-- Hooks will manage incoming messages and errors
|
||||
if not pcall(function() mt_irc.conn:think() end) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Send messages in the buffer
|
||||
if #self.message_buffer > 10 then
|
||||
minetest.log("error", "IRC: Message buffer overflow, clearing.")
|
||||
self.message_buffer = {}
|
||||
elseif #self.message_buffer > 0 then
|
||||
for i=1, #self.message_buffer do
|
||||
if self.recent_message_count > 4 then break end
|
||||
self.recent_message_count = self.recent_message_count + 1
|
||||
local msg = table.remove(self.message_buffer, 1) --Pop the first message
|
||||
self:send(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mt_irc:connect()
|
||||
if self.connected then
|
||||
minetest.log("error", "IRC: Ignoring attempt to connect when already connected.")
|
||||
return
|
||||
end
|
||||
self.conn = irc.new({
|
||||
nick = self.config.nick,
|
||||
username = "Minetest",
|
||||
realname = "Minetest",
|
||||
})
|
||||
self:doHook(self.conn)
|
||||
good, message = pcall(function()
|
||||
mt_irc.conn:connect({
|
||||
host = mt_irc.config.server,
|
||||
port = mt_irc.config.port,
|
||||
pass = mt_irc.config.password,
|
||||
timeout = mt_irc.config.timeout,
|
||||
secure = mt_irc.config.secure
|
||||
})
|
||||
end)
|
||||
|
||||
mt_irc.part = function ( name )
|
||||
if (not mt_irc.connected_players[name]) then
|
||||
minetest.chat_send_player(name, "IRC: You are not in the channel.");
|
||||
return;
|
||||
end
|
||||
mt_irc.connected_players[name] = nil;
|
||||
minetest.chat_send_player(name, "IRC: You are now out of the channel.");
|
||||
if not good then
|
||||
minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in ten minutes...")
|
||||
:format(self.config.server, message))
|
||||
minetest.after(600, function() mt_irc:connect() end)
|
||||
return
|
||||
end
|
||||
|
||||
mt_irc.join = function ( name )
|
||||
if (mt_irc.connected_players[name]) then
|
||||
minetest.chat_send_player(name, "IRC: You are already in the channel.");
|
||||
return;
|
||||
end
|
||||
mt_irc.connected_players[name] = true;
|
||||
minetest.chat_send_player(name, "IRC: You are now in the channel.");
|
||||
if self.config.NSPass then
|
||||
self:say("NickServ", "IDENTIFY "..self.config.NSPass)
|
||||
end
|
||||
|
||||
mt_irc.connect = function ( )
|
||||
mt_irc.connect_ok = irc.connect({
|
||||
network = mt_irc.server;
|
||||
port = mt_irc.port;
|
||||
nick = mt_irc.server_nick;
|
||||
pass = mt_irc.password;
|
||||
timeout = mt_irc.timeout;
|
||||
channel = mt_irc.channel;
|
||||
});
|
||||
if (not mt_irc.connect_ok) then
|
||||
local s = "DEBUG: irc.connect failed";
|
||||
minetest.debug(s);
|
||||
minetest.chat_send_all(s);
|
||||
return;
|
||||
self.conn:join(self.config.channel, self.config.key)
|
||||
self.connected = true
|
||||
minetest.log("action", "IRC: Connected!")
|
||||
minetest.chat_send_all("IRC: Connected!")
|
||||
end
|
||||
while (not mt_irc.got_motd) do
|
||||
irc.poll();
|
||||
|
||||
|
||||
function mt_irc:disconnect(message)
|
||||
if self.connected then
|
||||
--The OnDisconnect hook will clear self.connected and print a disconnect message
|
||||
self.conn:disconnect(message)
|
||||
end
|
||||
end
|
||||
|
||||
mt_irc.say = function ( to, msg )
|
||||
if (not msg) then
|
||||
msg = to;
|
||||
to = mt_irc.channel;
|
||||
|
||||
function mt_irc:say(to, message)
|
||||
if not message then
|
||||
message = to
|
||||
to = self.config.channel
|
||||
end
|
||||
to = to or mt_irc.channel;
|
||||
msg = msg or "";
|
||||
local msg2 = mt_irc._callback("msg_out", true, to, msg);
|
||||
if ((type(msg2) == "boolean") and (not msg2)) then
|
||||
return;
|
||||
elseif (msg2 ~= nil) then
|
||||
msg = tostring(msg);
|
||||
end
|
||||
irc.say(to, msg);
|
||||
to = to or self.config.channel
|
||||
|
||||
self:queueMsg(self.msgs.privmsg(to, message))
|
||||
end
|
||||
|
||||
mt_irc.irc = irc;
|
||||
|
||||
-- Misc helpers
|
||||
|
||||
-- Requested by Exio
|
||||
string.expandvars = function ( s, vars )
|
||||
return s:gsub("%$%(([^)]+)%)", vars);
|
||||
function mt_irc:send(line)
|
||||
self.conn:send(line)
|
||||
end
|
||||
|
||||
dofile(MODPATH.."/callback.lua");
|
||||
dofile(MODPATH.."/chatcmds.lua");
|
||||
dofile(MODPATH.."/botcmds.lua");
|
||||
dofile(MODPATH.."/friends.lua");
|
||||
|
||||
if (mt_irc.auto_connect) then
|
||||
mt_irc.connect()
|
||||
if mt_irc.config.auto_connect then
|
||||
mt_irc:connect()
|
||||
end
|
||||
|
||||
|
1023
src/luairc/irc.lua
1023
src/luairc/irc.lua
File diff suppressed because it is too large
Load Diff
@ -1,475 +0,0 @@
|
||||
---
|
||||
-- Implementation of the Channel class
|
||||
|
||||
-- initialization {{{
|
||||
local base = _G
|
||||
local irc = require 'irc'
|
||||
local misc = require 'irc.misc'
|
||||
local socket = require 'socket'
|
||||
local table = require 'table'
|
||||
-- }}}
|
||||
|
||||
---
|
||||
-- This module implements a channel object representing a single channel we
|
||||
-- have joined.
|
||||
module 'irc.channel'
|
||||
|
||||
-- object metatable {{{
|
||||
-- TODO: this <br /> shouldn't be necessary - bug in luadoc
|
||||
---
|
||||
-- An object of the Channel class represents a single joined channel. It has
|
||||
-- several table fields, and can be used in string contexts (returning the
|
||||
-- channel name).<br />
|
||||
-- @class table
|
||||
-- @name Channel
|
||||
-- @field name Name of the channel (read only)
|
||||
-- @field topic Channel topic, if set (read/write, writing to this sends a
|
||||
-- topic change request to the server for this channel)
|
||||
-- @field chanmode Channel mode (public/private/secret) (read only)
|
||||
-- @field members Array of all members of this channel
|
||||
local mt = {
|
||||
-- __index() {{{
|
||||
__index = function(self, key)
|
||||
if key == "name" then
|
||||
return self._name
|
||||
elseif key == "topic" then
|
||||
return self._topic
|
||||
elseif key == "chanmode" then
|
||||
return self._chanmode
|
||||
else
|
||||
return _M[key]
|
||||
end
|
||||
end,
|
||||
-- }}}
|
||||
-- __newindex() {{{
|
||||
__newindex = function(self, key, value)
|
||||
if key == "name" then
|
||||
return
|
||||
elseif key == "topic" then
|
||||
irc.send("TOPIC", self._name, value)
|
||||
elseif key == "chanmode" then
|
||||
return
|
||||
else
|
||||
base.rawset(self, key, value)
|
||||
end
|
||||
end,
|
||||
-- }}}
|
||||
-- __concat() {{{
|
||||
__concat = function(first, second)
|
||||
local first_str, second_str
|
||||
|
||||
if base.type(first) == "table" then
|
||||
first_str = first._name
|
||||
else
|
||||
first_str = first
|
||||
end
|
||||
if base.type(second) == "table" then
|
||||
second_str = second._name
|
||||
else
|
||||
second_str = second
|
||||
end
|
||||
|
||||
return first_str .. second_str
|
||||
end,
|
||||
-- }}}
|
||||
-- __tostring() {{{
|
||||
__tostring = function(self)
|
||||
return self._name
|
||||
end
|
||||
-- }}}
|
||||
}
|
||||
-- }}}
|
||||
|
||||
-- private methods {{{
|
||||
-- set_basic_mode {{{
|
||||
--
|
||||
-- Sets a no-arg mode on a channel.
|
||||
-- @name chan:set_basic_mode
|
||||
-- @param self Channel object
|
||||
-- @param set True to set the mode, false to unset it
|
||||
-- @param letter Letter of the mode
|
||||
local function set_basic_mode(self, set, letter)
|
||||
if set then
|
||||
irc.send("MODE", self.name, "+" .. letter)
|
||||
else
|
||||
irc.send("MODE", self.name, "-" .. letter)
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- internal methods {{{
|
||||
-- TODO: is there a better way to do this? also, storing op/voice as initial
|
||||
-- substrings of the username is just ugly
|
||||
-- _add_user {{{
|
||||
--
|
||||
-- Add a user to the channel's internal user list.
|
||||
-- @param self Channel object
|
||||
-- @param user Nick of the user to add
|
||||
-- @param mode Mode (op/voice) of the user, in symbolic form (@/+)
|
||||
function _add_user(self, user, mode)
|
||||
mode = mode or ''
|
||||
self._members[user] = mode .. user
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _remove_user {{{
|
||||
--
|
||||
-- Remove a user from the channel's internal user list.
|
||||
-- @param self Channel object
|
||||
-- @param user Nick of the user to remove
|
||||
function _remove_user(self, user)
|
||||
self._members[user] = nil
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _change_status {{{
|
||||
--
|
||||
-- Change the op/voice status of a user in the channel's internal user list.
|
||||
-- @param self Channel object
|
||||
-- @param user Nick of the user to affect
|
||||
-- @param on True if the mode is being set, false if it's being unset
|
||||
-- @param mode 'o' for op, 'v' for voice
|
||||
function _change_status(self, user, on, mode)
|
||||
if on then
|
||||
if mode == 'o' then
|
||||
self._members[user] = '@' .. user
|
||||
elseif mode == 'v' then
|
||||
self._members[user] = '+' .. user
|
||||
end
|
||||
else
|
||||
if (mode == 'o' and self._members[user]:sub(1, 1) == '@') or
|
||||
(mode == 'v' and self._members[user]:sub(1, 1) == '+') then
|
||||
self._members[user] = user
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _change_nick {{{
|
||||
--
|
||||
-- Change the nick of a user in the channel's internal user list.
|
||||
-- @param self Channel object
|
||||
-- @param old_nick User's old nick
|
||||
-- @param new_nick User's new nick
|
||||
function _change_nick(self, old_nick, new_nick)
|
||||
for member in self:each_member() do
|
||||
local member_nick = member:gsub('@+', '')
|
||||
if member_nick == old_nick then
|
||||
local mode = self._members[old_nick]:sub(1, 1)
|
||||
if mode ~= '@' and mode ~= '+' then mode = "" end
|
||||
self._members[old_nick] = nil
|
||||
self._members[new_nick] = mode .. new_nick
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- constructor {{{
|
||||
---
|
||||
-- Creates a new Channel object.
|
||||
-- @param chan Name of the new channel
|
||||
-- @return The new channel instance
|
||||
function new(chan)
|
||||
return base.setmetatable({_name = chan, _topic = {}, _chanmode = "",
|
||||
_members = {}}, mt)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- public methods {{{
|
||||
-- iterators {{{
|
||||
-- each_op {{{
|
||||
---
|
||||
-- Iterator over the ops in the channel
|
||||
-- @param self Channel object
|
||||
function each_op(self)
|
||||
return function(state, arg)
|
||||
return misc._value_iter(state, arg,
|
||||
function(v)
|
||||
return v:sub(1, 1) == "@"
|
||||
end)
|
||||
end,
|
||||
self._members,
|
||||
nil
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- each_voice {{{
|
||||
---
|
||||
-- Iterator over the voiced users in the channel
|
||||
-- @param self Channel object
|
||||
function each_voice(self)
|
||||
return function(state, arg)
|
||||
return misc._value_iter(state, arg,
|
||||
function(v)
|
||||
return v:sub(1, 1) == "+"
|
||||
end)
|
||||
end,
|
||||
self._members,
|
||||
nil
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- each_user {{{
|
||||
---
|
||||
-- Iterator over the normal users in the channel
|
||||
-- @param self Channel object
|
||||
function each_user(self)
|
||||
return function(state, arg)
|
||||
return misc._value_iter(state, arg,
|
||||
function(v)
|
||||
return v:sub(1, 1) ~= "@" and
|
||||
v:sub(1, 1) ~= "+"
|
||||
end)
|
||||
end,
|
||||
self._members,
|
||||
nil
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- each_member {{{
|
||||
---
|
||||
-- Iterator over all users in the channel
|
||||
-- @param self Channel object
|
||||
function each_member(self)
|
||||
return misc._value_iter, self._members, nil
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- return tables of users {{{
|
||||
-- ops {{{
|
||||
---
|
||||
-- Gets an array of all the ops in the channel.
|
||||
-- @param self Channel object
|
||||
-- @return Array of channel ops
|
||||
function ops(self)
|
||||
local ret = {}
|
||||
for nick in self:each_op() do
|
||||
table.insert(ret, nick)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- voices {{{
|
||||
---
|
||||
-- Gets an array of all the voiced users in the channel.
|
||||
-- @param self Channel object
|
||||
-- @return Array of channel voiced users
|
||||
function voices(self)
|
||||
local ret = {}
|
||||
for nick in self:each_voice() do
|
||||
table.insert(ret, nick)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- users {{{
|
||||
---
|
||||
-- Gets an array of all the normal users in the channel.
|
||||
-- @param self Channel object
|
||||
-- @return Array of channel normal users
|
||||
function users(self)
|
||||
local ret = {}
|
||||
for nick in self:each_user() do
|
||||
table.insert(ret, nick)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- members {{{
|
||||
---
|
||||
-- Gets an array of all the users in the channel.
|
||||
-- @param self Channel object
|
||||
-- @return Array of channel users
|
||||
function members(self)
|
||||
local ret = {}
|
||||
-- not just returning self._members, since the return value shouldn't be
|
||||
-- modifiable
|
||||
for nick in self:each_member() do
|
||||
table.insert(ret, nick)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- setting modes {{{
|
||||
-- ban {{{
|
||||
-- TODO: hmmm, this probably needs an appropriate mask, rather than a nick
|
||||
---
|
||||
-- Ban a user from a channel.
|
||||
-- @param self Channel object
|
||||
-- @param name User to ban
|
||||
function ban(self, name)
|
||||
irc.send("MODE", self.name, "+b", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- unban {{{
|
||||
-- TODO: same here
|
||||
---
|
||||
-- Remove a ban on a user.
|
||||
-- @param self Channel object
|
||||
-- @param name User to unban
|
||||
function unban(self, name)
|
||||
irc.send("MODE", self.name, "-b", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- voice {{{
|
||||
---
|
||||
-- Give a user voice on a channel.
|
||||
-- @param self Channel object
|
||||
-- @param name User to give voice to
|
||||
function voice(self, name)
|
||||
irc.send("MODE", self.name, "+v", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- devoice {{{
|
||||
---
|
||||
-- Remove voice from a user.
|
||||
-- @param self Channel object
|
||||
-- @param name User to remove voice from
|
||||
function devoice(self, name)
|
||||
irc.send("MODE", self.name, "-v", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- op {{{
|
||||
---
|
||||
-- Give a user ops on a channel.
|
||||
-- @param self Channel object
|
||||
-- @param name User to op
|
||||
function op(self, name)
|
||||
irc.send("MODE", self.name, "+o", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- deop {{{
|
||||
---
|
||||
-- Remove ops from a user.
|
||||
-- @param self Channel object
|
||||
-- @param name User to remove ops from
|
||||
function deop(self, name)
|
||||
irc.send("MODE", self.name, "-o", name)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_limit {{{
|
||||
---
|
||||
-- Set a channel limit.
|
||||
-- @param self Channel object
|
||||
-- @param new_limit New value for the channel limit (optional; limit is unset
|
||||
-- if this argument isn't passed)
|
||||
function set_limit(self, new_limit)
|
||||
if new_limit then
|
||||
irc.send("MODE", self.name, "+l", new_limit)
|
||||
else
|
||||
irc.send("MODE", self.name, "-l")
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_key {{{
|
||||
---
|
||||
-- Set a channel password.
|
||||
-- @param self Channel object
|
||||
-- @param key New channel password (optional; password is unset if this
|
||||
-- argument isn't passed)
|
||||
function set_key(self, key)
|
||||
if key then
|
||||
irc.send("MODE", self.name, "+k", key)
|
||||
else
|
||||
irc.send("MODE", self.name, "-k")
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_private {{{
|
||||
---
|
||||
-- Set the private state of a channel.
|
||||
-- @param self Channel object
|
||||
-- @param set True to set the channel as private, false to unset it
|
||||
function set_private(self, set)
|
||||
set_basic_mode(self, set, "p")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_secret {{{
|
||||
---
|
||||
-- Set the secret state of a channel.
|
||||
-- @param self Channel object
|
||||
-- @param set True to set the channel as secret, false to unset it
|
||||
function set_secret(self, set)
|
||||
set_basic_mode(self, set, "s")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_invite_only {{{
|
||||
---
|
||||
-- Set whether joining the channel requires an invite.
|
||||
-- @param self Channel object
|
||||
-- @param set True to set the channel invite only, false to unset it
|
||||
function set_invite_only(self, set)
|
||||
set_basic_mode(self, set, "i")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_topic_lock {{{
|
||||
---
|
||||
-- If true, the topic can only be changed by an op.
|
||||
-- @param self Channel object
|
||||
-- @param set True to lock the topic, false to unlock it
|
||||
function set_topic_lock(self, set)
|
||||
set_basic_mode(self, set, "t")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_no_outside_messages {{{
|
||||
---
|
||||
-- If true, users must be in the channel to send messages to it.
|
||||
-- @param self Channel object
|
||||
-- @param set True to require users to be in the channel to send messages to
|
||||
-- it, false to remove this restriction
|
||||
function set_no_outside_messages(self, set)
|
||||
set_basic_mode(self, set, "n")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set moderated {{{
|
||||
---
|
||||
-- Set whether voice is required to speak.
|
||||
-- @param self Channel object
|
||||
-- @param set True to set the channel as moderated, false to unset it
|
||||
function set_moderated(self, set)
|
||||
set_basic_mode(self, set, "m")
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- accessors {{{
|
||||
-- contains {{{
|
||||
---
|
||||
-- Test if a user is in the channel.
|
||||
-- @param self Channel object
|
||||
-- @param nick Nick to search for
|
||||
-- @return True if the nick is in the channel, false otherwise
|
||||
function contains(self, nick)
|
||||
for member in self:each_member() do
|
||||
local member_nick = member:gsub('@+', '')
|
||||
if member_nick == nick then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
-- }}}
|
@ -1,191 +0,0 @@
|
||||
---
|
||||
-- This module holds various constants used by the IRC protocol.
|
||||
module "irc.constants"
|
||||
|
||||
-- protocol constants {{{
|
||||
IRC_MAX_MSG = 512
|
||||
-- }}}
|
||||
|
||||
-- server replies {{{
|
||||
replies = {
|
||||
-- Command responses {{{
|
||||
[001] = "RPL_WELCOME",
|
||||
[002] = "RPL_YOURHOST",
|
||||
[003] = "RPL_CREATED",
|
||||
[004] = "RPL_MYINFO",
|
||||
[005] = "RPL_BOUNCE",
|
||||
[302] = "RPL_USERHOST",
|
||||
[303] = "RPL_ISON",
|
||||
[301] = "RPL_AWAY",
|
||||
[305] = "RPL_UNAWAY",
|
||||
[306] = "RPL_NOWAWAY",
|
||||
[311] = "RPL_WHOISUSER",
|
||||
[312] = "RPL_WHOISSERVER",
|
||||
[313] = "RPL_WHOISOPERATOR",
|
||||
[317] = "RPL_WHOISIDLE",
|
||||
[318] = "RPL_ENDOFWHOIS",
|
||||
[319] = "RPL_WHOISCHANNELS",
|
||||
[314] = "RPL_WHOWASUSER",
|
||||
[369] = "RPL_ENDOFWHOWAS",
|
||||
[321] = "RPL_LISTSTART",
|
||||
[322] = "RPL_LIST",
|
||||
[323] = "RPL_LISTEND",
|
||||
[325] = "RPL_UNIQOPIS",
|
||||
[324] = "RPL_CHANNELMODEIS",
|
||||
[331] = "RPL_NOTOPIC",
|
||||
[332] = "RPL_TOPIC",
|
||||
[341] = "RPL_INVITING",
|
||||
[342] = "RPL_SUMMONING",
|
||||
[346] = "RPL_INVITELIST",
|
||||
[347] = "RPL_ENDOFINVITELIST",
|
||||
[348] = "RPL_EXCEPTLIST",
|
||||
[349] = "RPL_ENDOFEXCEPTLIST",
|
||||
[351] = "RPL_VERSION",
|
||||
[352] = "RPL_WHOREPLY",
|
||||
[315] = "RPL_ENDOFWHO",
|
||||
[353] = "RPL_NAMREPLY",
|
||||
[366] = "RPL_ENDOFNAMES",
|
||||
[364] = "RPL_LINKS",
|
||||
[365] = "RPL_ENDOFLINKS",
|
||||
[367] = "RPL_BANLIST",
|
||||
[368] = "RPL_ENDOFBANLIST",
|
||||
[371] = "RPL_INFO",
|
||||
[374] = "RPL_ENDOFINFO",
|
||||
[375] = "RPL_MOTDSTART",
|
||||
[372] = "RPL_MOTD",
|
||||
[376] = "RPL_ENDOFMOTD",
|
||||
[381] = "RPL_YOUREOPER",
|
||||
[382] = "RPL_REHASHING",
|
||||
[383] = "RPL_YOURESERVICE",
|
||||
[391] = "RPL_TIME",
|
||||
[392] = "RPL_USERSSTART",
|
||||
[393] = "RPL_USERS",
|
||||
[394] = "RPL_ENDOFUSERS",
|
||||
[395] = "RPL_NOUSERS",
|
||||
[200] = "RPL_TRACELINK",
|
||||
[201] = "RPL_TRACECONNECTING",
|
||||
[202] = "RPL_TRACEHANDSHAKE",
|
||||
[203] = "RPL_TRACEUNKNOWN",
|
||||
[204] = "RPL_TRACEOPERATOR",
|
||||
[205] = "RPL_TRACEUSER",
|
||||
[206] = "RPL_TRACESERVER",
|
||||
[207] = "RPL_TRACESERVICE",
|
||||
[208] = "RPL_TRACENEWTYPE",
|
||||
[209] = "RPL_TRACECLASS",
|
||||
[210] = "RPL_TRACERECONNECT",
|
||||
[261] = "RPL_TRACELOG",
|
||||
[262] = "RPL_TRACEEND",
|
||||
[211] = "RPL_STATSLINKINFO",
|
||||
[212] = "RPL_STATSCOMMANDS",
|
||||
[219] = "RPL_ENDOFSTATS",
|
||||
[242] = "RPL_STATSUPTIME",
|
||||
[243] = "RPL_STATSOLINE",
|
||||
[221] = "RPL_UMODEIS",
|
||||
[234] = "RPL_SERVLIST",
|
||||
[235] = "RPL_SERVLISTEND",
|
||||
[221] = "RPL_UMODEIS",
|
||||
[251] = "RPL_LUSERCLIENT",
|
||||
[252] = "RPL_LUSEROP",
|
||||
[253] = "RPL_LUSERUNKNOWN",
|
||||
[254] = "RPL_LUSERCHANNELS",
|
||||
[255] = "RPL_LUSERME",
|
||||
[256] = "RPL_ADMINME",
|
||||
[257] = "RPL_ADMINLOC1",
|
||||
[258] = "RPL_ADMINLOC2",
|
||||
[259] = "RPL_ADMINEMAIL",
|
||||
[263] = "RPL_TRYAGAIN",
|
||||
-- }}}
|
||||
-- Error codes {{{
|
||||
[401] = "ERR_NOSUCHNICK", -- No such nick/channel
|
||||
[402] = "ERR_NOSUCHSERVER", -- No such server
|
||||
[403] = "ERR_NOSUCHCHANNEL", -- No such channel
|
||||
[404] = "ERR_CANNOTSENDTOCHAN", -- Cannot send to channel
|
||||
[405] = "ERR_TOOMANYCHANNELS", -- You have joined too many channels
|
||||
[406] = "ERR_WASNOSUCHNICK", -- There was no such nickname
|
||||
[407] = "ERR_TOOMANYTARGETS", -- Duplicate recipients. No message delivered
|
||||
[408] = "ERR_NOSUCHSERVICE", -- No such service
|
||||
[409] = "ERR_NOORIGIN", -- No origin specified
|
||||
[411] = "ERR_NORECIPIENT", -- No recipient given
|
||||
[412] = "ERR_NOTEXTTOSEND", -- No text to send
|
||||
[413] = "ERR_NOTOPLEVEL", -- No toplevel domain specified
|
||||
[414] = "ERR_WILDTOPLEVEL", -- Wildcard in toplevel domain
|
||||
[415] = "ERR_BADMASK", -- Bad server/host mask
|
||||
[421] = "ERR_UNKNOWNCOMMAND", -- Unknown command
|
||||
[422] = "ERR_NOMOTD", -- MOTD file is missing
|
||||
[423] = "ERR_NOADMININFO", -- No administrative info available
|
||||
[424] = "ERR_FILEERROR", -- File error
|
||||
[431] = "ERR_NONICKNAMEGIVEN", -- No nickname given
|
||||
[432] = "ERR_ERRONEUSNICKNAME", -- Erroneus nickname
|
||||
[433] = "ERR_NICKNAMEINUSE", -- Nickname is already in use
|
||||
[436] = "ERR_NICKCOLLISION", -- Nickname collision KILL
|
||||
[437] = "ERR_UNAVAILRESOURCE", -- Nick/channel is temporarily unavailable
|
||||
[441] = "ERR_USERNOTINCHANNEL", -- They aren't on that channel
|
||||
[442] = "ERR_NOTONCHANNEL", -- You're not on that channel
|
||||
[443] = "ERR_USERONCHANNEL", -- User is already on channel
|
||||
[444] = "ERR_NOLOGIN", -- User not logged in
|
||||
[445] = "ERR_SUMMONDISABLED", -- SUMMON has been disabled
|
||||
[446] = "ERR_USERSDISABLED", -- USERS has been disabled
|
||||
[451] = "ERR_NOTREGISTERED", -- You have not registered
|
||||
[461] = "ERR_NEEDMOREPARAMS", -- Not enough parameters
|
||||
[462] = "ERR_ALREADYREGISTERED", -- You may not reregister
|
||||
[463] = "ERR_NOPERMFORHOST", -- Your host isn't among the privileged
|
||||
[464] = "ERR_PASSWDMISMATCH", -- Password incorrect
|
||||
[465] = "ERR_YOUREBANNEDCREEP", -- You are banned from this server
|
||||
[466] = "ERR_YOUWILLBEBANNED",
|
||||
[467] = "ERR_KEYSET", -- Channel key already set
|
||||
[471] = "ERR_CHANNELISFULL", -- Cannot join channel (+l)
|
||||
[472] = "ERR_UNKNOWNMODE", -- Unknown mode char
|
||||
[473] = "ERR_INVITEONLYCHAN", -- Cannot join channel (+i)
|
||||
[474] = "ERR_BANNEDFROMCHAN", -- Cannot join channel (+b)
|
||||
[475] = "ERR_BADCHANNELKEY", -- Cannot join channel (+k)
|
||||
[476] = "ERR_BADCHANMASK", -- Bad channel mask
|
||||
[477] = "ERR_NOCHANMODES", -- Channel doesn't support modes
|
||||
[478] = "ERR_BANLISTFULL", -- Channel list is full
|
||||
[481] = "ERR_NOPRIVILEGES", -- Permission denied- You're not an IRC operator
|
||||
[482] = "ERR_CHANOPRIVSNEEDED", -- You're not channel operator
|
||||
[483] = "ERR_CANTKILLSERVER", -- You can't kill a server!
|
||||
[484] = "ERR_RESTRICTED", -- Your connection is restricted!
|
||||
[485] = "ERR_UNIQOPPRIVSNEEDED", -- You're not the original channel operator
|
||||
[491] = "ERR_NOOPERHOST", -- No O-lines for your host
|
||||
[501] = "ERR_UMODEUNKNOWNFLAG", -- Unknown MODE flag
|
||||
[502] = "ERR_USERSDONTMATCH", -- Can't change mode for other users
|
||||
-- }}}
|
||||
-- unused {{{
|
||||
[231] = "RPL_SERVICEINFO",
|
||||
[232] = "RPL_ENDOFSERVICES",
|
||||
[233] = "RPL_SERVICE",
|
||||
[300] = "RPL_NONE",
|
||||
[316] = "RPL_WHOISCHANOP",
|
||||
[361] = "RPL_KILLDONE",
|
||||
[362] = "RPL_CLOSING",
|
||||
[363] = "RPL_CLOSEEND",
|
||||
[373] = "RPL_INFOSTART",
|
||||
[384] = "RPL_MYPORTIS",
|
||||
[213] = "RPL_STATSCLINE",
|
||||
[214] = "RPL_STATSNLINE",
|
||||
[215] = "RPL_STATSILINE",
|
||||
[216] = "RPL_STATSKLINE",
|
||||
[217] = "RPL_STATSQLINE",
|
||||
[218] = "RPL_STATSYLINE",
|
||||
[240] = "RPL_STATSVLINE",
|
||||
[241] = "RPL_STATSLLINE",
|
||||
[244] = "RPL_STATSHLINE",
|
||||
[246] = "RPL_STATSPING",
|
||||
[247] = "RPL_STATSBLINE",
|
||||
[250] = "RPL_STATSDLINE",
|
||||
[492] = "ERR_NOSERVICEHOST",
|
||||
-- }}}
|
||||
-- guesses {{{
|
||||
[333] = "RPL_TOPICDATE", -- date the topic was set, in seconds since the epoch
|
||||
[505] = "ERR_NOTREGISTERED" -- freenode blocking privmsg from unreged users
|
||||
-- }}}
|
||||
}
|
||||
-- }}}
|
||||
|
||||
-- chanmodes {{{
|
||||
chanmodes = {
|
||||
["@"] = "secret",
|
||||
["*"] = "private",
|
||||
["="] = "public"
|
||||
}
|
||||
-- }}}
|
@ -1,115 +0,0 @@
|
||||
---
|
||||
-- Implementation of the CTCP protocol
|
||||
-- initialization {{{
|
||||
local base = _G
|
||||
local table = require "table"
|
||||
-- }}}
|
||||
|
||||
---
|
||||
-- This module implements the various quoting and escaping requirements of the
|
||||
-- CTCP protocol.
|
||||
module "irc.ctcp"
|
||||
|
||||
-- internal functions {{{
|
||||
-- _low_quote {{{
|
||||
--
|
||||
-- Applies low level quoting to a string (escaping characters which are illegal
|
||||
-- to appear in an IRC packet).
|
||||
-- @param ... Strings to quote together, space separated
|
||||
-- @return Quoted string
|
||||
function _low_quote(...)
|
||||
local str = table.concat({...}, " ")
|
||||
return str:gsub("[%z\n\r\020]", {["\000"] = "\0200",
|
||||
["\n"] = "\020n",
|
||||
["\r"] = "\020r",
|
||||
["\020"] = "\020\020"})
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _low_dequote {{{
|
||||
--
|
||||
-- Removes low level quoting done by low_quote.
|
||||
-- @param str String with low level quoting applied to it
|
||||
-- @return String with those quoting methods stripped off
|
||||
function _low_dequote(str)
|
||||
return str:gsub("\020(.?)", function(s)
|
||||
if s == "0" then return "\000" end
|
||||
if s == "n" then return "\n" end
|
||||
if s == "r" then return "\r" end
|
||||
if s == "\020" then return "\020" end
|
||||
return ""
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _ctcp_quote {{{
|
||||
--
|
||||
-- Applies CTCP quoting to a block of text which has been identified as CTCP
|
||||
-- data (by the calling program).
|
||||
-- @param ... Strings to apply CTCP quoting to together, space separated
|
||||
-- @return String with CTCP quoting applied
|
||||
function _ctcp_quote(...)
|
||||
local str = table.concat({...}, " ")
|
||||
local ret = str:gsub("[\001\\]", {["\001"] = "\\a",
|
||||
["\\"] = "\\\\"})
|
||||
return "\001" .. ret .. "\001"
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _ctcp_dequote {{{
|
||||
--
|
||||
-- Removes CTCP quoting from a block of text which has been identified as CTCP
|
||||
-- data (likely by ctcp_split).
|
||||
-- @param str String with CTCP quoting
|
||||
-- @return String with all CTCP quoting stripped
|
||||
function _ctcp_dequote(str)
|
||||
local ret = str:gsub("^\001", ""):gsub("\001$", "")
|
||||
return ret:gsub("\\(.?)", function(s)
|
||||
if s == "a" then return "\001" end
|
||||
if s == "\\" then return "\\" end
|
||||
return ""
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _ctcp_split {{{
|
||||
--
|
||||
-- Splits a low level dequoted string into normal text and unquoted CTCP
|
||||
-- messages.
|
||||
-- @param str Low level dequoted string
|
||||
-- @return Array of tables, with each entry in the array corresponding to one
|
||||
-- part of the split message. These tables will have these fields:
|
||||
-- <ul>
|
||||
-- <li><i>str:</i> The text of the split section</li>
|
||||
-- <li><i>ctcp:</i> True if the section was a CTCP message, false
|
||||
-- otherwise</li>
|
||||
-- </ul>
|
||||
function _ctcp_split(str)
|
||||
local ret = {}
|
||||
local iter = 1
|
||||
while true do
|
||||
local s, e = str:find("\001.*\001", iter)
|
||||
|
||||
local plain_string, ctcp_string
|
||||
if not s then
|
||||
plain_string = str:sub(iter, -1)
|
||||
else
|
||||
plain_string = str:sub(iter, s - 1)
|
||||
ctcp_string = str:sub(s, e)
|
||||
end
|
||||
|
||||
if plain_string ~= "" then
|
||||
table.insert(ret, {str = plain_string, ctcp = false})
|
||||
end
|
||||
if not s then break end
|
||||
if ctcp_string ~= "" then
|
||||
table.insert(ret, {str = _ctcp_dequote(ctcp_string), ctcp = true})
|
||||
end
|
||||
|
||||
iter = e + 1
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
@ -1,196 +0,0 @@
|
||||
---
|
||||
-- Implementation of the DCC protocol
|
||||
-- initialization {{{
|
||||
local base = _G
|
||||
local irc = require 'irc'
|
||||
local ctcp = require 'irc.ctcp'
|
||||
local c = ctcp._ctcp_quote
|
||||
local irc_debug = require 'irc.debug'
|
||||
local misc = require 'irc.misc'
|
||||
local socket = require 'socket'
|
||||
local coroutine = require 'coroutine'
|
||||
local io = require 'io'
|
||||
local string = require 'string'
|
||||
-- }}}
|
||||
|
||||
---
|
||||
-- This module implements the DCC protocol. File transfers (DCC SEND) are
|
||||
-- handled, but DCC CHAT is not, as of yet.
|
||||
module 'irc.dcc'
|
||||
|
||||
-- defaults {{{
|
||||
FIRST_PORT = 1028
|
||||
LAST_PORT = 5000
|
||||
-- }}}
|
||||
|
||||
-- private functions {{{
|
||||
-- debug_dcc {{{
|
||||
--
|
||||
-- Prints a debug message about DCC events similar to irc.debug.warn, etc.
|
||||
-- @param msg Debug message
|
||||
local function debug_dcc(msg)
|
||||
irc_debug._message("DCC", msg, "\027[0;32m")
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- send_file {{{
|
||||
--
|
||||
-- Sends a file to a remote user, after that user has accepted our DCC SEND
|
||||
-- invitation
|
||||
-- @param sock Socket to send the file on
|
||||
-- @param file Lua file object corresponding to the file we want to send
|
||||
-- @param packet_size Size of the packets to send the file in
|
||||
local function send_file(sock, file, packet_size)
|
||||
local bytes = 0
|
||||
while true do
|
||||
local packet = file:read(packet_size)
|
||||
if not packet then break end
|
||||
bytes = bytes + packet:len()
|
||||
local index = 1
|
||||
while true do
|
||||
local skip = false
|
||||
sock:send(packet, index)
|
||||
local new_bytes, err = sock:receive(4)
|
||||
if not new_bytes then
|
||||
if err == "timeout" then
|
||||
skip = true
|
||||
else
|
||||
irc_debug._warn(err)
|
||||
break
|
||||
end
|
||||
else
|
||||
new_bytes = misc._int_to_str(new_bytes)
|
||||
end
|
||||
if not skip then
|
||||
if new_bytes ~= bytes then
|
||||
index = packet_size - bytes + new_bytes + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
coroutine.yield(true)
|
||||
end
|
||||
debug_dcc("File completely sent")
|
||||
file:close()
|
||||
sock:close()
|
||||
irc._unregister_socket(sock, 'w')
|
||||
return true
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- handle_connect {{{
|
||||
--
|
||||
-- Handle the connection attempt by a remote user to get our file. Basically
|
||||
-- just swaps out the server socket we were listening on for a client socket
|
||||
-- that we can send data on
|
||||
-- @param ssock Server socket that the remote user connected to
|
||||
-- @param file Lua file object corresponding to the file we want to send
|
||||
-- @param packet_size Size of the packets to send the file in
|
||||
local function handle_connect(ssock, file, packet_size)
|
||||
debug_dcc("Offer accepted, beginning to send")
|
||||
packet_size = packet_size or 1024
|
||||
local sock = ssock:accept()
|
||||
sock:settimeout(0.1)
|
||||
ssock:close()
|
||||
irc._unregister_socket(ssock, 'r')
|
||||
irc._register_socket(sock, 'w',
|
||||
coroutine.wrap(function(s)
|
||||
return send_file(s, file, packet_size)
|
||||
end))
|
||||
return true
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- accept_file {{{
|
||||
--
|
||||
-- Accepts a file from a remote user which has offered it to us.
|
||||
-- @param sock Socket to receive the file on
|
||||
-- @param file Lua file object corresponding to the file we want to save
|
||||
-- @param packet_size Size of the packets to receive the file in
|
||||
local function accept_file(sock, file, packet_size)
|
||||
local bytes = 0
|
||||
while true do
|
||||
local packet, err, partial_packet = sock:receive(packet_size)
|
||||
if not packet and err == "timeout" then packet = partial_packet end
|
||||
if not packet then break end
|
||||
if packet:len() == 0 then break end
|
||||
bytes = bytes + packet:len()
|
||||
sock:send(misc._str_to_int(bytes))
|
||||
file:write(packet)
|
||||
coroutine.yield(true)
|
||||
end
|
||||
debug_dcc("File completely received")
|
||||
file:close()
|
||||
sock:close()
|
||||
irc._unregister_socket(sock, 'r')
|
||||
return true
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- internal functions {{{
|
||||
-- _accept {{{
|
||||
--
|
||||
-- Accepts a file offer from a remote user. Called when the on_dcc callback
|
||||
-- retuns true.
|
||||
-- @param filename Name to save the file as
|
||||
-- @param address IP address of the remote user in low level int form
|
||||
-- @param port Port to connect to at the remote user
|
||||
-- @param packet_size Size of the packets the remote user will be sending
|
||||
function _accept(filename, address, port, packet_size)
|
||||
debug_dcc("Accepting a DCC SEND request from " .. address .. ":" .. port)
|
||||
packet_size = packet_size or 1024
|
||||
local sock = base.assert(socket.tcp())
|
||||
base.assert(sock:connect(address, port))
|
||||
sock:settimeout(0.1)
|
||||
local file = base.assert(io.open(misc._get_unique_filename(filename), "w"))
|
||||
irc._register_socket(sock, 'r',
|
||||
coroutine.wrap(function(s)
|
||||
return accept_file(s, file, packet_size)
|
||||
end))
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- public functions {{{
|
||||
-- send {{{
|
||||
---
|
||||
-- Offers a file to a remote user.
|
||||
-- @param nick User to offer the file to
|
||||
-- @param filename Filename to offer
|
||||
-- @param port Port to accept connections on (optional, defaults to
|
||||
-- choosing an available port between FIRST_PORT and LAST_PORT
|
||||
-- above)
|
||||
function send(nick, filename, port)
|
||||
port = port or FIRST_PORT
|
||||
local sock
|
||||
repeat
|
||||
sock = base.assert(socket.tcp())
|
||||
err, msg = sock:bind('*', port)
|
||||
port = port + 1
|
||||
until msg ~= "address already in use" and port <= LAST_PORT + 1
|
||||
port = port - 1
|
||||
base.assert(err, msg)
|
||||
base.assert(sock:listen(1))
|
||||
local ip = misc._ip_str_to_int(irc.get_ip())
|
||||
local file, err = io.open(filename)
|
||||
if not file then
|
||||
irc_debug._warn(err)
|
||||
sock:close()
|
||||
return
|
||||
end
|
||||
local size = file:seek("end")
|
||||
file:seek("set")
|
||||
irc._register_socket(sock, 'r',
|
||||
coroutine.wrap(function(s)
|
||||
return handle_connect(s, file)
|
||||
end))
|
||||
filename = misc._basename(filename)
|
||||
if filename:find(" ") then filename = '"' .. filename .. '"' end
|
||||
debug_dcc("Offering " .. filename .. " to " .. nick .. " from " ..
|
||||
irc.get_ip() .. ":" .. port)
|
||||
irc.send("PRIVMSG", nick, c("DCC", "SEND", filename, ip, port, size))
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
@ -1,92 +0,0 @@
|
||||
---
|
||||
-- Basic debug output
|
||||
-- initialization {{{
|
||||
local base = _G
|
||||
local io = require 'io'
|
||||
-- }}}
|
||||
|
||||
---
|
||||
-- This module implements a few useful debug functions for use throughout the
|
||||
-- rest of the code.
|
||||
module 'irc.debug'
|
||||
|
||||
-- defaults {{{
|
||||
COLOR = true
|
||||
-- }}}
|
||||
|
||||
-- local variables {{{
|
||||
local ON = false
|
||||
local outfile = io.output()
|
||||
-- }}}
|
||||
|
||||
-- internal functions {{{
|
||||
-- _message {{{
|
||||
--
|
||||
-- Output a debug message.
|
||||
-- @param msg_type Arbitrary string corresponding to the type of message
|
||||
-- @param msg Message text
|
||||
-- @param color Which terminal code to use for color output (defaults to
|
||||
-- dark gray)
|
||||
function _message(msg_type, msg, color)
|
||||
if ON then
|
||||
local endcolor = ""
|
||||
if COLOR and outfile == io.stdout then
|
||||
color = color or "\027[1;30m"
|
||||
endcolor = "\027[0m"
|
||||
else
|
||||
color = ""
|
||||
endcolor = ""
|
||||
end
|
||||
outfile:write(color .. msg_type .. ": " .. msg .. endcolor .. "\n")
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _err {{{
|
||||
--
|
||||
-- Signal an error. Writes the error message to the screen in red and calls
|
||||
-- error().
|
||||
-- @param msg Error message
|
||||
-- @see error
|
||||
function _err(msg)
|
||||
_message("ERR", msg, "\027[0;31m")
|
||||
base.error(msg, 2)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- _warn {{{
|
||||
--
|
||||
-- Signal a warning. Writes the warning message to the screen in yellow.
|
||||
-- @param msg Warning message
|
||||
function _warn(msg)
|
||||
_message("WARN", msg, "\027[0;33m")
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
-- public functions {{{
|
||||
-- enable {{{
|
||||
---
|
||||
-- Turns on debug output.
|
||||
function enable()
|
||||
ON = true
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- disable {{{
|
||||
---
|
||||
-- Turns off debug output.
|
||||
function disable()
|
||||
ON = false
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- set_output {{{
|
||||
---
|
||||
-- Redirects output to a file rather than stdout.
|
||||
-- @param file File to write debug output to
|
||||
function set_output(file)
|
||||
outfile = base.assert(io.open(file))
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
@ -1,69 +0,0 @@
|
||||
---
|
||||
-- Implementation of IRC server message parsing
|
||||
-- initialization {{{
|
||||
local base = _G
|
||||
local constants = require 'irc.constants'
|
||||
local ctcp = require 'irc.ctcp'
|
||||
local irc_debug = require 'irc.debug'
|
||||
local misc = require 'irc.misc'
|
||||
local socket = require 'socket'
|
||||
local string = require 'string'
|
||||
local table = require 'table'
|
||||
-- }}}
|
||||
|
||||
---
|
||||
-- This module contains parsing functions for IRC server messages.
|
||||
module 'irc.message'
|
||||
|
||||
-- internal functions {{{
|
||||
-- _parse {{{
|
||||
--
|
||||
-- Parse a server command.
|
||||
-- @param str Command to parse
|
||||
-- @return Table containing the parsed message. It contains:
|
||||
-- <ul>
|
||||
-- <li><i>from:</i> The source of this message, in full usermask
|
||||
-- form (nick!user@host) for messages originating
|
||||
-- from users, and as a hostname for messages from
|
||||
-- servers</li>
|
||||
-- <li><i>command:</i> The command sent, in name form if possible,
|
||||
-- otherwise as a numeric code</li>
|
||||
-- <li><i>args:</i> Array of strings corresponding to the arguments
|
||||
-- to the received command</li>
|
||||
--
|
||||
-- </ul>
|
||||
function _parse(str)
|
||||
-- low-level ctcp quoting {{{
|
||||
str = ctcp._low_dequote(str)
|
||||
-- }}}
|
||||
-- parse the from field, if it exists (leading :) {{{
|
||||
local from = ""
|
||||
if str:sub(1, 1) == ":" then
|
||||
local e
|
||||
e, from = socket.skip(1, str:find("^:([^ ]*) "))
|
||||
str = str:sub(e + 1)
|
||||
end
|
||||
-- }}}
|
||||
-- get the command name or numerical reply value {{{
|
||||
local command, argstr = socket.skip(2, str:find("^([^ ]*) ?(.*)"))
|
||||
local reply = false
|
||||
if command:find("^%d%d%d$") then
|
||||
reply = true
|
||||
if constants.replies[base.tonumber(command)] then
|
||||
command = constants.replies[base.tonumber(command)]
|
||||
else
|
||||
irc_debug._warn("Unknown server reply: " .. command)
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
-- get the args {{{
|
||||
local args = misc._split(argstr, " ", ":")
|
||||
-- the first arg in a reply is always your nick
|
||||
if reply then table.remove(args, 1) end
|
||||
-- }}}
|
||||
-- return the parsed message {{{
|
||||
return {from = from, command = command, args = args}
|
||||
-- }}}
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user