|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// File : libkviobjects.cpp
|
|
|
|
// Creation date : Wed Sep 09 2000 20:59:01 by Szymon Stefanek
|
|
|
|
//
|
|
|
|
// This file is part of the KVirc irc client distribution
|
|
|
|
// Copyright (C) 2000-2005 Szymon Stefanek (pragma at kvirc dot net)
|
|
|
|
//
|
|
|
|
// This program is FREE software. You can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your opinion) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the HOPE that it will be USEFUL,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, write to the Free Software Foundation,
|
|
|
|
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#include "kvi_debug.h"
|
|
|
|
#include "kvi_settings.h"
|
|
|
|
#include "kvi_string.h"
|
|
|
|
#include "kvi_module.h"
|
|
|
|
#include "kvi_sparser.h"
|
|
|
|
#include "kvi_locale.h"
|
|
|
|
#include "kvi_out.h"
|
|
|
|
#include "kvi_console.h"
|
|
|
|
#include "kvi_netutils.h"
|
|
|
|
#include "kvi_frame.h"
|
|
|
|
#include "kvi_console.h"
|
|
|
|
#include "kvi_error.h"
|
|
|
|
#include "kvi_options.h"
|
|
|
|
#include "kvi_defaults.h"
|
|
|
|
#include "kvi_mirccntrl.h"
|
|
|
|
#include "kvi_app.h"
|
|
|
|
#include "kvi_ircconnection.h"
|
|
|
|
#include "kvi_ircconnectionuserinfo.h"
|
|
|
|
|
|
|
|
#include "gsmcodec.h"
|
|
|
|
#include "broker.h"
|
|
|
|
#include "voice.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "send.h"
|
|
|
|
#include "window.h"
|
|
|
|
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
|
|
|
|
#ifdef COMPILE_ON_WINDOWS
|
|
|
|
// Ugly Windoze compiler...
|
|
|
|
#include "dialogs.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//#warning "KviOption_boolIgnoreDccChat and other types too"
|
|
|
|
|
|
|
|
//extern KVIRC_API KviSharedFilesManager * g_pSharedFilesManager;
|
|
|
|
|
|
|
|
KviDccBroker * g_pDccBroker = 0;
|
|
|
|
|
|
|
|
|
|
|
|
static void dcc_module_set_dcc_type(KviDccDescriptor * d,const char * szBaseType)
|
|
|
|
{
|
|
|
|
d->szType = szBaseType;
|
|
|
|
#ifdef COMPILE_SSL_SUPPORT
|
|
|
|
if(d->bIsSSL)d->szType.prepend('S');
|
|
|
|
#endif
|
|
|
|
if(d->bIsTdcc)d->szType.prepend('T');
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool dcc_kvs_parse_default_parameters(KviDccDescriptor * d,KviKvsModuleCommandCall *c)
|
|
|
|
{
|
|
|
|
d->bIsTdcc = c->switches()->find('t',"tdcc");
|
|
|
|
|
|
|
|
KviKvsVariant * pSw = c->switches()->find('m',"minimize");
|
|
|
|
|
|
|
|
if(pSw != 0)
|
|
|
|
d->bOverrideMinimize = pSw->asBoolean();
|
|
|
|
else
|
|
|
|
d->bOverrideMinimize = false;
|
|
|
|
|
|
|
|
if(!d->console())
|
|
|
|
{
|
|
|
|
// We don't need a console with -c and -n , otherwise we need it
|
|
|
|
if(!(c->switches()->find('c',"connect") || c->switches()->find('n',"no-ctcp")))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("This window has no associated IRC context (an IRC context is required unless -c or -n are passed)","dcc"));
|
|
|
|
return false;
|
|
|
|
} else d->setConsole(c->window()->frame()->firstConsole());
|
|
|
|
}
|
|
|
|
|
|
|
|
__range_valid(d->console());
|
|
|
|
|
|
|
|
if(!d->console()->isConnected())
|
|
|
|
{
|
|
|
|
// We don't need a connection with -c and -n , otherwise we need it
|
|
|
|
if(!(c->switches()->find('c',"connect") || c->switches()->find('n',"no-ctcp")))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("You're not connected to a server (an active connection is required unless -c or -n are passed)","dcc"));
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
// -c or -n , grab a local nick from somewhere
|
|
|
|
d->szLocalNick = KVI_OPTION_STRING(KviOption_stringNickname1);
|
|
|
|
d->szLocalNick.stripWhiteSpace();
|
|
|
|
if(d->szLocalNick.isEmpty())d->szLocalNick = KVI_DEFAULT_NICKNAME1;
|
|
|
|
d->szLocalUser = __tr2qs_ctx("unknown","dcc"); // we can live without it
|
|
|
|
d->szLocalHost = d->szLocalUser; // we can live without it
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We know everything
|
|
|
|
d->szLocalNick = d->console()->connection()->userInfo()->nickName();
|
|
|
|
d->szLocalUser = d->console()->connection()->userInfo()->userName();
|
|
|
|
d->szLocalHost = d->console()->connection()->userInfo()->hostName();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pSw = c->switches()->find('i',"ip"))
|
|
|
|
{
|
|
|
|
pSw->asString(d->szListenIp);
|
|
|
|
if(!(d->szListenIp.contains('.') || d->szListenIp.contains(':')))
|
|
|
|
{
|
|
|
|
// This will magically work with the same buffer as source and dst!
|
|
|
|
if(!KviNetUtils::getInterfaceAddress(d->szListenIp,d->szListenIp))
|
|
|
|
{
|
|
|
|
c->error(__tr2qs_ctx("Unable to get address of interface %Q","dcc"),&(d->szListenIp));
|
|
|
|
delete d;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TQString tmp;
|
|
|
|
if(!dcc_kvs_get_listen_ip_address(c,d->console(),tmp))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("No suitable interfaces to listen on, use -i","dcc"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
d->szListenIp=tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pSw = c->switches()->find('p',"port"))
|
|
|
|
{
|
|
|
|
pSw->asString(d->szListenPort); // fixme!
|
|
|
|
}
|
|
|
|
else d->szListenPort = "0"; // any port is ok
|
|
|
|
|
|
|
|
if(pSw = c->switches()->find('a',"fake-address"))
|
|
|
|
{
|
|
|
|
pSw->asString(d->szFakeIp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault))
|
|
|
|
{
|
|
|
|
d->szFakeIp = KVI_OPTION_STRING(KviOption_stringDefaultDccFakeAddress);
|
|
|
|
if(d->szFakeIp.isEmpty())KVI_OPTION_BOOL(KviOption_boolDccSendFakeAddressByDefault) = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pSw = c->switches()->find('f',"fake-port"))
|
|
|
|
{
|
|
|
|
pSw->asString(d->szFakePort);
|
|
|
|
}
|
|
|
|
|
|
|
|
d->bDoTimeout = (!c->switches()->find('u',"unlimited"));
|
|
|
|
#ifdef COMPILE_SSL_SUPPORT
|
|
|
|
d->bIsSSL = c->switches()->find('s',"ssl");
|
|
|
|
#else
|
|
|
|
if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable was built without SSL support, -s switch ignored","dcc"));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.chat
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.chat
|
|
|
|
@short:
|
|
|
|
Starts a DCC Chat connection
|
|
|
|
@syntax:
|
|
|
|
dcc.chat [-s] [-n] [-c] [-u] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname>
|
|
|
|
@switches:
|
|
|
|
!sw: -m[=<boolean>] | --minimize[=<boolean>]
|
|
|
|
If the -m switch is passed, the default boolCreateMinimizedDccChat option
|
|
|
|
is overridden with the <boolean> parameter passed. So actually
|
|
|
|
by passing -m=1 will create a minimized DCC send even
|
|
|
|
if the [fnc]$option[/fnc](boolCreateMinimizedDccChat) returns false.[br]
|
|
|
|
In the same way, by passing -m=0 you will create a non minimized DCC send.
|
|
|
|
If no <boolean> value is specified, it defaults to 1.[br]
|
|
|
|
|
|
|
|
!sw: -n | --no-ctcp
|
|
|
|
Do NOT send the CTCP request to the target user, you will have to do it manually,
|
|
|
|
or the remote user will have to connect manually (for example by using dcc.chat -c).[br]
|
|
|
|
|
|
|
|
!sw: -c | --connect
|
|
|
|
Attempt to CONNECT to the remote host specified as <interface> and <port>,
|
|
|
|
instead of listening (active connection instead of a passive one).
|
|
|
|
In this case the -i and -p switches are mandatory.[br]
|
|
|
|
The 'c' switch takes precedence over 'n' (In fact both should
|
|
|
|
be mutually exclusive).[br]
|
|
|
|
If the 'c' and 'n' switches are missing, this commands
|
|
|
|
needs to be executed in a window that is bound to a connected
|
|
|
|
IRC context (you need a third entity to accomplish the negotiation).[br]
|
|
|
|
|
|
|
|
!sw: -i=<interface> | --ip=<interface>
|
|
|
|
Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
|
|
|
|
If this switch is NOT specified, the socket is bound to the interface of
|
|
|
|
the current IRC connection (if any) or to "127.0.0.1".[br]
|
|
|
|
You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
|
|
|
|
since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
|
|
|
|
Here go some examples:[br]
|
|
|
|
-i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
|
|
|
|
-i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
|
|
|
|
-i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
|
|
|
|
The -i switch parameter may serve also as a target address when the -c switch is used.[br]
|
|
|
|
|
|
|
|
!sw: -p=<port> | --port=<port>
|
|
|
|
Bind the local listening socket to the specified <port>.
|
|
|
|
If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
|
|
|
|
|
|
|
|
!sw: -a=<fake address> | --fake-address=<fake address>
|
|
|
|
Send the <fake address> as target for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real IP address of the listening
|
|
|
|
interface.[br]
|
|
|
|
|
|
|
|
!sw: -f=<fake port> | --fake-port=<fake port>
|
|
|
|
Send the <fake port> as target port for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real port of the listening socket.
|
|
|
|
[br][br]
|
|
|
|
All these switches are meant to allow maximum flexibility of the
|
|
|
|
DCC negotiation, earlier KVIrc releases had serious problems
|
|
|
|
with firewalled and/or masqueraded machines. With the -a and -f switches
|
|
|
|
you can work around it.[br]
|
|
|
|
[br]
|
|
|
|
|
|
|
|
!sw: -u | --unlimited
|
|
|
|
If the 'u' switch is given, the connection attempt will
|
|
|
|
never time out; this might be useful if you want to leave
|
|
|
|
a listening socket for a friend of yours while you are sleeping
|
|
|
|
and have the CTCP processing disabled. The 'u' switch works either
|
|
|
|
in active and passive mode.[br]
|
|
|
|
|
|
|
|
!sw: -s | --ssl
|
|
|
|
Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
|
|
|
|
with a private key algorithm after a public key handshake.[br]
|
|
|
|
This option will work only if the KVIrc executable has been compiled with SSL support
|
|
|
|
and the remote end supports the SSL protocol too.[br]
|
|
|
|
Please note that this will may down the transfer somewhat.[br]
|
|
|
|
-s can be combined with -t.[br]
|
|
|
|
The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
|
|
|
|
When requesting a SSL based DCC send to someone you probably will need a
|
|
|
|
certificate. If you don't have one, create it (for example with CA.pl -newcert)
|
|
|
|
and set it in the options dialog.
|
|
|
|
|
|
|
|
!sw: -z | --zero-port
|
|
|
|
Use the 0 port method. This is a dirty hack that allows you to use the CHAT
|
|
|
|
protocol with mIrc receiving clients.
|
|
|
|
@description:
|
|
|
|
Attempts a DCC connection to <nickname>.[br]
|
|
|
|
The simplest case "dcc.chat <nickname>" will work just as in all
|
|
|
|
the other IRC clients, but this command is really more powerful...[br]
|
|
|
|
Before attempting to understand the possibilities of this command,
|
|
|
|
be sure to know how [doc:dcc_connection]DCC negotiation and connections[/doc] work.
|
|
|
|
If the 'i' switch is specified, the local listening socket
|
|
|
|
will be bound to the specified <interface> (which is an IP address, IPv4 or IPv6),
|
|
|
|
otherwise it will be bound to the interface of the
|
|
|
|
current IRC connection.[br]
|
|
|
|
You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
|
|
|
|
since IPv6 ones seem to be unsupported by the system ioctl() calls at the moment (in Linux at least)).[br]
|
|
|
|
Here are some examples:[br]
|
|
|
|
-i=215.243.12.12: This will bind to the IPv4 interface with the specified address.[br]
|
|
|
|
-i=3ffe:1001::1: This will bind to the IPv6 interface with the specified address.[br]
|
|
|
|
-i=ppp0: This will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
|
|
|
|
The -i switch parameter may serve also as a target address when the -c switch is used.[br]
|
|
|
|
If the 'p' switch is specified, the local listening socket
|
|
|
|
will be bound to the <port>, otherwise it will be bound to
|
|
|
|
a random port choosen by the kernel.[br]
|
|
|
|
If the 'a' switch is specified, the requesting CTCP message
|
|
|
|
will contain <fake address> as target for the remote user,
|
|
|
|
otherwise the CTCP message will contain the real IP address
|
|
|
|
of the listening interface.
|
|
|
|
If the 'f' switch is specified, the requesting CTCP message
|
|
|
|
will contain <fake port> as target for the remote user,
|
|
|
|
otherwise the CTCP message will contain the real port of the
|
|
|
|
listening socket.
|
|
|
|
All these switches are meant to allow maximum flexibility of the
|
|
|
|
DCC negotiation, earlier KVIrc releases had serious problems
|
|
|
|
with firewalled and/or masqueraded machines. With the -a and -f switches
|
|
|
|
you can workaround it.
|
|
|
|
If the 'n' switch is specified, KVIrc will NOT send the CTCP request
|
|
|
|
to the target user; you will have to do it manually, or the remote user
|
|
|
|
will have to connect manually (for example by using dcc.chat -c).
|
|
|
|
If the 'c' switch is specified, KVIrc will attempt to connect
|
|
|
|
to the remote host specified as <interface> and <port>, instead
|
|
|
|
of listening (active connection instead of a passive one).
|
|
|
|
In this case the -i and -p switches are mandatory.[br]
|
|
|
|
The 'c' switch takes precedence over 'n' (In fact both should
|
|
|
|
be mutually exclusive).[br]
|
|
|
|
If the 'c' and 'n' switches are missing, this commands
|
|
|
|
needs to be executed in a window that is bound to a connected
|
|
|
|
IRC context (you need a third entity to accomplish the negotiation).[br]
|
|
|
|
If the 'u' switch is given, the connection attempt will
|
|
|
|
never time out; this might be useful if you want to leave
|
|
|
|
a listening socket for a friend of yours while you are sleeping
|
|
|
|
and have the CTCP processing disabled. The 'u' switch works either
|
|
|
|
in active and passive mode.[br]
|
|
|
|
If the -m switch is passed, the default boolCreateMinimizedDccChat option
|
|
|
|
is overridden with the <boolean> parameter passed. So actually
|
|
|
|
by passing -m=1 will create a minimized DCC chat even
|
|
|
|
if the [fnc]$option[/fnc](boolCreateMinimizedDccChat) returns false.[br]
|
|
|
|
In the same way, by passing -m=0 you will create a non minimized DCC chat.
|
|
|
|
If no <boolean> value is specified, it defaults to 1.[br]
|
|
|
|
-s will cause the DCC chat to be attempted in Secure Sockets Layer mode:
|
|
|
|
the connection will be encrypted with a private key algorithm after a
|
|
|
|
public key handshake. -s will work only if the KVIrc executable was compiled
|
|
|
|
with SSL support enabled and if the remote end supports it.
|
|
|
|
The eventual DCC request will contain the string SCHAT instead of CHAT.[br]
|
|
|
|
When requesting a SSL based DCC chat to someone you probably will need a
|
|
|
|
certificate. If you don't have one, create it (for example with CA.pl -newcert)
|
|
|
|
and set it in the options dialog.
|
|
|
|
@examples:
|
|
|
|
Simple examples:
|
|
|
|
[example]
|
|
|
|
# Simple DCC chat to Pragma
|
|
|
|
dcc.chat Pragma
|
|
|
|
# DCC chat to Pragma, listen on address 127.0.0.1
|
|
|
|
dcc.chat -i=127.0.0.1 Pragma
|
|
|
|
# DCC chat to Pragma, listen on address 168.0.0.1 and port 1025
|
|
|
|
dcc.chat -i=168.0.0.1 -p=1025 Pragma
|
|
|
|
[/example]
|
|
|
|
More tricky ones:
|
|
|
|
[example]
|
|
|
|
# DCC chat to Pragma, listen on address 127.0.0.1 and port 1080
|
|
|
|
# but tell him to connect to address 212.134.22.11 port 1080
|
|
|
|
dcc.chat -i=127.0.0.1 -p=1080 -a=212.134.22.11 Pragma
|
|
|
|
# DCC chat to Pragma, listen on address 127.0.0.1 and port 1080
|
|
|
|
# but tell him to connect to address 212.134.22.11 port 1090
|
|
|
|
dcc.chat -i=127.0.0.1 -p=1080 -a=212.134.22.11 -f=1090 Pragma
|
|
|
|
[/example]
|
|
|
|
Now run completely out of bounds. Use dcc.chat connections
|
|
|
|
to do various things:
|
|
|
|
[example]
|
|
|
|
# Tricky: simulate a HTTP server
|
|
|
|
dcc.chat -n -i=127.0.0.1 -p=80 Netscape
|
|
|
|
# Now open http://127.0.0.1 with netscape
|
|
|
|
# and type "<html><body>Hello!</body></html>" :)
|
|
|
|
#
|
|
|
|
# Tricky 2: simulate the ident daemon (if you have none)
|
|
|
|
dcc.chat -n -i=127.0.0.1 -p=113 Client
|
|
|
|
#
|
|
|
|
# Now a self-DCC connection without the IRC negotiation
|
|
|
|
# Src: Setup a listening socket awaiting the "Destination" user connection
|
|
|
|
dcc.chat -n -i=127.0.0.1 -p=1080 Dst
|
|
|
|
# Dst: Connect to the listening socket at addr 127.0.0.1 and port 1080
|
|
|
|
dcc.chat -c -i=127.0.0.1 -p=1080 Src
|
|
|
|
# The above example will mess you a bit...
|
|
|
|
# Try to guess why in both windows YOU have the same nickname
|
|
|
|
# that is probably not Dst nor Src... :)
|
|
|
|
[/example]
|
|
|
|
Using the shell ftp proggie is too easy:
|
|
|
|
we're [b]real hackers[/b] and want to do complicated things...
|
|
|
|
[example]
|
|
|
|
# Connect to the local ftp server and get the list of contents
|
|
|
|
/dcc.chat -c -i=127.0.0.1 -p=21 FtpServer
|
|
|
|
# Now login, type in the new window (the following lines are NOT commands):
|
|
|
|
USER youruser
|
|
|
|
PASS yourpass
|
|
|
|
# Now enter passive mode
|
|
|
|
PASV
|
|
|
|
# And watch the line that you have received...sth like
|
|
|
|
# 227 Entering passive mode (127,0,0,1,210,195)
|
|
|
|
/dcc.chat -c -i=127.0.0.1 -p=$((210 * 256) + 195) FtpList
|
|
|
|
# (Change the port numbers accordingly)
|
|
|
|
# And then type in the FtpServer window (this is NOT a KVIrc command):
|
|
|
|
LIST
|
|
|
|
# Then watch the ls output in the FtpList window. :)
|
|
|
|
# In this way you can also read ascii files by ftp:
|
|
|
|
# Assume that in the previous ls output you have seen
|
|
|
|
# a README file.
|
|
|
|
# In the FtpServer window type:
|
|
|
|
PASV
|
|
|
|
# Watch the message
|
|
|
|
# 227 Entering passive mode (127,0,0,1,22,227)
|
|
|
|
/dcc.chat -c -i=127.0.0.1 -p=$((22 * 256) + 227) README
|
|
|
|
# In the FtpServer window type:
|
|
|
|
RETR README
|
|
|
|
# And read the file in the README window :)
|
|
|
|
[/example]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_chat(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
|
|
|
|
d->szNick = szTarget; // we always specify the nickname
|
|
|
|
d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
|
|
|
|
d->szHost = d->szUser; // host is always unknown
|
|
|
|
|
|
|
|
if(!dcc_kvs_parse_default_parameters(d,c))return false;
|
|
|
|
dcc_module_set_dcc_type(d,"CHAT");
|
|
|
|
|
|
|
|
if(c->switches()->find('z',"zero-port"))
|
|
|
|
{
|
|
|
|
// we want to have it reversed... add a tag and send out the request
|
|
|
|
KviDccZeroPortTag * t = g_pDccBroker->addZeroPortTag();
|
|
|
|
|
|
|
|
d->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s chat 127.0.0.1 0 %s%c",
|
|
|
|
d->console()->connection()->encodeText(d->szNick).data(),
|
|
|
|
0x01,
|
|
|
|
d->console()->connection()->encodeText(d->szType).data(),
|
|
|
|
d->console()->connection()->encodeText(t->m_szTag).data(),
|
|
|
|
0x01);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->switches()->find('c',"connect"))
|
|
|
|
{
|
|
|
|
if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
d->szIp = d->szListenIp;
|
|
|
|
d->szPort = d->szListenPort;
|
|
|
|
d->szListenIp = ""; // useless
|
|
|
|
d->szListenPort = ""; // useless
|
|
|
|
d->bActive = true;
|
|
|
|
} else {
|
|
|
|
d->szIp = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szPort = d->szIp;
|
|
|
|
d->bActive = false;
|
|
|
|
d->bSendRequest = !c->switches()->find('n',"no-ctcp");
|
|
|
|
}
|
|
|
|
|
|
|
|
//c->window()->output(0,"%Q %Q %Q",&(d->szIp),&(d->szPort),&(d->szListenIp));
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->executeChat(0,d);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.send
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.send
|
|
|
|
@short:
|
|
|
|
Sends a file
|
|
|
|
@syntax:
|
|
|
|
dcc.send [-s] [-n] [-c] [-u] [-b] [-g[=<file size>]] [-t] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname> [filename]
|
|
|
|
@switches:
|
|
|
|
!sw: -g[=<file size>] | --get[=<file size>]
|
|
|
|
This switch is a dirty trick, you can use it to receive files from people
|
|
|
|
behind a firewall with masquerading enabled.[br]
|
|
|
|
It causes the transfer direction to be inverted; your client will receive
|
|
|
|
the file from the remote host instead of sending it.[br]
|
|
|
|
<file size> is the expected file size in bytes. This parameter can be omitted,
|
|
|
|
and in this case the DCC will "blindly" trust the remote end and assume
|
|
|
|
that the file has been transferred correctly when the remote end closes the connection.[br]
|
|
|
|
If you don't pass the -n option, the remote end will receive an informational DCC RECV request,
|
|
|
|
specifying the IP address and the port to connect to.[br]
|
|
|
|
-t can be used to prevent sending acknowledges to the remote end, and -u can be used
|
|
|
|
to avoid the listening socket to timeout.[br]
|
|
|
|
-a and -f can be used as well, but I see no real reason for that...[br]
|
|
|
|
Here is an example of usage of this option:[br]
|
|
|
|
spion can't accept connections (is behind a firewall with masquerading or some other reason...),
|
|
|
|
to his machine.[br]
|
|
|
|
spion wants to send the file important.jpg to Pragma.[br]
|
|
|
|
spion tells to Pragma that he wants to send him the file and Pragma sets up a connection in the following way:[br]
|
|
|
|
[b]dcc.send -g spion important.png[/b][br]
|
|
|
|
spion will see the informational DCC RECV request with the IP address and port that Pragma is listening on.
|
|
|
|
Assume that the address was 212.212.231.220 and the port 32344.[br]
|
|
|
|
spion will then use the following command:[br]
|
|
|
|
[b]dcc.send -c -i=212.212.231.220 -p=32344 Pragma /home/spion/important.jpg[/b][br]
|
|
|
|
Et voila!..the file is transferring.[br]
|
|
|
|
Pragma will see no file progress indication, since the file size is unknown on Pragma's side.[br]
|
|
|
|
If spion had specified the file size, Pragma could use -g=<file size> while setting up the connection,
|
|
|
|
to be able to see the progress indications.[br]
|
|
|
|
If Pragma used the the -n option, the DCC RECV indication wouldn't have been sent, in this case
|
|
|
|
Pragma would need to communicate the Ip address and the port "manually" to spion.[br]
|
|
|
|
|
|
|
|
!sw: -b | --blind
|
|
|
|
Assume that no acknowledges are sent.
|
|
|
|
Assume that the transfer was successful when the whole file has been sent,
|
|
|
|
then close the socket.[br]
|
|
|
|
This is called a "blind" DCC send.[br]
|
|
|
|
|
|
|
|
!sw: -t | -tdcc
|
|
|
|
Emulate the TDCC protocol: Use the TDCC CTCP message (DCC TSEND) for requesting the connection
|
|
|
|
and assume that no acknowledges are sent. Wait for the remote end to close the connection.[br]
|
|
|
|
|
|
|
|
!sw: -m[=<boolean>] | --minimize[=<boolean>]
|
|
|
|
If the -m switch is passed, the default boolCreateMinimizedDccSend option
|
|
|
|
is overridden with the <boolean> parameter passed. So actually
|
|
|
|
by passing -m=1 will create a minimized DCC send even
|
|
|
|
if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
|
|
|
|
In the same way, by passing -m=0 you will create a non minimized DCC send.
|
|
|
|
If no <boolean> value is specified, it defaults to 1.[br]
|
|
|
|
|
|
|
|
!sw: -n | --no-ctcp
|
|
|
|
Do NOT send the CTCP request to the target user, you will have to do it manually,
|
|
|
|
or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
|
|
|
|
|
|
|
|
!sw: -c | --connect
|
|
|
|
Attempt to CONNECT to the remote host specified as <interface> and <port>,
|
|
|
|
instead of listening (active connection instead of a passive one).
|
|
|
|
In this case the -i and -p switches are mandatory.[br]
|
|
|
|
The 'c' switch takes precedence over 'n' (In fact both should
|
|
|
|
be mutually exclusive).[br]
|
|
|
|
If the 'c' and 'n' switches are missing, this commands
|
|
|
|
needs to be executed in a window that is bound to a connected
|
|
|
|
IRC context (you need a third entity to accomplish the negotiation).[br]
|
|
|
|
|
|
|
|
!sw: -i=<interface> | --ip=<interface>
|
|
|
|
Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
|
|
|
|
If this switch is NOT specified, the socket is bound to the interface of
|
|
|
|
the current IRC connection (if any) or to "127.0.0.1".[br]
|
|
|
|
You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
|
|
|
|
since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
|
|
|
|
Here go some examples:[br]
|
|
|
|
-i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
|
|
|
|
-i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
|
|
|
|
-i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
|
|
|
|
The -i switch parameter may serve also as a target address when the -c switch is used.[br]
|
|
|
|
|
|
|
|
!sw: -p=<port> | --port=<port>
|
|
|
|
Bind the local listening socket to the specified <port>.
|
|
|
|
If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
|
|
|
|
|
|
|
|
!sw: -a=<fake address> | --fake-address=<fake address>
|
|
|
|
Send the <fake address> as target for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real IP address of the listening
|
|
|
|
interface.[br]
|
|
|
|
|
|
|
|
!sw: -f=<fake port> | --fake-port=<fake port>
|
|
|
|
Send the <fake port> as target port for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real port of the listening socket.
|
|
|
|
[br][br]
|
|
|
|
All these switches are meant to allow maximum flexibility of the
|
|
|
|
DCC negotiation, earlier KVIrc releases had serious problems
|
|
|
|
with firewalled and/or masqueraded machines. With the -a and -f switches
|
|
|
|
you can work around it.[br]
|
|
|
|
[br]
|
|
|
|
|
|
|
|
!sw: -u | --unlimited
|
|
|
|
If the 'u' switch is given, the connection attempt will
|
|
|
|
never time out; this might be useful if you want to leave
|
|
|
|
a listening socket for a friend of yours while you are sleeping
|
|
|
|
and have the CTCP processing disabled. The 'u' switch works either
|
|
|
|
in active and passive mode.[br]
|
|
|
|
|
|
|
|
!sw: -s | --ssl
|
|
|
|
Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
|
|
|
|
with a private key algorithm after a public key handshake.[br]
|
|
|
|
This option will work only if the KVIrc executable has been compiled with SSL support
|
|
|
|
and the remote end supports the SSL protocol too.[br]
|
|
|
|
Please note that this will may down the transfer somewhat.[br]
|
|
|
|
-s can be combined with -t.[br]
|
|
|
|
The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
|
|
|
|
When requesting a SSL based DCC send to someone you probably will need a
|
|
|
|
certificate. If you don't have one, create it (for example with CA.pl -newcert)
|
|
|
|
and set it in the options dialog.
|
|
|
|
|
|
|
|
@description:
|
|
|
|
Attempts to send the file <filename> to <nickname>.[br]
|
|
|
|
If [filename] is specified it must be an absolute file path,
|
|
|
|
otherwise a file selection dialog is opened.[br]
|
|
|
|
The simplest case "dcc.send <nickname> <filename>" will work just as in all
|
|
|
|
the other IRC clients, but this command is really more powerful...[br]
|
|
|
|
Before attempting to understand the possibilities of this command,
|
|
|
|
be sure to know how a [doc:dcc_connection]DCC negotiation and connection[/doc] works.[br]
|
|
|
|
The file will be sent as a sequence of packets which must
|
|
|
|
be acknowledged one by one by the active client.[br]
|
|
|
|
There is a special option (see $option()) called "fast send" (also known
|
|
|
|
as "send ahead") that makes KVIrc avoid to wait for the acknowledge
|
|
|
|
of the last packet before sending the next one.[br]
|
|
|
|
Anyway, the connection is declared as successful only
|
|
|
|
when the whole file (all the packets) has been acknowledged.[br]
|
|
|
|
If you need to send a file but you're firewalled, you might take
|
|
|
|
a look at the [cmd]dcc.rsend[/cmd] command. It also handles
|
|
|
|
the mIrc zero port protocol extension.
|
|
|
|
@examples:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
//#warning "Example for -r"
|
|
|
|
//#warning "OPTION FOR NO GUI ? (this is hard...)"
|
|
|
|
//#warning "When in IPv6 mode, should be able to use the IPv4 binding!"
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_send(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget,szFileName;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETER("file name",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szFileName)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
|
|
|
|
d->szNick = szTarget; // we always specify the nickname
|
|
|
|
|
|
|
|
TQString szTmp;
|
|
|
|
KviKvsVariant * pSw = 0;
|
|
|
|
|
|
|
|
if(pSw = c->switches()->find('g',"get"))
|
|
|
|
{
|
|
|
|
d->szFileName = TQFileInfo(szFileName).fileName();
|
|
|
|
|
|
|
|
if(!pSw->isBoolean())
|
|
|
|
{
|
|
|
|
kvs_int_t iSize;
|
|
|
|
if(pSw->asInteger(iSize)) // is an integer
|
|
|
|
{
|
|
|
|
pSw->asString(szTmp);
|
|
|
|
// avoid sprintf as long as possibile
|
|
|
|
d->szFileSize = szTmp;
|
|
|
|
} else {
|
|
|
|
d->szFileSize = __tr_ctx("<unknown size>","dcc");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
d->szFileName = szFileName;
|
|
|
|
d->szLocalFileName = szFileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
|
|
|
|
d->szHost = d->szUser; // host is always unknown
|
|
|
|
d->bRecvFile = pSw != 0;
|
|
|
|
d->bNoAcks = c->switches()->find('b',"blind") || c->switches()->find('t',"tdcc");
|
|
|
|
d->bResume = false;
|
|
|
|
d->bAutoAccept = pSw != 0;
|
|
|
|
d->bIsIncomingAvatar = false;
|
|
|
|
|
|
|
|
if(!dcc_kvs_parse_default_parameters(d,c))return false;
|
|
|
|
|
|
|
|
if(c->switches()->find('c',"connect"))
|
|
|
|
{
|
|
|
|
if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
d->szIp = d->szListenIp;
|
|
|
|
d->szPort = d->szListenPort;
|
|
|
|
d->szListenIp = ""; // useless
|
|
|
|
d->szListenPort = ""; // useless
|
|
|
|
d->bActive = true;
|
|
|
|
} else {
|
|
|
|
d->szIp = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szPort = d->szIp;
|
|
|
|
d->bActive = false;
|
|
|
|
d->bSendRequest = !c->switches()->find('n',"no-ctcp");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->switches()->find('g',"get"))
|
|
|
|
{
|
|
|
|
dcc_module_set_dcc_type(d,"RECV");
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->recvFileManage(d);
|
|
|
|
} else {
|
|
|
|
dcc_module_set_dcc_type(d,"SEND");
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
if(!d->szLocalFileName.isEmpty())
|
|
|
|
{
|
|
|
|
g_pDccBroker->sendFileExecute(0,d);
|
|
|
|
} else {
|
|
|
|
g_pDccBroker->sendFileManage(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.recv
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.recv
|
|
|
|
@short:
|
|
|
|
Sets up a file receiving connection
|
|
|
|
@syntax:
|
|
|
|
dcc.recv [-s] [-t] [-u] [-b] [-n] [-c] [-i=<interface>] [-p=<port>] [-m[=<boolean>]] <nickname> <filename> <remote file size>
|
|
|
|
@switches:
|
|
|
|
!sw: -b | --blind
|
|
|
|
Assume that no acknowledges are sent.
|
|
|
|
Assume that the transfer was successful when the whole file has been sent,
|
|
|
|
then close the socket.[br]
|
|
|
|
This is called a "blind" DCC send.[br]
|
|
|
|
|
|
|
|
!sw: -t | -tdcc
|
|
|
|
Emulate the TDCC protocol: Use the TDCC CTCP message (DCC TSEND) for requesting the connection
|
|
|
|
and assume that no acknowledges are sent. Wait for the remote end to close the connection.[br]
|
|
|
|
|
|
|
|
!sw: -m[=<boolean>] | --minimize[=<boolean>]
|
|
|
|
If the -m switch is passed, the default boolCreateMinimizedDccSend option
|
|
|
|
is overridden with the <boolean> parameter passed. So actually
|
|
|
|
by passing -m=1 will create a minimized DCC send even
|
|
|
|
if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
|
|
|
|
In the same way, by passing -m=0 you will create a non minimized DCC send.
|
|
|
|
If no <boolean> value is specified, it defaults to 1.[br]
|
|
|
|
|
|
|
|
!sw: -n | --no-ctcp
|
|
|
|
Do NOT send the CTCP request to the target user, you will have to do it manually,
|
|
|
|
or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
|
|
|
|
|
|
|
|
!sw: -i=<interface> | --ip=<interface>
|
|
|
|
Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
|
|
|
|
If this switch is NOT specified, the socket is bound to the interface of
|
|
|
|
the current IRC connection (if any) or to "127.0.0.1".[br]
|
|
|
|
You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
|
|
|
|
since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
|
|
|
|
Here go some examples:[br]
|
|
|
|
-i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
|
|
|
|
-i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
|
|
|
|
-i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
|
|
|
|
The -i switch parameter may serve also as a target address when the -c switch is used.[br]
|
|
|
|
|
|
|
|
!sw: -p=<port> | --port=<port>
|
|
|
|
Bind the local listening socket to the specified <port>.
|
|
|
|
If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
|
|
|
|
|
|
|
|
!sw: -a=<fake address> | --fake-address=<fake address>
|
|
|
|
Send the <fake address> as target for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real IP address of the listening
|
|
|
|
interface.[br]
|
|
|
|
|
|
|
|
!sw: -f=<fake port> | --fake-port=<fake port>
|
|
|
|
Send the <fake port> as target port for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real port of the listening socket.
|
|
|
|
[br][br]
|
|
|
|
All these switches are meant to allow maximum flexibility of the
|
|
|
|
DCC negotiation, earlier KVIrc releases had serious problems
|
|
|
|
with firewalled and/or masqueraded machines. With the -a and -f switches
|
|
|
|
you can work around it.[br]
|
|
|
|
[br]
|
|
|
|
|
|
|
|
!sw: -u | --unlimited
|
|
|
|
If the 'u' switch is given, the connection attempt will
|
|
|
|
never time out; this might be useful if you want to leave
|
|
|
|
a listening socket for a friend of yours while you are sleeping
|
|
|
|
and have the CTCP processing disabled. The 'u' switch works either
|
|
|
|
in active and passive mode.[br]
|
|
|
|
|
|
|
|
!sw: -s | --ssl
|
|
|
|
Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
|
|
|
|
with a private key algorithm after a public key handshake.[br]
|
|
|
|
This option will work only if the KVIrc executable has been compiled with SSL support
|
|
|
|
and the remote end supports the SSL protocol too.[br]
|
|
|
|
Please note that this will may down the transfer somewhat.[br]
|
|
|
|
-s can be combined with -t.[br]
|
|
|
|
The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
|
|
|
|
When requesting a SSL based DCC send to someone you probably will need a
|
|
|
|
certificate. If you don't have one, create it (for example with CA.pl -newcert)
|
|
|
|
and set it in the options dialog.
|
|
|
|
|
|
|
|
!sw: -c | --connect
|
|
|
|
Accepted for compatibility: don't use it!
|
|
|
|
@description:
|
|
|
|
Sets up a connection ready to receive a file.[br]
|
|
|
|
In most 'common' cases you will not need this command, you might want to use [cmd]dcc.get[/cmd] instead.[br]
|
|
|
|
This works like dcc.send but has two main differences: The file is INCOMING, and the CTCP sent to the other side
|
|
|
|
is a CTCP RECV.[br]
|
|
|
|
This command is the counterpart of [cmd]dcc.send[/cmd] and its parameters are exactly the same, so please refer to that
|
|
|
|
help page for the full discussion. This help page contains only a brief resume of these parameters.[br]
|
|
|
|
The [doc:dcc_connection]dcc documentation[/doc] explains the DCC Recv subprotocol in detail.[br]
|
|
|
|
@examples:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
//#warning "ENCODE THE CTCP'S!!!!!!!"
|
|
|
|
//#warning "DOCS FOR dcc.recv (examples!)"
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_recv(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget,szFileName;
|
|
|
|
kvs_uint_t uSize;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
|
|
|
|
KVSM_PARAMETER("size",KVS_PT_UINT,0,uSize)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
d->szNick = szTarget;
|
|
|
|
d->szUser = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szHost = d->szUser;
|
|
|
|
d->szIp = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szPort = d->szIp;
|
|
|
|
|
|
|
|
// -c is senseless here...but we accept it for compatibility
|
|
|
|
|
|
|
|
if(!dcc_kvs_parse_default_parameters(d,c))return false;
|
|
|
|
|
|
|
|
d->szFileName = szFileName;
|
|
|
|
d->szFileSize.setNum(uSize);
|
|
|
|
|
|
|
|
d->bActive = false; // we have to listen!
|
|
|
|
d->bResume = false;
|
|
|
|
d->bRecvFile = true; // we have to receive the file!
|
|
|
|
d->bSendRequest = !c->switches()->find('n',"no-ctcp");
|
|
|
|
d->bNoAcks = d->bIsTdcc || c->switches()->find('b',"blind");
|
|
|
|
d->bAutoAccept = KVI_OPTION_BOOL(KviOption_boolAutoAcceptDccSend);
|
|
|
|
d->bIsIncomingAvatar = g_pApp->findPendingAvatarChange(d->console(),d->szNick,d->szFileName);
|
|
|
|
|
|
|
|
if(KVI_OPTION_BOOL(KviOption_boolAutoAcceptIncomingAvatars))d->bAutoAccept = d->bAutoAccept || d->bIsIncomingAvatar;
|
|
|
|
dcc_module_set_dcc_type(d,"RECV");
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->recvFileManage(d);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.rsend
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.rsend
|
|
|
|
@short:
|
|
|
|
Sends a file by using the Reverse DCC Send protocol
|
|
|
|
@syntax:
|
|
|
|
dcc.rsend [-s] [-t] <nickname> [filename]
|
|
|
|
@switches:
|
|
|
|
!sw: -t | -tdcc
|
|
|
|
Emulate the TDCC protocol.
|
|
|
|
|
|
|
|
!sw: -s | --ssl
|
|
|
|
Use a Secure Socket Layer for the transfer; the whole communication will be encrypted
|
|
|
|
with a private key algorithm after a public key handshake.[br]
|
|
|
|
This option will work only if the KVIrc executable has been compiled with SSL support
|
|
|
|
and the remote end supports the SSL protocol too.[br]
|
|
|
|
Please note that this will may down the transfer somewhat.[br]
|
|
|
|
-s can be combined with -t.[br]
|
|
|
|
The CTCP negotiation will use SSEND as parameter (or eventually TSSEND).[br]
|
|
|
|
When requesting a SSL based DCC send to someone you probably will need a
|
|
|
|
certificate. If you don't have one, create it (for example with CA.pl -newcert)
|
|
|
|
and set it in the options dialog.
|
|
|
|
!sw: -z | --zero-port
|
|
|
|
Use the 0 port method. This is a dirty hack that allows you to use the RSEND
|
|
|
|
protocol with mIrc receiving clients.
|
|
|
|
@description:
|
|
|
|
Sends a DCC RSEND request to <nickname> notifying him that you want to
|
|
|
|
send him the file [filename].[br]
|
|
|
|
The remote end may acknowledge the request by sending a DCC RECV request.
|
|
|
|
This command effects are similar to [cmd]dcc.send[/cmd], but will work also on machines
|
|
|
|
that can't accept incoming connections (firewalling or masquerading problems).[br]
|
|
|
|
A 120 seconds file offer is added for the specified file and mask "<nickname>!*@*".
|
|
|
|
@examples:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
//#warning "ENCODE THE CTCP'S!!!!!!!"
|
|
|
|
//#warning "DOCS FOR dcc.rsend"
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_rsend(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget,szFileName;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,KVS_PF_OPTIONAL,szFileName)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KVSM_RETQUIRE_CONNECTION(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
d->szNick = szTarget;
|
|
|
|
d->szLocalFileName = szFileName;
|
|
|
|
d->bIsTdcc = c->switches()->find('t',"tdcc");
|
|
|
|
#ifdef COMPILE_SSL_SUPPORT
|
|
|
|
d->bIsSSL = c->switches()->find('s',"ssl");
|
|
|
|
#else
|
|
|
|
if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable has been built without SSL support, -s switch ignored","dcc"));
|
|
|
|
#endif //!COMPILE_SSL_SUPPORT
|
|
|
|
|
|
|
|
if(c->switches()->find('z',"zero-port"))
|
|
|
|
{
|
|
|
|
dcc_module_set_dcc_type(d,"SEND");
|
|
|
|
d->setZeroPortRequestTag("nonempty"); // just to tag it
|
|
|
|
} else
|
|
|
|
dcc_module_set_dcc_type(d,"RSEND");
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->rsendManage(d);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.get
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.get
|
|
|
|
@short:
|
|
|
|
Requests a file
|
|
|
|
@syntax:
|
|
|
|
dcc.get [-s] [-t] <nickname> <filename> [filesize]
|
|
|
|
@description:
|
|
|
|
Sends a CTCP DCC GET to <nickname> requesting the file <filename>.
|
|
|
|
The remote end should reply with a DCC SEND request CTCP.
|
|
|
|
<filename> must not contain any leading path.
|
|
|
|
If the -t switch is given, the message is a DCC TGET, expecting
|
|
|
|
a TSEND reply.[br]
|
|
|
|
If the -s switch is given, the message will be a DCC SGET, expecting
|
|
|
|
a SSEND reply.[br]
|
|
|
|
-t and -s can be combined together to obtain a "turbo"+"SSL" extension transfer.[br]
|
|
|
|
-s will work only if the KVIrc executable has been compiled with SSL support and
|
|
|
|
the remote client supports it.[br]
|
|
|
|
@examples:
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
//#warning "ENCODE THE CTCP'S!!!!!!!"
|
|
|
|
//#warning "DOCS FOR dcc.get"
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_get(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget,szFileName;
|
|
|
|
kvs_uint_t uSize;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETER("filename",KVS_PT_NONEMPTYSTRING,0,szFileName)
|
|
|
|
KVSM_PARAMETER("size",KVS_PT_UINT,KVS_PF_OPTIONAL,uSize)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KVSM_RETQUIRE_CONNECTION(c)
|
|
|
|
|
|
|
|
KviTQString::cutToLast(szFileName,'/');
|
|
|
|
|
|
|
|
if(szFileName.contains(' '))
|
|
|
|
{
|
|
|
|
szFileName.prepend('"');
|
|
|
|
szFileName.append('"');
|
|
|
|
}
|
|
|
|
|
|
|
|
KviStr szDCC("GET");
|
|
|
|
#ifdef COMPILE_SSL_SUPPORT
|
|
|
|
if(c->switches()->find('s',"ssl"))szDCC.prepend('S');
|
|
|
|
#else
|
|
|
|
if(c->switches()->find('s',"ssl"))c->warning(__tr2qs_ctx("This executable has no SSL support, -s switch ignored","dcc"));
|
|
|
|
#endif
|
|
|
|
if(c->switches()->find('t',"tdcc"))szDCC.prepend('T');
|
|
|
|
|
|
|
|
if(uSize == 0)
|
|
|
|
{
|
|
|
|
c->window()->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s%c",
|
|
|
|
c->window()->console()->connection()->encodeText(szTarget).data(),
|
|
|
|
0x01,
|
|
|
|
c->window()->console()->connection()->encodeText(szDCC.ptr()).data(),
|
|
|
|
c->window()->console()->connection()->encodeText(szFileName).data(),
|
|
|
|
0x01);
|
|
|
|
} else {
|
|
|
|
c->window()->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC %s %s %u%c",
|
|
|
|
c->window()->console()->connection()->encodeText(szTarget).data(),
|
|
|
|
0x01,
|
|
|
|
c->window()->console()->connection()->encodeText(szDCC.ptr()).data(),
|
|
|
|
c->window()->console()->connection()->encodeText(szFileName).data(),
|
|
|
|
uSize,0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME: SSL support for DCC VOICE ? (has a sense ?)
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.voice
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.voice
|
|
|
|
@short:
|
|
|
|
Starts a DCC Voice connection
|
|
|
|
@syntax:
|
|
|
|
dcc.voice [-g=<codec>] [-n] [-c] [-u] [-h=<sample_rate_in_hz>] [-m[=<boolean>]] [-i=<interface>] [-p=<port>] [-a=<fake address>] [-f=<fake port>] <nickname>
|
|
|
|
@switches:
|
|
|
|
!sw: -g=<codec> | --codec=<codec>
|
|
|
|
Use the codec specified as parameter.
|
|
|
|
Actually the supported codecs are "null","adpcm" and "gsm".
|
|
|
|
|
|
|
|
!sw: -h=<rate> | --sample-rate=<rate>
|
|
|
|
Use the sample rate specified by <rage>.
|
|
|
|
Valid sample rates are 8000, 11025, 22050 and 44100 Hz.
|
|
|
|
|
|
|
|
!sw: -m[=<boolean>] | --minimize[=<boolean>]
|
|
|
|
If the -m switch is passed, the default boolCreateMinimizedDccSend option
|
|
|
|
is overridden with the <boolean> parameter passed. So actually
|
|
|
|
by passing -m=1 will create a minimized DCC send even
|
|
|
|
if the [fnc]$option[/fnc](boolCreateMinimizedDccSend) returns false.[br]
|
|
|
|
In the same way, by passing -m=0 you will create a non minimized DCC send.
|
|
|
|
If no <boolean> value is specified, it defaults to 1.[br]
|
|
|
|
|
|
|
|
!sw: -n | --no-ctcp
|
|
|
|
Do NOT send the CTCP request to the target user, you will have to do it manually,
|
|
|
|
or the remote user will have to connect manually (for example by using dcc.recv -c).[br]
|
|
|
|
|
|
|
|
!sw: -c | --connect
|
|
|
|
Attempt to CONNECT to the remote host specified as <interface> and <port>,
|
|
|
|
instead of listening (active connection instead of a passive one).
|
|
|
|
In this case the -i and -p switches are mandatory.[br]
|
|
|
|
The 'c' switch takes precedence over 'n' (In fact both should
|
|
|
|
be mutually exclusive).[br]
|
|
|
|
If the 'c' and 'n' switches are missing, this commands
|
|
|
|
needs to be executed in a window that is bound to a connected
|
|
|
|
IRC context (you need a third entity to accomplish the negotiation).[br]
|
|
|
|
|
|
|
|
!sw: -i=<interface> | --ip=<interface>
|
|
|
|
Bind the local listening socket to the specified <interface> (which is an IP address, IPv4 or IPv6).
|
|
|
|
If this switch is NOT specified, the socket is bound to the interface of
|
|
|
|
the current IRC connection (if any) or to "127.0.0.1".[br]
|
|
|
|
You can also specify a local interface name to get the address from (this works only for IPv4 interfaces
|
|
|
|
since IPv6 ones seems to be unsupported by the system ioctl() calls at the moment (for linux at least)).[br]
|
|
|
|
Here go some examples:[br]
|
|
|
|
-i=215.243.12.12: this will bind to the IPv4 interface with the specified address.[br]
|
|
|
|
-i=3ffe:1001::1: this will bind to the IPv6 interface with the specified address.[br]
|
|
|
|
-i=ppp0: this will bind to the IPv4 address of the interface ppp0 (if supported by the underlying system).[br]
|
|
|
|
The -i switch parameter may serve also as a target address when the -c switch is used.[br]
|
|
|
|
|
|
|
|
!sw: -p=<port> | --port=<port>
|
|
|
|
Bind the local listening socket to the specified <port>.
|
|
|
|
If this switch is NOT specified, the port will be a "random" one choosen by the kernel.[br]
|
|
|
|
|
|
|
|
!sw: -a=<fake address> | --fake-address=<fake address>
|
|
|
|
Send the <fake address> as target for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real IP address of the listening
|
|
|
|
interface.[br]
|
|
|
|
|
|
|
|
!sw: -f=<fake port> | --fake-port=<fake port>
|
|
|
|
Send the <fake port> as target port for the remote client in the requesting CTCP message.
|
|
|
|
If this switch is not given, the CTCP will contain the real port of the listening socket.
|
|
|
|
[br][br]
|
|
|
|
All these switches are meant to allow maximum flexibility of the
|
|
|
|
DCC negotiation, earlier KVIrc releases had serious problems
|
|
|
|
with firewalled and/or masqueraded machines. With the -a and -f switches
|
|
|
|
you can work around it.[br]
|
|
|
|
[br]
|
|
|
|
|
|
|
|
!sw: -u | --unlimited
|
|
|
|
If the 'u' switch is given, the connection attempt will
|
|
|
|
never time out; this might be useful if you want to leave
|
|
|
|
a listening socket for a friend of yours while you are sleeping
|
|
|
|
and have the CTCP processing disabled. The 'u' switch works either
|
|
|
|
in active and passive mode.[br]
|
|
|
|
|
|
|
|
@description:
|
|
|
|
Attempts a DCC Voice connection to <nickname>.[br]
|
|
|
|
The -g option is used to select the GSM codec, available codecs are "gsm", "adpcm" and "null".[br]
|
|
|
|
The adpcm codec is the one that was used in previous KVIrc versions, it provides a 1:4 compression rate
|
|
|
|
and is designed for 8 KHz audio sampling rate (but will work also with other sampling rates).[br]
|
|
|
|
The gsm codec offers 1:10 compression at the cost of some quality and cpu time. If you have a good
|
|
|
|
cpu and plan to transmit voice only, use this codec.<br> The null codec
|
|
|
|
offers no compression and may be used to transfer plain audio data over a fast connection (usually loopback
|
|
|
|
connection or local networks). The null codec with 44100 sampling rate would provide CD quality audio
|
|
|
|
streaming, but it is practically not usable (at the time I'm writing) since requires a
|
|
|
|
monster bandwidth. If the -g switch is not present, the adpcm codec is used by default (for compatibility reasons).[br]
|
|
|
|
The -h switch is used to select the sampling rate, if not given the sampling rate defaults to 8000 Hz.
|
|
|
|
This switch accepts any value, but in fact the soundcards have limits on the values. Typically
|
|
|
|
the lowest limit is 5 KHz and the upper limit is 44.1 KHz (but some soundcards support 96 KHz).
|
|
|
|
It is also possible that the soundcard can't support a continous range of frequencies and
|
|
|
|
will select a discrete closest match instead.[br]
|
|
|
|
The "commonly used" sample rates are 8000, 11025, 22050 and 44100 Hz.[br]
|
|
|
|
The remaining parameters are equivalent to the ones used in [cmd]dcc.send[/cmd], so please refer to that
|
|
|
|
help page for the full discussion. This help page contains only a brief resume of these parameters.[br]
|
|
|
|
@examples:
|
|
|
|
[example]
|
|
|
|
[comment]# Setup a DCC VOICE connection with Pragma (IRC user)[/comment]
|
|
|
|
dcc.voice Pragma
|
|
|
|
[comment]# Setup a DCC VOICE connection with Pragma and use the gsm codec[/comment]
|
|
|
|
dcc.voice -g=gsm Pragma
|
|
|
|
[comment]# Setup a DCC VOICE connection with Pragma, use the gsm codec and 22050 Hz sampling rate[/comment]
|
|
|
|
dcc.voice -g=gsm -h=22050 Pragma
|
|
|
|
[comment]# Setup a listening socket for a DCC VOICE connection on interface 127.0.0.1 and port 8088[/comment]
|
|
|
|
dcc.voice -n -i=127.0.0.1 -p=8088 Pippo
|
|
|
|
[comment]# Connect to the socket above[/comment]
|
|
|
|
dcc.voice -c -i=127.0.0.1 -p=8088 Pluto
|
|
|
|
[comment]# Same as above but use the NULL codec with 11025 Hz sampling rate[/comment]
|
|
|
|
dcc.voice -g=null -h=11025 -n -i=127.0.0.1 -p=8088 Pippo
|
|
|
|
[comment]# Connect to the socket above[/comment]
|
|
|
|
dcc.voice -g=null -h=11025 -c -i=127.0.0.1 -p=8088 Pluto
|
|
|
|
[/example]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_voice(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
TQString szTarget;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("target",KVS_PT_NONEMPTYSTRING,0,szTarget)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
#ifdef COMPILE_DISABLE_DCC_VOICE
|
|
|
|
c->warning(__tr2qs_ctx("DCC VOICE support not enabled at compilation time","dcc"));
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
|
|
|
|
d->szNick = szTarget; // we always specify the nickname
|
|
|
|
d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
|
|
|
|
d->szHost = d->szUser; // host is always unknown
|
|
|
|
d->iSampleRate = 8000;
|
|
|
|
|
|
|
|
if(!dcc_kvs_parse_default_parameters(d,c))return false;
|
|
|
|
|
|
|
|
if(KviKvsVariant * pSR = c->switches()->find('h',"sample-rate"))
|
|
|
|
{
|
|
|
|
kvs_int_t iSR;
|
|
|
|
if(!pSR->asInteger(iSR))
|
|
|
|
{
|
|
|
|
c->warning(__tr2qs_ctx("Invalid sample rate specified, defaulting to 8000","dcc"));
|
|
|
|
d->iSampleRate = 8000;
|
|
|
|
} else {
|
|
|
|
d->iSampleRate = iSR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->szCodec = "adpcm";
|
|
|
|
|
|
|
|
if(KviKvsVariant * pCodec = c->switches()->find('g',"codec"))
|
|
|
|
{
|
|
|
|
TQString szCodec;
|
|
|
|
pCodec->asString(szCodec);
|
|
|
|
|
|
|
|
if(!kvi_dcc_voice_is_valid_codec(szCodec))
|
|
|
|
{
|
|
|
|
c->warning(__tr2qs_ctx("Invalid codec specified, defaulting to 'adpcm'","dcc"));
|
|
|
|
d->szCodec = "adpcm";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dcc_module_set_dcc_type(d,"VOICE");
|
|
|
|
if(c->switches()->find('c',"connect"))
|
|
|
|
{
|
|
|
|
if(!(c->switches()->find('i',"ip") && c->switches()->find('p',"port")))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
c->error(__tr2qs_ctx("-c requires -i and -p","dcc"));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
d->szIp = d->szListenIp;
|
|
|
|
d->szPort = d->szListenPort;
|
|
|
|
d->szListenIp = ""; // useless
|
|
|
|
d->szListenPort = ""; // useless
|
|
|
|
d->bActive = true;
|
|
|
|
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->activeVoiceExecute(0,d);
|
|
|
|
} else {
|
|
|
|
d->szIp = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szPort = d->szIp;
|
|
|
|
d->bActive = false;
|
|
|
|
d->bSendRequest = !(c->switches()->find('n',"no-ctcp"));
|
|
|
|
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->passiveVoiceExecute(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
static bool dcc_module_cmd_canvas(KviModule *m,KviCommand *c)
|
|
|
|
{
|
|
|
|
ENTER_STACK_FRAME(c,"dcc_module_cmd_canvas");
|
|
|
|
|
|
|
|
KviStr target;
|
|
|
|
if(!g_pUserParser->parseCmdFinalPart(c,target))return false;
|
|
|
|
|
|
|
|
if(target.isEmpty())return c->error(KviError_notEnoughParameters,"%s",__tr_ctx("Missing target nickname","dcc"));
|
|
|
|
|
|
|
|
KviDccDescriptor * d = new KviDccDescriptor(c->window()->console());
|
|
|
|
|
|
|
|
d->szNick = target.ptr(); // we always specify the nickname
|
|
|
|
d->szUser = __tr2qs_ctx("unknown","dcc"); // username is always unknown
|
|
|
|
d->szHost = d->szUser; // host is always unknown
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
d->bIsTdcc = c->hasSwitch('t');
|
|
|
|
|
|
|
|
d->bOverrideMinimize = c->hasSwitch('m');
|
|
|
|
|
|
|
|
if(d->bOverrideMinimize)
|
|
|
|
{
|
|
|
|
KviStr tmpVal;
|
|
|
|
if(!(c->getSwitchValue('m',tmpVal)))d->bShowMinimized = false;
|
|
|
|
else d->bShowMinimized = kvi_strEqualCI(tmpVal.ptr(),"1");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(!d->console())
|
|
|
|
{
|
|
|
|
// We don't need a console with -c and -n , otherwise we need it
|
|
|
|
if(!(c->hasSwitch('c') || c->hasSwitch('n')))return c->noIrcContext();
|
|
|
|
else d->console() = c->window()->frame()->firstConsole();
|
|
|
|
}
|
|
|
|
|
|
|
|
__range_valid(d->console());
|
|
|
|
|
|
|
|
if(!d->console()->isConnected())
|
|
|
|
{
|
|
|
|
// We don't need a connection with -c and -n , otherwise we need it
|
|
|
|
if(!(c->hasSwitch('c') || c->hasSwitch('n')))return c->notConnectedToServer();
|
|
|
|
else {
|
|
|
|
// -c or -n , grab a local nick from somewhere
|
|
|
|
d->szLocalNick = KVI_OPTION_STRING(KviOption_stringNickname1);
|
|
|
|
d->szLocalNick.stripWhiteSpace();
|
|
|
|
if(d->szLocalNick.isEmpty())d->szLocalNick = KVI_DEFAULT_NICKNAME1;
|
|
|
|
d->szLocalUser = __tr("unknown"); // we can live without it
|
|
|
|
d->szLocalHost = d->szLocalUser; // we can live without it
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We know everything
|
|
|
|
d->szLocalNick = d->console()->currentNickName();
|
|
|
|
d->szLocalUser = d->console()->currentUserName();
|
|
|
|
d->szLocalHost = d->console()->currentLocalHostName();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(c->hasSwitch('i'))
|
|
|
|
{
|
|
|
|
c->getSwitchValue('i',d->szListenIp);
|
|
|
|
if(!(d->szListenIp.contains('.') || d->szListenIp.contains(':')))
|
|
|
|
{
|
|
|
|
// This will magically work with the same buffer as source and dst!
|
|
|
|
if(!kvi_getInterfaceAddress(d->szListenIp.ptr(),d->szListenIp))
|
|
|
|
{
|
|
|
|
return c->error(KviError_invalidParameter,__tr("Can't get address of interface %s"),d->szListenIp.ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(d->console()->isConnected())
|
|
|
|
{
|
|
|
|
d->console()->socket()->getLocalHostIp(d->szListenIp,d->console()->isIpV6Connection());
|
|
|
|
} else d->szListenIp = "127.0.0.1"; // huh ? :)
|
|
|
|
}
|
|
|
|
|
|
|
|
if(c->hasSwitch('p'))c->getSwitchValue('p',d->szListenPort);
|
|
|
|
else d->szListenPort = "0"; // any port is ok
|
|
|
|
|
|
|
|
if(c->hasSwitch('a'))c->getSwitchValue('a',d->szFakeIp);
|
|
|
|
|
|
|
|
if(c->hasSwitch('f'))c->getSwitchValue('f',d->szFakePort);
|
|
|
|
|
|
|
|
d->bDoTimeout = (!c->hasSwitch('u'));
|
|
|
|
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
if(!dcc_module_parse_default_parameters(d,c))return false;
|
|
|
|
dcc_module_set_dcc_type(d,"VOICE");
|
|
|
|
|
|
|
|
if(c->hasSwitch('c'))
|
|
|
|
{
|
|
|
|
if(!(c->hasSwitch('i') && c->hasSwitch('p')))
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
return c->error(KviError_notEnoughParameters,__tr_ctx("-c requires -i and -p","dcc"));
|
|
|
|
}
|
|
|
|
d->szIp = d->szListenIp;
|
|
|
|
d->szPort = d->szListenPort;
|
|
|
|
d->szListenIp = ""; // useless
|
|
|
|
d->szListenPort = ""; // useless
|
|
|
|
d->bActive = true;
|
|
|
|
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->activeCanvasExecute(0,d);
|
|
|
|
} else {
|
|
|
|
d->szIp = __tr2qs_ctx("unknown","dcc");
|
|
|
|
d->szPort = d->szIp;
|
|
|
|
d->bActive = false;
|
|
|
|
d->bSendRequest = !c->hasSwitch('n');
|
|
|
|
|
|
|
|
d->triggerCreationEvent();
|
|
|
|
g_pDccBroker->passiveCanvasExecute(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
return c->leaveStackFrame();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc_connection
|
|
|
|
@type:
|
|
|
|
generic
|
|
|
|
@title:
|
|
|
|
DCC negotiation and connection
|
|
|
|
@short:
|
|
|
|
Overview of the DCC internals
|
|
|
|
@keyterms:
|
|
|
|
DCC without IRC
|
|
|
|
@body:
|
|
|
|
[big]What is DCC?[/big][br]
|
|
|
|
'DCC' stands for Direct Client Connection, it is used to exchange data
|
|
|
|
directly between two IRC clients (with no IRC server in the middle).[br]
|
|
|
|
DCC itself is not a well-defined protocol, but rather a set of
|
|
|
|
subprotocols with (more or less) standardized rules.[br]
|
|
|
|
Sub-protocols are also (historically) called [b]"DCC types"[/b]; this term often
|
|
|
|
leads to confusion and it will become clear later.[br]
|
|
|
|
Each subprotocol has two main parts: The [b]DCC negotiation[/b] and the [b]DCC transfer[/b].[br]
|
|
|
|
The [b]DCC negotiation[/b] part is used to request the [b]DCC transfer[/b] and define its necessary parameters,[br]
|
|
|
|
while the [b]DCC transfer[/b] part is the real data transfer between clients.[br]
|
|
|
|
The [b]DCC negotiation[/b] requires a third entity that routes the negotiation data between clients,
|
|
|
|
this is usually an IRC server.[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Negotiation[/big][br]
|
|
|
|
This part of the protocol is the most tricky and difficult one, and is different for almost every DCC subprotocol.[br]
|
|
|
|
The "constant" scenario of the negotiation is more or less the following:[br]
|
|
|
|
There are two IRC clients connected to the same IRC network and they want to exchange some data in
|
|
|
|
a direct client connection.[br]
|
|
|
|
Each client knows the other by nickname only (and eventually by the host displayed by the IRC server,
|
|
|
|
but this cannot be trusted for several reasons), and can send text messages to each other by using the
|
|
|
|
IRC network as data channel.[br]
|
|
|
|
To initiate a direct client connection, one of the clients must start listening on some port (this is called [b]passive client[/b])
|
|
|
|
and the other must connect to that port on the first client's machine (this is the [b]active client[/b]).[br]
|
|
|
|
Both clients must agree on who is the passive and who is the active client. The active client must also
|
|
|
|
know the passive client's IP address and port (in order to be able to contact it).[br]
|
|
|
|
Finally, both clients must agree on the transfer type that has to be initiated.[br]
|
|
|
|
The negotiation exchanges these informations between clients by using IRC as channel and CTCP messages
|
|
|
|
as encoding method.[br]
|
|
|
|
An example will make things clearer:[br]
|
|
|
|
DCC Chat is the simplest (and most widely implemented) DCC subprotocol:
|
|
|
|
it is used to exchange <cr><lf> separated text data between clients.[br]
|
|
|
|
Assume that you want to establish a DCC Chat
|
|
|
|
connection to 'Sarah' that is actually connected to your IRC network (so
|
|
|
|
she/he is an IRC user just like you).
|
|
|
|
All you have to do is type sth as "/dcc chat Sarah" in your IRC client.
|
|
|
|
The client will setup a listening socket on a random port choosen
|
|
|
|
usually by the kernel of your OS. In this case YOU are the [b]passive client[/b], and Sarah is the active one.[br]
|
|
|
|
Once the socket is ready to accept connections,
|
|
|
|
your client will send a [doc:ctcp_handling]CTCP message[/doc] to Sarah using the IRC connection (and protocol) as channel:[br]
|
|
|
|
PRIVMSG Sarah :<0x01>DCC CHAT chat <ip_address> <port><0x01>[br]
|
|
|
|
where <ip_address> is the address of the listening socket and <port>
|
|
|
|
is the port that it has been bound to (these informations are obtained
|
|
|
|
after the socket has been setup). Once Sarah has received the CTCP message,
|
|
|
|
and agreed to connect, her (active) client will attempt to connect to the
|
|
|
|
specified <ip_address> and <port> (eg. to your listening socket).[br]
|
|
|
|
Once the connection has been established, it continues using the
|
|
|
|
specific CHAT transfer protocol.[br]
|
|
|
|
Some IRC clients allow modifications of this procedure:[br]
|
|
|
|
First of all, the port to listen on can be specified by the user
|
|
|
|
and not by the kernel; this is useful when the passive client
|
|
|
|
is behind a firewall that "shades" some sets of ports.
|
|
|
|
The ip address for the listening socket
|
|
|
|
can be specified by the user as well (especially when the machine has more than one network interface).[br]
|
|
|
|
A more challenging trick is to listen on a specified ip address and port
|
|
|
|
and notify different ones to the remote user (eg, <ip_address> and <port>
|
|
|
|
parameters of the CTCP message are not the ones that the client is listening on).
|
|
|
|
This is especially useful with "transparent proxy" firewalls that
|
|
|
|
often are not transparent enough to allow the DCC connections.
|
|
|
|
(If you have one of these firewalls you know what I'm talking about,
|
|
|
|
otherwise just read on). KVIrc allows to avoid the usage of a third entity
|
|
|
|
for the protocol negotiation too.
|
|
|
|
You can setup a listening socket on a specified port and ip address
|
|
|
|
without notyfying anyone of this.
|
|
|
|
You can also manually connect to a specified port and ip address without
|
|
|
|
having been notified of a DCC request.[br][br][br]
|
|
|
|
Is everything clear ?...I don't think so... my English is really too bad...
|
|
|
|
[br]
|
|
|
|
[big]DCC Transfer[/big][br]
|
|
|
|
The DCC transfer part is different for every DCC subprotocol, but
|
|
|
|
it always happens over a direct client to client TCP connection.[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Subprotocols[/big][br]
|
|
|
|
There are two main standardized DCC subprotocols that are widely implemented in IRC clients:
|
|
|
|
[b]DCC Chat[/b] and [b]DCC Send[/b].[br]
|
|
|
|
DCC Chat is quite simple and the protocol is more or less completely defined.[br]
|
|
|
|
DCC Send is a *real mess*, the original definition was not very flexible
|
|
|
|
so many IRC clients tried to enchance both the negotiation and the transfer, leading
|
|
|
|
often to incompatible implementations. (I can remember the Turbo File Transfer implemented
|
|
|
|
by VIrc, the Send-Ahead enchancement implemented in many clients, the RESUME facility...)[br]
|
|
|
|
Many clients introduced new DCC subprotocols with non-standard implementations,
|
|
|
|
leading again to client incompatibility.[br]
|
|
|
|
Some of the notable subprotocols are DCC Voice, DCC Draw, DCC Whiteboard...[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Chat[/big][br]
|
|
|
|
This is the simplest and most standardized DCC subprotocol. Almost every IRC client implements it.[br]
|
|
|
|
It is used to exchange lines of text between the two clients.[br]
|
|
|
|
The negotiation is quite simple, we assume that Client A wants to establish a DCC Chat connection to Client B.
|
|
|
|
Client A sets up a listening socket and retrieves its adress (ip address and port).[br]
|
|
|
|
Once the socket is ready Client A sends a CTCP request to B, in the following form:[br]
|
|
|
|
[b]DCC CHAT chat <ipaddress> <port>[/b][br]
|
|
|
|
Where <ipaddress> is a string representing an positive integer that is the A socket's IP address
|
|
|
|
in network byte order, and where <port> is a string representing an positive integer that is the
|
|
|
|
A socket's port.[br]
|
|
|
|
The original purpose of the second "chat" string in the CTCP request is quite obscure, it was probably
|
|
|
|
introduced to have the <ipaddress> as second parameter, as in the DCC Send subprotocol.[br]
|
|
|
|
Client B receives the CTCP, parses it, eventually asks the user for permission and connects
|
|
|
|
to the specified ip address and port.
|
|
|
|
The transfer protocol is quite simple, both clients can send text lines separated by <cr><lf> pairs.[br]
|
|
|
|
Some clients use only <lf> as line terminator so the general idea is that one of <cr> <cr><lf> or <lf>
|
|
|
|
can be used as line terminator.[br]
|
|
|
|
As extension to the protocol, KVIrc allows <ipaddress> to be an IPv6 address in the standard hexadecimal
|
|
|
|
notation, the connection will be made over the IPv6 protocol in this case (obviously if both clients
|
|
|
|
support this feature).[br]
|
|
|
|
(It is not clear why the original DCC specification used the unsigned int format instead of a
|
|
|
|
standard string representation of the IP address... missing inet_aton() function on the target system?).[br]
|
|
|
|
KVIrc adds the Secure Sockets Layer to the DCC Chat protocol. In this case the negotiation string becomes:[br]
|
|
|
|
[b]DCC SCHAT chat <ipaddress> <port>[/b][br]
|
|
|
|
where "SCHAT" stands for Secure CHAT.[br] The external protocol is exactly the same but is built on top of a Secure Sockets Layer
|
|
|
|
implementation (specifically OpenSSL). The connection will be encrypted with a private key algorithm after
|
|
|
|
a public key handshake.[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Send[/big][br]
|
|
|
|
DCC Send is another standard subprotocol. Most clients implement this as well, many have tried
|
|
|
|
to enchance it.[br]
|
|
|
|
The basic DCC Send protocol allows transferring a file from the requesting client to the receiving client.[br]
|
|
|
|
The requesting client (the one that sends the file) is always passive and the receiving client is always active.[br]
|
|
|
|
This is a huge protocol limitation since firewalled clients are often unable to accept incoming connections.[br]
|
|
|
|
The negotiation protocol is more complex than DCC Chat; we assume that Client A wants to send the file F to Client B.[br]
|
|
|
|
Client A sets up a listening socket and retrieves its ip address and port.[br]
|
|
|
|
Client A sends a CTCP request to Client B in the following form:[br]
|
|
|
|
[b]DCC SEND <filename> <ipaddress> <port> <filesize>[/b][br]
|
|
|
|
<ipaddress> and <port> have the same semantics as in the DCC Chat subprotocol.[br]
|
|
|
|
<filename> is the name (without path!) of the file to be sent, and <filesize> is (yeah), the file size.[br]
|
|
|
|
Client B receives the CTCP, parses it, eventually asks the user for confirmation and connects to the
|
|
|
|
specified ip address and port; the transfer then begins.[br]
|
|
|
|
Client A sends blocks of data (usually 1-2 KB) and at every block awaits confirmation from the Client B,
|
|
|
|
that when receiving a block should reply 4 bytes containing an positive number specifying the total size
|
|
|
|
of the file received up to that moment.[br]
|
|
|
|
The transmission closes when the last acknowledge is received by Client A.[br]
|
|
|
|
The acknowledges were meant to include some sort of coherency check in the transmission, but in fact
|
|
|
|
no client can "recover" from an acknowledge error/desync, all of them just close the connection declaring the
|
|
|
|
transfer as failed (the situation is even worse in fact, often acknowledge errors aren't even detected!).[br]
|
|
|
|
Since the packet-acknowledge round trip eats a lot of time, many clients included
|
|
|
|
the "send-ahead" feature; the Client A does NOT wait for the acknowledge of the first packet before sending the second one.[br]
|
|
|
|
The acknowledges are still sent, but just a reverse independent stream.[br] This makes the DCC Send considerably faster.[br]
|
|
|
|
Since the acknowledge stream has non-zero bandwidth usage, no client can recover from an acknowledge error and
|
|
|
|
having them as an independant stream is more or less like having no acknowledges, the "Turbo" ( :) ) extension has been added:
|
|
|
|
Client B will send no acknowledges and will just close the connection when he has received all the expected data.[br]
|
|
|
|
This makes the DCC Send as fast as FTP transfers.[br]
|
|
|
|
The "Turbo" extension is specified during the negotiation phase, bu using TSEND as DCC message type (instead of SEND).[br]
|
|
|
|
The "Turbo" extension is not widely implemented.[br]
|
|
|
|
Later implementations have added the support for resuming interrupted DCC Send transfers:[br]
|
|
|
|
Client A sets up the socket and sends the CTCP request as before.[br]
|
|
|
|
If Client B discovers that the file has been partially received in a previous DCC Send session it sends
|
|
|
|
a resume request in the following form:[br]
|
|
|
|
[b]DCC RESUME <filename> <port> <resume position>[/b][br]
|
|
|
|
Where <port> is the <port> sent in the DCC SEND request and <resume position> is the position in the file
|
|
|
|
from where the transfer should start.[br]
|
|
|
|
Cilent A receives the request, parses it and eventually replies with:[br]
|
|
|
|
[b]DCC ACCEPT <filename> <port> <resume position>[/b][br]
|
|
|
|
Client B receives the ACCEPT message, connects to Client A and the transfer initiates as before.[br]
|
|
|
|
The "Send-ahead" and "Turbo" extensions can obviously be used also in this case (But 'T' is NOT prepended to the RESUME and ACCEPT messages).[br]
|
|
|
|
The IPv6 extension can be used also in this subprotocol, so <ipaddress> can be also an IPv6 address in hexadecimal notation.[br]
|
|
|
|
KVIrc introduces the SSL extension also to DCC Send. The protocol remains the same again but it is built on top of
|
|
|
|
a Secure Sockets Layer implementation just like DCC Chat.[br]
|
|
|
|
With SSL the negotiation string becomes:[br]
|
|
|
|
[b]DCC SSEND <filename> <ipaddress> <port> <filesize>[/b][br]
|
|
|
|
where "SSEND" stands for Secure SEND.[br]
|
|
|
|
The "turbo" extension can be combined with the SSL extension too. In this case the second parameter
|
|
|
|
of the negotiation string must be "TSSEND" or "STSEND".[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Recv[/big][br]
|
|
|
|
DCC Recv is the counterpart of DCC Send. This is a KVIrc extension and is not standard yet.[br]
|
|
|
|
The purpose of this subprotocol will not be immediately clear, but read on for an explanation.[br]
|
|
|
|
It is used to request a file from another client; we assume that Client A knows that Client B has
|
|
|
|
a specific file and is able/wants to send it.[br]
|
|
|
|
Client A sets up a listening socket, retrieves its address and port and then
|
|
|
|
sends a CTCP request to Client B in the following form:[br]
|
|
|
|
[b]DCC RECV <filename> <ipaddress> <port> <resume position>[/b][br]
|
|
|
|
where <filename> is the name of the requested file without path, <ipaddress> and <port> have the usual meaning and <resume position>
|
|
|
|
is the position from that the transfer should start from.[br]
|
|
|
|
<ipaddress> can be an IPv6 address as well.[br]
|
|
|
|
Client B receives the CTCP message, parses it, looks for the file to send (in some unspecified way)
|
|
|
|
and connects to the specified ip address and port. The transfer then begins just as in the DCC send, but in the inverse way:
|
|
|
|
Client B sends blocks of data to Client A and Client B sends back acknowledges.[br]
|
|
|
|
This subprotocol is useful in transferring data from clients that are behind a firewall and are not able to accept
|
|
|
|
incoming connections (this is not possible with a normal DCC Send). In this case the client that receives
|
|
|
|
the file is passive and the client that sends it is active (as opposite to DCC Send).[br]
|
|
|
|
The "Send ahead" extension can be used also in this case and the "Turbo" extension is activated by prepending a 'T' to the
|
|
|
|
DCC message, "TRECV" instead of "RECV". The SSL extension is activated by prepending an 'S' to the
|
|
|
|
DCC message, "SRECV", "STRECV" or "TSRECV".[br]
|
|
|
|
This subprotocol has an implicit resume capability and thus has no need for RESUME and ACCEPT messages.[br]
|
|
|
|
DCC Recv requires the initiating (passive) client to know that the file to be transferred is avaiable on the B's side
|
|
|
|
and probably also know the file size. This subprotocol does not specify how this information is obtained, but it
|
|
|
|
will become clear soon that it can be obtained either manually (User B can simply tell the info to User A),
|
|
|
|
or automatically (as in the DCC Rsend subprotocol (keep reading)).[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC RSend[/big][br]
|
|
|
|
DCC RSend stands for Reverse Send. This is a KVIrc extension to the SEND protocol to allow firewalled clients
|
|
|
|
to send files.[br] In fact, this is a "half" subprotocol, since it defines only a part of the DCC negotiation;
|
|
|
|
the transfer is defined by another subprotocol (and specifically bu DCC Recv).[br]
|
|
|
|
The requesting client (the one that sends the file) is active and the receiving client is passive.[br]
|
|
|
|
Assume that Client A wants to send a file to Client B and that Client A cannot accept incoming connections.[br]
|
|
|
|
Client A sends a CTCP request to Client B in the following form:[br]
|
|
|
|
[b]DCC RSEND <filename> <filesize>[/b][br]
|
|
|
|
Client B receives the request, parses it, eventually asks the user for confirmation, sets up a listening socket, retrieves
|
|
|
|
its ip address and port and switches to the DCC Recv subprotocol by effectively sending the following CTCP message:[br]
|
|
|
|
[b]DCC RECV <filename> <ipaddress> <port> <resume position>[/b][br]
|
|
|
|
The rest of the transfer is defined by the DCC Recv subprotocol.[br]
|
|
|
|
The "Turbo" extension is again activated by prepending a 'T' to the RSEND string, so the initial CTCP will become:[br]
|
|
|
|
[b]DCC TRSEND <filename> <filesize>[/b][br]
|
|
|
|
The "SSL" extension is also activated by prepending an 'S' to the RSEND string. It can be again combined
|
|
|
|
with the "turbo" extension. The negotiation parameter becomes then "SRSEND","TSRSEND" or "STRSEND".[br]
|
|
|
|
Easy, no ? :)[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Get[/big][br]
|
|
|
|
This is again a "half" subprotocol in fact since it defines only a part of the negotiation for file transfers.[br]
|
|
|
|
It is also NON standard, since actually no client except KVIrc implements it (AFAIK).[br]
|
|
|
|
DCC Get is used to request a file from a remote client. Assume that Client A wants to request a file from Client B
|
|
|
|
(and assume that Client A knows that B has that file and wants to send it).[br]
|
|
|
|
Client A sends a CTCP message to Client B in the following form:[br]
|
|
|
|
[b]DCC GET <filename>[/b][br]
|
|
|
|
Where <filename> is a name of a file without path.[br]
|
|
|
|
Client B receives the message, parses it, looks for an association of the <filename> to a real filesystem file
|
|
|
|
and starts one of the two DCC File transfer subprotocols, DCC Send or DCC RSend.[br]
|
|
|
|
Client B should prefer the DCC Send method and choose DCC RSend only if it is not able to accept incoming connections.[br]
|
|
|
|
This subprotocol can be used by firewalled clients that can't accept connections but still want to request a file
|
|
|
|
from another client, this one can fail only if both clients are firewalled (in this case no DCC transfer is possible at all).[br]
|
|
|
|
This subprotocol also does not need to "magically" know the file size, the size definition
|
|
|
|
is found in the subprotocol that the remote client will choose.[br]
|
|
|
|
The association of <filename> with a real file on the B's machine is not explicitly defined by the subprotocol;
|
|
|
|
KVIrc uses an internal "file-offer" table with a list of files that are available for download.[br]
|
|
|
|
The "turbo" and "SSL" extensions are activated as usual, "TGET", "SGET", "TSGET" and "STGET" are supported.[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC File Transfer[/big][br]
|
|
|
|
DCC Send: Send a file, sender is passive, receiver is active (not good for firewalled senders)[br]
|
|
|
|
DCC Recv: Receive a file, sender is active, receiver is passive (not good for firewalled tqreceivers)[br]
|
|
|
|
DCC RSend: Send a file, sender is active, receiver is passive (not good for firewalled tqreceivers)[br]
|
|
|
|
DCC Get: Receive a file, sender is passive if not firewalled, receiver active if sender not firewalled (will fail only if both are firewalled)[br]
|
|
|
|
The "turbo" extension disables the stream of acknowledges and is activated by prepending the 'T' character to the DCC subprotocol name[br]
|
|
|
|
The "SSL" extension causes a Secure Socket Layer to be used and is activated by prepending the 'S' character to the DCC subprotocol name[br]
|
|
|
|
[br]
|
|
|
|
[big]DCC Voice[/big][br]
|
|
|
|
DCC Voice is a KVIrc extension (there is a Windows client called VIrc that implements such
|
|
|
|
a protocol, but it is incompatible with KVIrc).[br]
|
|
|
|
DCC Voice allows audio level communication between two clients, the audio stream is compressed
|
|
|
|
with a specified codec.[br]
|
|
|
|
KVIrc currently supports the ADPCM (core support) and the GSM codec (if the libgsm is available on the target system).[br]
|
|
|
|
[b]TODO: Finish the DCC Voice doc :)[/b]
|
|
|
|
[big]More tricks[/big][br]
|
|
|
|
KVIrc supports another "hack" to the DCC negotiation, it recognizes "XDCC" as
|
|
|
|
a DCC negotiation CTCP parameter.[br]
|
|
|
|
This can be used to circumvent limitations of some IRC clients (read mIRC) that will not allow
|
|
|
|
you to send a /DCC GET since it is an unrecognized DCC type.[br]
|
|
|
|
"XDCC" has exactly the same meaning as "DCC" (at least in KVIrc).[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static KviDccDescriptor * dcc_kvs_find_dcc_descriptor(const kvs_uint_t &uId,KviKvsModuleRunTimeCall * c,bool bWarn = true)
|
|
|
|
{
|
|
|
|
KviDccDescriptor * dcc = 0;
|
|
|
|
if(uId == 0)
|
|
|
|
{
|
|
|
|
if(c->window()->inherits("KviDccWindow"))
|
|
|
|
{
|
|
|
|
dcc = ((KviDccWindow *)(c->window()))->descriptor();
|
|
|
|
}
|
|
|
|
if((!dcc) && bWarn)
|
|
|
|
c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
|
|
|
|
return dcc;
|
|
|
|
}
|
|
|
|
dcc = KviDccDescriptor::find(uId);
|
|
|
|
if((!dcc) && bWarn)
|
|
|
|
c->warning(__tr2qs_ctx("The specified parameter is not a valid DCC identifier","dcc"));
|
|
|
|
return dcc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.abort
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.abort
|
|
|
|
@short:
|
|
|
|
Aborts a dcc session
|
|
|
|
@syntax:
|
|
|
|
dcc.abort [-q] [dcc_id:uint]
|
|
|
|
@description:
|
|
|
|
Terminates the Direct Client Connection specified by <dcc_id>.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function doesn't abort anything and prints a warning unless the -q switch is used.[br]
|
|
|
|
If <dcc_id> refers to a file transfer then it the transfer is simply
|
|
|
|
terminated. If <dcc_id> refers to a dcc chat then the result
|
|
|
|
is equivalent to closing the related window.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
@examples:
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_cmd_abort(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,!c->switches()->find('q',"quiet"));
|
|
|
|
|
|
|
|
if(dcc)
|
|
|
|
{
|
|
|
|
if(dcc->transfer())dcc->transfer()->abort();
|
|
|
|
else if(dcc->window())dcc->window()->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.setBandwidthLimit
|
|
|
|
@type:
|
|
|
|
command
|
|
|
|
@title:
|
|
|
|
dcc.setBandwidthLimit
|
|
|
|
@short:
|
|
|
|
Set the bandwidthlimit of a dcc.send session.
|
|
|
|
@syntax:
|
|
|
|
dcc.setBandwidthLimit [-q] [dcc_id:uint]
|
|
|
|
@description:
|
|
|
|
Terminates the Direct Client Connection specified by <dcc_id>.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning unless the -q switch is used.[br]
|
|
|
|
If <dcc_id> does not refers to a file transfer a warning will be printing unless the -q switch is used.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
@examples:
|
|
|
|
*/
|
|
|
|
static bool dcc_kvs_cmd_setBandwidthLimit(KviKvsModuleCommandCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId,uVal;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("limit_value",KVS_PT_UINT,0,uVal)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,!c->switches()->find('q',"quiet"));
|
|
|
|
if(dcc)
|
|
|
|
{
|
|
|
|
if (dcc->transfer())dcc->transfer()->setBandwidthLimit(uVal);
|
|
|
|
else if (!c->switches()->find('q',"quiet"))c->warning(__tr2qs_ctx("This DCC session is not a DCC transfer session","dcc"));
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.protocol
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.protocol
|
|
|
|
@short:
|
|
|
|
Returns the protocol of the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.protocol
|
|
|
|
<string> $dcc.protocol(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the string describing the protocol of the
|
|
|
|
Direct Client Connection specified by <dcc_id>.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_protocol(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->protocol());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.connectionType
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.connectionType
|
|
|
|
@short:
|
|
|
|
Returns the connection type of the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.connectionType
|
|
|
|
<string> $dcc.connectionType(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the connection type of the specified DCC.[br]
|
|
|
|
Returns the string "ACTIVE" for active DCC connections
|
|
|
|
and the string "PASSIVE" for passive DCC connections.
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_connectionType(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->isActive() ? "ACTIVE" : "PASSIVE");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.isFileTransfer
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.isFileTransfer
|
|
|
|
@short:
|
|
|
|
Checks if a DCC is a file transfer
|
|
|
|
@syntax:
|
|
|
|
<boolean> $dcc.isFileTransfer
|
|
|
|
<boolean> $dcc.isFileTransfer(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns 1 if the specified Direct Client Connection
|
|
|
|
is a file transfer and 0 otherwise.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this and returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_isFileTransfer(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c,false);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setBoolean(dcc->isFileTransfer());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.isFileUpload
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.isFileUpload
|
|
|
|
@short:
|
|
|
|
Checks if a DCC is an upload file transfer
|
|
|
|
@syntax:
|
|
|
|
<boolean> $dcc.isFileUpload
|
|
|
|
<boolean> $dcc.isFileUpload(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns 1 if the specified Direct Client Connection
|
|
|
|
is an upload file transfer and 0 otherwise.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_isFileUpload(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setBoolean(dcc->isFileUpload());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.isFileDownload
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.isFileDownload
|
|
|
|
@short:
|
|
|
|
Checks if a DCC is a download file transfer
|
|
|
|
@syntax:
|
|
|
|
<boolean> $dcc.isFileDownload
|
|
|
|
<boolean> $dcc.isFileDownload(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns 1 if the specified Direct Client Connection
|
|
|
|
is a download file transfer and 0 otherwise.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_isFileDownload(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setBoolean(dcc->isFileDownload());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localNick
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localNick
|
|
|
|
@short:
|
|
|
|
Returns the local nickname associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.localNick
|
|
|
|
<string> $dcc.localNick(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local nickname associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localNick(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localNick());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localUser
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localUser
|
|
|
|
@short:
|
|
|
|
Returns the local username associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.localUser
|
|
|
|
<string> $dcc.localUser(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local username associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localUser(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localUser());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localHost
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localHost
|
|
|
|
@short:
|
|
|
|
Returns the local hostname associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.localHost
|
|
|
|
<string> $dcc.localHost(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local hostname associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localHost(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localHost());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localIp
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localIp
|
|
|
|
@short:
|
|
|
|
Returns the local ip address associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.localIp
|
|
|
|
<string> $dcc.localIp(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local ip address associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localIp(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localIp());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localPort
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localPort
|
|
|
|
@short:
|
|
|
|
Returns the local port associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.localPort
|
|
|
|
<integer> $dcc.localPort(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local port associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localPort(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localPort());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localFileName
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localFileName
|
|
|
|
@short:
|
|
|
|
Returns the local file name associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.localFileName(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local file name associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> does not identify a file transfer DCC then this
|
|
|
|
function returns an empty string.
|
|
|
|
If <dcc_id> is not a valid Direct Client Connection identifier
|
|
|
|
then this function prints a warning and returns an empty string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localFileName(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localFileName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.localFileSize
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.localFileSize
|
|
|
|
@short:
|
|
|
|
Returns the local file size associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.localFileSize(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the local file size associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> does not identify a file transfer DCC then this
|
|
|
|
function returns '0'[br]
|
|
|
|
If <dcc_id> is not a valid Direct Client Connection identifier
|
|
|
|
then this function prints a warning and returns '0'[br]
|
|
|
|
In upload transfers the local file size rappresents the
|
|
|
|
total size of the file to be transferred. In download transfers
|
|
|
|
the local file size is non zero only if the transfer has to resume
|
|
|
|
a file already existing on the local disk and it rappresents the
|
|
|
|
size of that file (and thus the offset that the transfer started on).
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_localFileSize(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->localFileSize().isEmpty() ? TQString("0") : dcc->localFileSize());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteNick
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteNick
|
|
|
|
@short:
|
|
|
|
Returns the remote nickname associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.remoteNick
|
|
|
|
<string> $dcc.remoteNick(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote nickname associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteNick(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteNick());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteUser
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteUser
|
|
|
|
@short:
|
|
|
|
Returns the remote username associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.remoteUser
|
|
|
|
<string> $dcc.remoteUser(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote username associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteUser(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteUser());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteHost
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteHost
|
|
|
|
@short:
|
|
|
|
Returns the remote hostname associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.remoteHost
|
|
|
|
<string> $dcc.remoteHost(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote hostname associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteHost(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteHost());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteIp
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteIp
|
|
|
|
@short:
|
|
|
|
Returns the remote ip address associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.remoteIp
|
|
|
|
<string> $dcc.remoteIp(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote ip address associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteIp(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteIp());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remotePort
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remotePort
|
|
|
|
@short:
|
|
|
|
Returns the remote port associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.remotePort
|
|
|
|
<integer> $dcc.remotePort(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote port associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remotePort(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remotePort());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteFileName
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteFileName
|
|
|
|
@short:
|
|
|
|
Returns the remote file name associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.remoteFileName(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote file name associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> does not identify a file transfer DCC then this
|
|
|
|
function returns an empty string.
|
|
|
|
If <dcc_id> is not a valid Direct Client Connection identifier
|
|
|
|
then this function prints a warning and returns an empty string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteFileName(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteFileName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.remoteFileSize
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.remoteFileSize
|
|
|
|
@short:
|
|
|
|
Returns the remote file size associated to the specified DCC
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.remoteFileSize(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the remote file size associated to the specified DCC.[br]
|
|
|
|
If <dcc_id> does not identify a file transfer DCC then this
|
|
|
|
function returns '0'[br]
|
|
|
|
If <dcc_id> is not a valid Direct Client Connection identifier
|
|
|
|
then this function prints a warning and returns '0'[br]
|
|
|
|
In download transfers the remote file size rappresents the
|
|
|
|
total size of the file to be transferred (advertished by the remote end).[br]
|
|
|
|
In upload transfers the remote file size is non zero only if the
|
|
|
|
remote user has issued a resume request and is rappresents the requested offset
|
|
|
|
in bytes from which the transfer has started.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_remoteFileSize(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setString(dcc->remoteFileSize().isEmpty() ? TQString("0") : dcc->remoteFileSize());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.ircContext
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.ircContext
|
|
|
|
@short:
|
|
|
|
Returns the ircContext from which this DCC has originated
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.ircContext
|
|
|
|
<integer> $dcc.ircContext(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the identifier of the irc context from which
|
|
|
|
the specified DCC has been originated.[br]
|
|
|
|
When the DCC is not originated from an IRC context
|
|
|
|
then this function returns '0' : an invalid irc context id.
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_ircContext(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)c->returnValue()->setInteger(dcc->console()->context()->id());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.transferStatus
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.transferStatus
|
|
|
|
@short:
|
|
|
|
Returns the current status of a dcc file transfer
|
|
|
|
@syntax:
|
|
|
|
<string> $dcc.transferStatus
|
|
|
|
<string> $dcc.transferStatus(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the status in the specified DCC session.[br]
|
|
|
|
The status is one of the strings "connecting", "transferring", "success" and "failure".
|
|
|
|
"success" and "failure" are reported when the transfer is terminated.
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
If the DCC session does not refer to a file transfer then
|
|
|
|
this function returns "".[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_transferStatus(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)
|
|
|
|
{
|
|
|
|
if(dcc->transfer())
|
|
|
|
{
|
|
|
|
TQString tmp;
|
|
|
|
dcc->transfer()->fillStatusString(tmp);
|
|
|
|
c->returnValue()->setString(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.transferredBytes
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.transferredBytes
|
|
|
|
@short:
|
|
|
|
Returns the number of transferred bytes in a dcc file transfer
|
|
|
|
@syntax:
|
|
|
|
<integer> $dcc.transferredBytes
|
|
|
|
<integer> $dcc.transferredBytes(<dcc_id:uint>)
|
|
|
|
@description:
|
|
|
|
Returns the number of transferred bytes in the specified DCC session.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
If the DCC session does not refer to a file transfer then
|
|
|
|
this function returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_transferredBytes(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)
|
|
|
|
{
|
|
|
|
if(dcc->transfer())
|
|
|
|
{
|
|
|
|
c->returnValue()->setInteger(dcc->transfer()->transferredBytes());
|
|
|
|
} else {
|
|
|
|
c->returnValue()->setInteger(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.averageSpeed
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.averageSpeed
|
|
|
|
@short:
|
|
|
|
Returns the average speed of a dcc file transfer
|
|
|
|
@syntax:
|
|
|
|
$dcc.averageSpeed
|
|
|
|
$dcc.averageSpeed(<dcc_id>)
|
|
|
|
@description:
|
|
|
|
Returns the average speed (in bytes/sec) of the specified DCC session.[br]
|
|
|
|
If <dcc_id> is omitted then the DCC Session associated
|
|
|
|
to the current window is assumed.[br]
|
|
|
|
If <dcc_id> is not a valid DCC session identifier (or it is omitted
|
|
|
|
and the current window has no associated DCC session) then
|
|
|
|
this function prints a warning and returns an empty sting.[br]
|
|
|
|
If the DCC session does not refer to a file transfer then
|
|
|
|
this function returns 0.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_averageSpeed(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
kvs_uint_t uDccId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("dcc_id",KVS_PT_UINT,KVS_PF_OPTIONAL,uDccId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = dcc_kvs_find_dcc_descriptor(uDccId,c);
|
|
|
|
|
|
|
|
if(dcc)
|
|
|
|
{
|
|
|
|
if(dcc->transfer())
|
|
|
|
{
|
|
|
|
c->returnValue()->setInteger(dcc->transfer()->averageSpeed());
|
|
|
|
} else {
|
|
|
|
c->returnValue()->setInteger(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.session
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.session
|
|
|
|
@short:
|
|
|
|
Returns the DCC session identifier associated to a window
|
|
|
|
@syntax:
|
|
|
|
<uint> $dcc.session
|
|
|
|
<uint> $dcc.session(<window_id>)
|
|
|
|
@description:
|
|
|
|
Returns the DCC session identifier associated to the DCC window specified
|
|
|
|
by <window_id>. If <window_id> is omitted then the DCC session identifier
|
|
|
|
associated to the current window is returned. If the specified window
|
|
|
|
has no associated DCC session then a warning is printed and 0 is returned.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_session(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
TQString szWinId;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("window_id",KVS_PT_STRING,KVS_PF_OPTIONAL,szWinId)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviDccDescriptor * dcc = 0;
|
|
|
|
if(szWinId.isEmpty())
|
|
|
|
{
|
|
|
|
if(c->window()->inherits("KviDccWindow"))
|
|
|
|
dcc = ((KviDccWindow *)(c->window()))->descriptor();
|
|
|
|
if(!dcc)
|
|
|
|
{
|
|
|
|
c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
|
|
|
|
c->returnValue()->setInteger(0);
|
|
|
|
} else {
|
|
|
|
c->returnValue()->setInteger(dcc->id());
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
KviWindow * pWnd = g_pApp->findWindow(szWinId);
|
|
|
|
if(!pWnd)
|
|
|
|
{
|
|
|
|
c->warning(__tr2qs_ctx("The specified window identifier is not valid","dcc"));
|
|
|
|
c->returnValue()->setInteger(0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pWnd->inherits("KviDccWindow"))
|
|
|
|
dcc = ((KviDccWindow *)pWnd)->descriptor();
|
|
|
|
if(!dcc)
|
|
|
|
{
|
|
|
|
c->warning(__tr2qs_ctx("The current window has no associated DCC session","dcc"));
|
|
|
|
c->returnValue()->setInteger(0);
|
|
|
|
} else {
|
|
|
|
c->returnValue()->setInteger(dcc->id());
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc.sessionList
|
|
|
|
@type:
|
|
|
|
function
|
|
|
|
@title:
|
|
|
|
$dcc.sessionList
|
|
|
|
@short:
|
|
|
|
List the existing dcc session identifiers
|
|
|
|
@syntax:
|
|
|
|
<array> $dcc.sessionList
|
|
|
|
<array> $dcc.sessionList(<filter:string>)
|
|
|
|
@description:
|
|
|
|
The first form returns an array with all the currently existing dcc session
|
|
|
|
identifiers. The second form returns an array with the session types specified
|
|
|
|
in <filter> which may be a combination of the flags 'u' (for file upload),
|
|
|
|
'd' (for file download) and 'c' (for dcc chat). To select all the file transfers
|
|
|
|
please use the combination 'ud'.[br]
|
|
|
|
See the [module:dcc]dcc module[/module] documentation for more informations.[br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool dcc_kvs_fnc_sessionList(KviKvsModuleFunctionCall * c)
|
|
|
|
{
|
|
|
|
TQString szFlags;
|
|
|
|
KVSM_PARAMETERS_BEGIN(c)
|
|
|
|
KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFlags)
|
|
|
|
KVSM_PARAMETERS_END(c)
|
|
|
|
|
|
|
|
KviKvsArray * a = new KviKvsArray();
|
|
|
|
c->returnValue()->setArray(a);
|
|
|
|
|
|
|
|
KviPointerHashTable<int,KviDccDescriptor> * dict = KviDccDescriptor::descriptorDict();
|
|
|
|
if(!dict)return true;
|
|
|
|
|
|
|
|
KviPointerHashTableIterator<int,KviDccDescriptor> it(*dict);
|
|
|
|
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if(szFlags.isEmpty())
|
|
|
|
{
|
|
|
|
// all
|
|
|
|
while(KviDccDescriptor * dcc = it.current())
|
|
|
|
{
|
|
|
|
a->set(idx++,new KviKvsVariant((kvs_int_t)(dcc->id())));
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bool bWantFileUploads = szFlags.find('u',false) != -1;
|
|
|
|
bool bWantFileDownloads = szFlags.contains('d',false) != -1;
|
|
|
|
bool bWantChats = szFlags.contains('c',false) != -1;
|
|
|
|
|
|
|
|
while(KviDccDescriptor * dcc = it.current())
|
|
|
|
{
|
|
|
|
if((dcc->isFileUpload() && bWantFileUploads) ||
|
|
|
|
(dcc->isFileDownload() && bWantFileDownloads) ||
|
|
|
|
(dcc->isDccChat() && bWantChats))
|
|
|
|
{
|
|
|
|
a->set(idx++,new KviKvsVariant((kvs_int_t)(dcc->id())));
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@doc: dcc
|
|
|
|
@type:
|
|
|
|
module
|
|
|
|
@short:
|
|
|
|
Direct Client Connections
|
|
|
|
@title:
|
|
|
|
The DCC module
|
|
|
|
@body:
|
|
|
|
[big]Overview[/big][br]
|
|
|
|
The DCC module handles the Direct Client Connection
|
|
|
|
protocol layer and all it's sub-protocols.[br]
|
|
|
|
The sub-protocols include the standard CHAT
|
|
|
|
the standard SEND and its variants plus several
|
|
|
|
KVIrc extensions like RECV,RSEND,GET and VOICE.[br]
|
|
|
|
[br]
|
|
|
|
[big]Initiating a DCC negotiation[/big][br]
|
|
|
|
The following commands initiate a specific DCC session
|
|
|
|
with a remote client:[br]
|
|
|
|
[cmd]dcc.chat[/cmd][br]
|
|
|
|
[cmd]dcc.send[/cmd][br]
|
|
|
|
[cmd]dcc.rsend[/cmd][br]
|
|
|
|
[cmd]dcc.recv[/cmd][br]
|
|
|
|
[cmd]dcc.get[/cmd][br]
|
|
|
|
[cmd]dcc.voice[/cmd][br]
|
|
|
|
[br]
|
|
|
|
[big]Handling the DCC events[/big][br]
|
|
|
|
Each DCC session has an associated unique identifier (<dcc_id>).[br]
|
|
|
|
You can interact with the session by using several commands
|
|
|
|
and functions exported by this module and by passing the above session
|
|
|
|
id as parameter.[br]
|
|
|
|
The session related commands and functions are the following:[br]
|
|
|
|
[fnc]$dcc.sessionList[/fnc][br]
|
|
|
|
[fnc]$dcc.protocol[/fnc][br]
|
|
|
|
[fnc]$dcc.connectionType[/fnc][br]
|
|
|
|
[fnc]$dcc.transferStatus[/fnc][br]
|
|
|
|
[fnc]$dcc.isFileTransfer[/fnc][br]
|
|
|
|
[fnc]$dcc.isFileUpload[/fnc][br]
|
|
|
|
[fnc]$dcc.isFileDownload[/fnc][br]
|
|
|
|
[fnc]$dcc.localNick[/fnc][br]
|
|
|
|
[fnc]$dcc.localUser[/fnc][br]
|
|
|
|
[fnc]$dcc.localHost[/fnc][br]
|
|
|
|
[fnc]$dcc.localIp[/fnc][br]
|
|
|
|
[fnc]$dcc.localPort[/fnc][br]
|
|
|
|
[fnc]$dcc.localFileName[/fnc][br]
|
|
|
|
[fnc]$dcc.localFileSize[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteNick[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteUser[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteHost[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteIp[/fnc][br]
|
|
|
|
[fnc]$dcc.remotePort[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteFileName[/fnc][br]
|
|
|
|
[fnc]$dcc.remoteFileSize[/fnc][br]
|
|
|
|
[fnc]$dcc.ircContext[/fnc][br]
|
|
|
|
[fnc]$dcc.session[/fnc][br]
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static bool dcc_module_init(KviModule * m)
|
|
|
|
{
|
|
|
|
g_pDccBroker = new KviDccBroker();
|
|
|
|
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"send",dcc_kvs_cmd_send);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"chat",dcc_kvs_cmd_chat);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"voice",dcc_kvs_cmd_voice);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"recv",dcc_kvs_cmd_recv);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"rsend",dcc_kvs_cmd_rsend);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"get",dcc_kvs_cmd_get);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"abort",dcc_kvs_cmd_abort);
|
|
|
|
KVSM_REGISTER_SIMPLE_COMMAND(m,"setBandwidthLimit",dcc_kvs_cmd_setBandwidthLimit);
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME: file upload / download state ?
|
|
|
|
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"transferStatus",dcc_kvs_fnc_transferStatus);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"protocol",dcc_kvs_fnc_protocol);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"connectionType",dcc_kvs_fnc_connectionType);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"isFileTransfer",dcc_kvs_fnc_isFileTransfer);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"isFileUpload",dcc_kvs_fnc_isFileUpload);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"isFileDownload",dcc_kvs_fnc_isFileDownload);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localNick",dcc_kvs_fnc_localNick);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localUser",dcc_kvs_fnc_localUser);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localHost",dcc_kvs_fnc_localHost);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localIp",dcc_kvs_fnc_localIp);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localPort",dcc_kvs_fnc_localPort);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localFileName",dcc_kvs_fnc_localFileName);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"localFileSize",dcc_kvs_fnc_localFileSize);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteNick",dcc_kvs_fnc_remoteNick);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteUser",dcc_kvs_fnc_remoteUser);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteHost",dcc_kvs_fnc_remoteHost);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteIp",dcc_kvs_fnc_remoteIp);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remotePort",dcc_kvs_fnc_remotePort);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteFileName",dcc_kvs_fnc_remoteFileName);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"remoteFileSize",dcc_kvs_fnc_remoteFileSize);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"averageSpeed",dcc_kvs_fnc_averageSpeed);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"transferredBytes",dcc_kvs_fnc_transferredBytes);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"ircContext",dcc_kvs_fnc_ircContext);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"session",dcc_kvs_fnc_session);
|
|
|
|
KVSM_REGISTER_FUNCTION(m,"sessionList",dcc_kvs_fnc_sessionList);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool dcc_module_cleanup(KviModule *m)
|
|
|
|
{
|
|
|
|
delete g_pDccBroker;
|
|
|
|
g_pDccBroker = 0;
|
|
|
|
#ifdef COMPILE_USE_GSM
|
|
|
|
kvi_gsm_codec_done();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool dcc_module_can_unload(KviModule *m)
|
|
|
|
{
|
|
|
|
return g_pDccBroker ? g_pDccBroker->canUnload() : true;
|
|
|
|
}
|
|
|
|
|
|
|
|
KVIRC_MODULE(
|
|
|
|
"Dcc",
|
|
|
|
"1.0.0",
|
|
|
|
"Copyright (C) 2000-2004:\n" \
|
|
|
|
" Szymon Stefanek (pragma at kvirc dot net)\n",
|
|
|
|
"DCC extension for KVIrc\n",
|
|
|
|
dcc_module_init,
|
|
|
|
dcc_module_can_unload,
|
|
|
|
0,
|
|
|
|
dcc_module_cleanup
|
|
|
|
)
|