1
0
mirror of https://github.com/minetest-mods/irc.git synced 2024-12-26 00:40:19 +01:00
This commit is contained in:
ShadowNinja 2013-04-29 18:07:44 -04:00
parent 3aede000b7
commit c7f989dd85
105 changed files with 946 additions and 22249 deletions

10
.gitignore vendored
View File

@ -1,9 +1,3 @@
Build*
dists
irc-*
Build
irc
*.zip
*.tar.gz
*.tar.bz2
*.marks
screenshot_*.png

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "src/LuaIRC"]
path = src/LuaIRC
url = https://github.com/ShadowNinja/LuaIRC.git

View File

@ -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}
)

View File

@ -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
@ -202,15 +206,12 @@ LICENSE
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
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.

View File

@ -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)

View File

@ -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 :)

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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>
&copy; 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -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

View File

@ -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 ;
}

View File

@ -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 "&gt; " and "&gt;&gt; ".
<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>

View File

@ -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

View File

@ -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>

File diff suppressed because it is too large Load Diff

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;()</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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;()</dt>
<dd>
This callback is triggered when the connection has completed.
</dd>
<dt><a name="ctcp_error"></a><strong>ctcp_error</strong>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>

View File

@ -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>&nbsp;(self, name)</td>
<td class="summary">Ban a user from a channel.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#contains">contains</a>&nbsp;(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>&nbsp;(self, name)</td>
<td class="summary">Remove ops from a user.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#devoice">devoice</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(chan)</td>
<td class="summary">Creates a new Channel object.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#op">op</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(self, key)</td>
<td class="summary">Set a channel password.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_limit">set_limit</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(self, name)</td>
<td class="summary">Remove a ban on a user.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#users">users</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>

View File

@ -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>

View File

@ -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>

View File

@ -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>&nbsp;(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>&nbsp;(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>

View File

@ -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>&nbsp;()</td>
<td class="summary">Turns off debug output.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#enable">enable</a>&nbsp;()</td>
<td class="summary">Turns on debug output.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#set_output">set_output</a>&nbsp;(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>&nbsp;()</dt>
<dd>
Turns off debug output.
</dd>
<dt><a name="enable"></a><strong>enable</strong>&nbsp;()</dt>
<dd>
Turns on debug output.
</dd>
<dt><a name="set_output"></a><strong>set_output</strong>&nbsp;(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>

View File

@ -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>&nbsp;(name, action)</td>
<td class="summary">Perform a /me action.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#channels">channels</a>&nbsp;()</td>
<td class="summary">Iterate over currently joined channels.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#connect">connect</a>&nbsp;(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>&nbsp;(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>&nbsp;(cb, nick)</td>
<td class="summary">Send a localtime request.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#ctcp_version">ctcp_version</a>&nbsp;(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>&nbsp;()</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>&nbsp;(channel)</td>
<td class="summary">Join a channel.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#notice">notice</a>&nbsp;(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>&nbsp;(channel)</td>
<td class="summary">Leave a channel.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#quit">quit</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(command, ...)</td>
<td class="summary">Send a raw IRC command.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#server_time">server_time</a>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;()</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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;()</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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>&nbsp;(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>

View File

@ -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>

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>
&nbsp;&nbsp;name = <i>canonic-name</i>,<br>
&nbsp;&nbsp;alias = <i>alias-list</i>,<br>
&nbsp;&nbsp;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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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://][&lt;user&gt;[:&lt;password&gt;]@]&lt;host&gt;[:&lt;port&gt;][/&lt;path&gt;][<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>
&nbsp;&nbsp;host = <i>string</i>,<br>
&nbsp;&nbsp;sink = <i>LTN12 sink</i>,<br>
&nbsp;&nbsp;argument <i>or</i> path = <i>string</i>,<br>
&nbsp;&nbsp;[user = <i>string</i>,]<br>
&nbsp;&nbsp;[password = <i>string</i>]<br>
&nbsp;&nbsp;[command = <i>string</i>,]<br>
&nbsp;&nbsp;[port = <i>number</i>,]<br>
&nbsp;&nbsp;[type = <i>string</i>,]<br>
&nbsp;&nbsp;[step = <i>LTN12 pump step</i>,]<br>
&nbsp;&nbsp;[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>
&nbsp;&nbsp;host = <i>string</i>,<br>
&nbsp;&nbsp;source = <i>LTN12 sink</i>,<br>
&nbsp;&nbsp;argument <i>or</i> path = <i>string</i>,<br>
&nbsp;&nbsp;[user = <i>string</i>,]<br>
&nbsp;&nbsp;[password = <i>string</i>]<br>
&nbsp;&nbsp;[command = <i>string</i>,]<br>
&nbsp;&nbsp;[port = <i>number</i>,]<br>
&nbsp;&nbsp;[type = <i>string</i>,]<br>
&nbsp;&nbsp;[step = <i>LTN12 pump step</i>,]<br>
&nbsp;&nbsp;[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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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 &copy; 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&nbsp;5.0 and has been tested on
Windows&nbsp;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\&gt; set LUA_INIT=@c:\luasocket\compat-5.1.lua
c:\luasocket\&gt; set LUA_CPATH=?.dll
c:\luasocket\&gt; 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\&gt; lua50
Lua 5.0.2 Copyright (C) 1994-2004 Tecgraf, PUC-Rio
&gt; http = require"socket.http"
&gt; print(http.request"http://www.cs.princeton.edu/~diego/professional/luasocket/")
--&gt; 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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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://][&lt;user&gt;[:&lt;password&gt;]@]&lt;host&gt;[:&lt;port&gt;][/&lt;path&gt;]
</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>
&nbsp;&nbsp;field-1-name = <i>field-1-value</i>,<br>
&nbsp;&nbsp;field-2-name = <i>field-2-value</i>,<br>
&nbsp;&nbsp;field-3-name = <i>field-3-value</i>,<br>
&nbsp;&nbsp;...<br>
&nbsp;&nbsp;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>
&nbsp;&nbsp;url = <i>string</i>,<br>
&nbsp;&nbsp;[sink = <i>LTN12 sink</i>,]<br>
&nbsp;&nbsp;[method = <i>string</i>,]<br>
&nbsp;&nbsp;[headers = <i>header-table</i>,]<br>
&nbsp;&nbsp;[source = <i>LTN12 source</i>],<br>
&nbsp;&nbsp;[step = <i>LTN12 pump step</i>,]<br>
&nbsp;&nbsp;[proxy = <i>string</i>,]<br>
&nbsp;&nbsp;[redirect = <i>boolean</i>,]<br>
&nbsp;&nbsp;[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&nbsp;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>&lt;user&gt;</tt> and
<tt>&lt;password&gt;</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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>&lt;CDIR&gt;</tt>
and <tt>&lt;LDIR&gt;</tt>, respectively.
For instance, in my laptop, I use '<tt>/usr/local/lib/lua/5.0</tt>' for
<tt>&lt;CDIR&gt;</tt> and '<tt>/usr/local/share/lua/5.0</tt>' for
<tt>&lt;LDIR&gt;</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>
&lt;LDIR&gt;/compat-5.1.lua
&lt;LDIR&gt;/ltn12.lua
&lt;LDIR&gt;/socket.lua
&lt;CDIR&gt;/socket/core.dll
&lt;LDIR&gt;/socket/http.lua
&lt;LDIR&gt;/socket/tp.lua
&lt;LDIR&gt;/socket/ftp.lua
&lt;LDIR&gt;/socket/smtp.lua
&lt;LDIR&gt;/socket/url.lua
&lt;LDIR&gt;/mime.lua
&lt;CDIR&gt;/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=@&lt;LDIR&gt;/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=&lt;LDIR&gt;/?.lua;?.lua
LUA_CPATH=&lt;CDIR&gt;/?.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
&gt; socket = require("socket")
&gt; print(socket._VERSION)
--&gt; 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
&gt; http = require("socket.http")
&gt; print(http.request("http://www.cs.princeton.edu/~diego/professional/luasocket"))
--&gt; homepage gets dumped to terminal
</pre>
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<div class=footer>
<hr>
<center>
<p class=bar>
<a href="home.html">home</a> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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")))
--&gt; 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")))
--&gt; ..\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çã")))
--&gt; 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=")))
--&gt; 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=")))
--&gt; 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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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; }

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>
&nbsp;&nbsp;field-1-name = <i>field-1-value</i>,<br>
&nbsp;&nbsp;field-2-name = <i>field-2-value</i>,<br>
&nbsp;&nbsp;field-3-name = <i>field-3-value</i>,<br>
&nbsp;&nbsp;...<br>
&nbsp;&nbsp;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>
&nbsp;&nbsp;from = <i>string</i>,<br>
&nbsp;&nbsp;rcpt = <i>string</i> or <i>string-table</i>,<br>
&nbsp;&nbsp;source = <i>LTN12 source</i>,<br>
&nbsp;&nbsp;[user = <i>string</i>,]<br>
&nbsp;&nbsp;[password = <i>string</i>,]<br>
&nbsp;&nbsp;[server = <i>string</i>,]<br>
&nbsp;&nbsp;[port = <i>number</i>,]<br>
&nbsp;&nbsp;[domain = <i>string</i>,]<br>
&nbsp;&nbsp;[step = <i>LTN12 pump step</i>,]<br>
&nbsp;&nbsp;[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>&lt;fulano@example.com&gt;</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 = "&lt;luasocket@example.com&gt;"
rcpt = {
"&lt;fulano@example.com&gt;",
"&lt;beltrano@example.com&gt;",
"&lt;sicrano@example.com&gt;"
}
mesgt = {
headers = {
to = "Fulano da Silva &lt;fulano@example.com&gt;",
cc = '"Beltrano F. Nunes" &lt;beltrano@example.com&gt;',
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>
&nbsp;&nbsp;headers = <i>header-table</i>,<br>
&nbsp;&nbsp;body = <i>LTN12 source</i> or <i>string</i> or
<i>multipart-mesgt</i><br>
}<br>
&nbsp;<br>
multipart-mesgt = {<br>
&nbsp;&nbsp;[preamble = <i>string</i>,]<br>
&nbsp;&nbsp;[1] = <i>mesgt</i>,<br>
&nbsp;&nbsp;[2] = <i>mesgt</i>,<br>
&nbsp;&nbsp;...<br>
&nbsp;&nbsp;[<i>n</i>] = <i>mesgt</i>,<br>
&nbsp;&nbsp;[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 &lt;sicrano@example.com&gt;",
to = "Fulano da Silva &lt;fulano@example.com&gt;",
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 = "&lt;sicrano@example.com&gt;",
rcpt = "&lt;fulano@example.com&gt;",
source = source,
}
</pre>
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<div class=footer>
<hr>
<center>
<p class=bar>
<a href="home.html">home</a> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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&nbsp;10), optionally preceded by a
CR character (ASCII&nbsp;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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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> &middot;
<a href="home.html#download">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>
&lt;url&gt; ::= [&lt;scheme&gt;:][//&lt;authority&gt;][/&lt;path&gt;][;&lt;params&gt;][?&lt;query&gt;][#&lt;fragment&gt;]<br>
&lt;authority&gt; ::= [&lt;userinfo&gt;@]&lt;host&gt;[:&lt;port&gt;]<br>
&lt;userinfo&gt; ::= &lt;user&gt;[:&lt;password&gt;]<br>
&lt;path&gt; ::= {&lt;segment&gt;/}&lt;segment&gt;<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>&lt;path&gt;</tt> component from a list of
<tt>&lt;segment&gt;</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>&lt;segment&gt;</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>&lt;path&gt;</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>
&nbsp;&nbsp;url = <i>string</i>,<br>
&nbsp;&nbsp;scheme = <i>string</i>,<br>
&nbsp;&nbsp;authority = <i>string</i>,<br>
&nbsp;&nbsp;path = <i>string</i>,<br>
&nbsp;&nbsp;params = <i>string</i>,<br>
&nbsp;&nbsp;query = <i>string</i>,<br>
&nbsp;&nbsp;fragment = <i>string</i>,<br>
&nbsp;&nbsp;userinfo = <i>string</i>,<br>
&nbsp;&nbsp;host = <i>string</i>,<br>
&nbsp;&nbsp;port = <i>string</i>,<br>
&nbsp;&nbsp;user = <i>string</i>,<br>
&nbsp;&nbsp;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>&lt;path&gt;</tt> URL component into all its
<tt>&lt;segment&gt;</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>&lt;path&gt;</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> &middot;
<a href="home.html#down">download</a> &middot;
<a href="installation.html">installation</a> &middot;
<a href="introduction.html">introduction</a> &middot;
<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>

View File

@ -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";

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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/;

View File

@ -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/

View File

@ -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"}

View File

@ -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"}

View File

@ -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.

View File

@ -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))

View File

@ -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

View File

@ -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
})

View File

@ -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
View 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
View 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
View 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

@ -0,0 +1 @@
Subproject commit 8a2e47a326e097102533dfd90c67193614e7a479

View File

@ -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;
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
cmd = message
args = ""
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
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
mt_irc.register_bot_command = function ( name, def )
if ((not def.func) or (type(def.func) ~= "function")) then
error("Wrong bot command definition", 2);
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
mt_irc.bot_commands[name] = def;
self.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);
else
local cmdlist = "Available commands:";
for name,cmd in pairs(mt_irc.bot_commands) do
cmdlist = cmdlist.." "..name;
end
irc.say(from, cmdlist);
irc.say(from, "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
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
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;
local cmd = mt_irc.bot_commands[args]
if not cmd then
mt_irc:say(user.nick, "Unknown command '"..cmdname.."'.")
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;
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..", "
end
irc.say(from, "There's No player named `"..args.."'");
end;
});
mt_irc:say(user.nick, cmdlist
.." -- Use 'help <command name>' to get help about a specific command.")
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(
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 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
})
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
})

View File

@ -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
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
if mt_irc.connected then
mt_irc:say("*** "..name.." joined the game")
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);
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
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;
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);
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!");
end)
mt_irc.register_callback("nick_change", function ( old_nick, new_nick )
mt_irc.say("TEST: "..old_nick.." -> "..new_nick);
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if mt_irc.connected then
mt_irc:say("*** "..name.." left the game")
end
end)
]]
minetest.register_on_chat_message(function(name, message)
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
mt_irc:queueMsg(mt_irc.msgs.playerMessage(mt_irc.config.channel, name, message))
end)
minetest.register_on_shutdown(function()
mt_irc:disconnect("Game shutting down.")
end)

View File

@ -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; };
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;
end
local found, _, toname, msg = param:find("^([^%s#]+)%s(.+)");
if not found then
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);
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 };
params = "<name> <message>",
description = "Send a private message to an IRC user",
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; };
func = function ( name, param )
local s = "";
for k, v in pairs(mt_irc.connected_players) do
if (v) then
s = s.." "..k;
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, message = param:find("^([^%s]+)%s(.+)")
if not found then
minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.")
return
end
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
minetest.chat_send_player(name, "Players On Channel:"..s);
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", {
description = "Connect to the IRC server.",
privs = {irc_admin=true},
func = function(name, param)
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.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

View File

@ -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");
-- (boolean, default true)
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

View File

@ -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
View 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)

View File

@ -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)
end
mt_irc.buffered_messages = nil
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
irc.poll()
mt_irc.cur_time = mt_irc.cur_time - mt_irc.dtime
self.cur_time = self.cur_time - self.config.interval
end
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;
-- Hooks will manage incoming messages and errors
if not pcall(function() mt_irc.conn:think() end) then
return
end
mt_irc.connected_players[name] = nil;
minetest.chat_send_player(name, "IRC: You are now out of the channel.");
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.");
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;
end
while (not mt_irc.got_motd) do
irc.poll();
-- 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
mt_irc.say = function ( to, msg )
if (not msg) then
msg = to;
to = mt_irc.channel;
function mt_irc:connect()
if self.connected then
minetest.log("error", "IRC: Ignoring attempt to connect when already connected.")
return
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);
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)
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
irc.say(to, msg);
if self.config.NSPass then
self:say("NickServ", "IDENTIFY "..self.config.NSPass)
end
self.conn:join(self.config.channel, self.config.key)
self.connected = true
minetest.log("action", "IRC: Connected!")
minetest.chat_send_all("IRC: Connected!")
end
mt_irc.irc = irc;
-- Misc helpers
-- Requested by Exio
string.expandvars = function ( s, vars )
return s:gsub("%$%(([^)]+)%)", vars);
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
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()
function mt_irc:say(to, message)
if not message then
message = to
to = self.config.channel
end
to = to or self.config.channel
self:queueMsg(self.msgs.privmsg(to, message))
end
function mt_irc:send(line)
self.conn:send(line)
end
if mt_irc.config.auto_connect then
mt_irc:connect()
end

File diff suppressed because it is too large Load Diff

View File

@ -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
-- }}}
-- }}}
-- }}}

View File

@ -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"
}
-- }}}

View File

@ -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
-- }}}
-- }}}

View File

@ -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
-- }}}
-- }}}

View File

@ -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
-- }}}
-- }}}

View File

@ -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