580 lines
13 KiB
PHP
580 lines
13 KiB
PHP
|
<?php
|
||
|
/*
|
||
|
+---------------------------------------------------------------------------
|
||
|
| PHP-IRC v2.2.1 Service Release
|
||
|
| ========================================================
|
||
|
| by Manick
|
||
|
| (c) 2001-2005 by http://www.phpbots.org/
|
||
|
| Contact: manick@manekian.com
|
||
|
| irc: #manekian@irc.rizon.net
|
||
|
| ========================================
|
||
|
+---------------------------------------------------------------------------
|
||
|
| > dcc module
|
||
|
| > Module written by Manick
|
||
|
| > Module Version Number: 2.2.0
|
||
|
+---------------------------------------------------------------------------
|
||
|
| > 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 option) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
+---------------------------------------------------------------------------
|
||
|
| Changes
|
||
|
| =======-------
|
||
|
| > If you wish to suggest or submit an update/change to the source
|
||
|
| > code, email me at manick@manekian.com with the change, and I
|
||
|
| > will look to adding it in as soon as I can.
|
||
|
+---------------------------------------------------------------------------
|
||
|
*/
|
||
|
|
||
|
class dcc {
|
||
|
|
||
|
private $dccList = array(); //holds all connected sockets
|
||
|
private $dccChangedList = array();
|
||
|
private $dccChangedCount = 0;
|
||
|
|
||
|
private $fileDlCount = 0;
|
||
|
private $fileUlCount = 0;
|
||
|
private $chatCount = 0;
|
||
|
|
||
|
//Classes
|
||
|
private $timerClass;
|
||
|
private $socketClass;
|
||
|
private $ircClass;
|
||
|
private $parserClass;
|
||
|
|
||
|
//Bytes Transferred
|
||
|
private $bytesUp = 0;
|
||
|
private $bytesDown = 0;
|
||
|
|
||
|
//Process Queue
|
||
|
private $procQueue;
|
||
|
|
||
|
public function __construct()
|
||
|
{
|
||
|
// do nothing...
|
||
|
}
|
||
|
|
||
|
public function setProcQueue($class)
|
||
|
{
|
||
|
$this->procQueue = $class;
|
||
|
}
|
||
|
|
||
|
public function setIrcClass($class)
|
||
|
{
|
||
|
$this->ircClass = $class;
|
||
|
}
|
||
|
|
||
|
public function setParserClass($class)
|
||
|
{
|
||
|
$this->parserClass = $class;
|
||
|
$this->parserClass->setDccClass($this);
|
||
|
}
|
||
|
|
||
|
public function setSocketClass($class)
|
||
|
{
|
||
|
$this->socketClass = $class;
|
||
|
}
|
||
|
|
||
|
public function setTimerClass($class)
|
||
|
{
|
||
|
$this->timerClass = $class;
|
||
|
}
|
||
|
|
||
|
public function getDownloadCount()
|
||
|
{
|
||
|
return $this->fileDlCount;
|
||
|
}
|
||
|
|
||
|
public function getUploadCount()
|
||
|
{
|
||
|
return $this->fileUlCount;
|
||
|
}
|
||
|
|
||
|
public function getChatCount()
|
||
|
{
|
||
|
return $this->chatCount;
|
||
|
}
|
||
|
|
||
|
public function closeAll()
|
||
|
{
|
||
|
foreach ($this->dccList AS $dcc)
|
||
|
{
|
||
|
$dcc->disconnect("Owner Requsted Close");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function addBytesUp($num)
|
||
|
{
|
||
|
$this->bytesUp += $num;
|
||
|
}
|
||
|
|
||
|
public function addBytesDown($num)
|
||
|
{
|
||
|
$this->bytesDown += $num;
|
||
|
}
|
||
|
|
||
|
public function getBytesDown()
|
||
|
{
|
||
|
return $this->bytesDown;
|
||
|
}
|
||
|
|
||
|
public function getBytesUp()
|
||
|
{
|
||
|
return $this->bytesUp;
|
||
|
}
|
||
|
|
||
|
|
||
|
public function getDcc($someDcc)
|
||
|
{
|
||
|
if (isset($this->dccList[$someDcc]))
|
||
|
{
|
||
|
return $this->dccList[$someDcc];
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
public function dccInform($data, $from = null)
|
||
|
{
|
||
|
foreach ($this->dccList AS $dcc)
|
||
|
{
|
||
|
if ($dcc->type == CHAT && $dcc->verified == true && $dcc->isAdmin == true)
|
||
|
{
|
||
|
if ($from != null)
|
||
|
{
|
||
|
if ($dcc->sockInt != $from->sockInt)
|
||
|
{
|
||
|
$dcc->dccSend($data);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$dcc->dccSend($data);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Works in conjunction with $oldConn->connected
|
||
|
public function accepted($oldConn, $newConn)
|
||
|
{
|
||
|
$sockInt = $oldConn->getSockInt();
|
||
|
$hasAccepted = $newConn->getSockInt();
|
||
|
|
||
|
$dcc = $this->dccList[$sockInt];
|
||
|
$this->dccList[$hasAccepted] = $dcc;
|
||
|
$dcc->status = DCC_CONNECTED;
|
||
|
$dcc->sockInt = $hasAccepted;
|
||
|
unset($this->dccList[$sockInt]);
|
||
|
}
|
||
|
|
||
|
//CheckDccTimeout function
|
||
|
public function checkDccTimeout($dcc)
|
||
|
{
|
||
|
if (!is_object($dcc) || $dcc->removed == true)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ($dcc->status != DCC_LISTENING)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
switch ($dcc->timeOutLevel)
|
||
|
{
|
||
|
case 0:
|
||
|
$dcc->timeOutLevel++;
|
||
|
break;
|
||
|
case 1:
|
||
|
$dcc->timeOutLevel++;
|
||
|
$this->ircClass->notice($dcc->nick, "You have a DCC session pending. Set your client to connect. 60 seconds before timeout.", 1);
|
||
|
break;
|
||
|
case 2:
|
||
|
$dcc->timeOutLevel++;
|
||
|
$this->ircClass->notice($dcc->nick, "You have a DCC session pending. Set your client to connect. 30 seconds before timeout.", 1);
|
||
|
break;
|
||
|
case 3:
|
||
|
$dcc->timeOutLevel = 0;
|
||
|
$dcc->disconnect("DCC Session timed out (90 Seconds)");
|
||
|
return false;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
public function getDccList()
|
||
|
{
|
||
|
return $this->dccList;
|
||
|
}
|
||
|
|
||
|
private function removeDcc($dcc)
|
||
|
{
|
||
|
$sockInt = $dcc->sockInt;
|
||
|
unset($this->dccList[$sockInt]);
|
||
|
}
|
||
|
|
||
|
public function dccSend($to, $data)
|
||
|
{
|
||
|
if (($len = $this->socketClass->sendSocket($to->sockInt, $data)) === false)
|
||
|
{
|
||
|
$to->disconnect();
|
||
|
}
|
||
|
return $len;
|
||
|
}
|
||
|
|
||
|
|
||
|
private function highestId()
|
||
|
{
|
||
|
$highest = 0;
|
||
|
|
||
|
foreach ($this->dccList AS $index => $dcc)
|
||
|
{
|
||
|
$highest = ($dcc->id > $highest ? $dcc->id : $highest);
|
||
|
}
|
||
|
|
||
|
return $highest + 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
public function addChat($nick, $host, $port, $admin, $handler, $fromTimer = false)
|
||
|
{
|
||
|
$lnick = irc::myStrToLower($nick);
|
||
|
|
||
|
foreach ($this->dccList AS $index => $dcc)
|
||
|
{
|
||
|
if ($dcc->type == CHAT)
|
||
|
{
|
||
|
if (irc::myStrToLower($dcc->nick) == $lnick)
|
||
|
{
|
||
|
$dcc->disconnect();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$reverse = false;
|
||
|
|
||
|
if ($this->ircClass->getClientConf("mircdccreverse") != "" && $fromTimer == false)
|
||
|
{
|
||
|
$port = intval($this->ircClass->getClientConf("mircdccreverse"));
|
||
|
if ($port == 0)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
$args = new argClass;
|
||
|
|
||
|
$args->arg1 = $nick;
|
||
|
$args->arg2 = $host;
|
||
|
$args->arg3 = $port;
|
||
|
$args->arg4 = $admin;
|
||
|
$args->arg5 = $handler;
|
||
|
$args->arg7 = time();
|
||
|
$args->arg8 = CHAT;
|
||
|
|
||
|
$this->ircClass->notice($nick, "DCC: NOTICE: This server is using the mIRC Chat Server Protocol. Please use ' /dccserver +c on " . $this->ircClass->getClientConf("mircdccreverse") . " ' to chat with me! Starting 6 second delay...", 0);
|
||
|
|
||
|
$this->ircClass->sendRaw("WHOIS " . $nick);
|
||
|
$this->timerClass->addTimer(irc::randomHash(), $this, "reverseTimer", $args, 6, false);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ($fromTimer == true)
|
||
|
{
|
||
|
$reverse = DCC_REVERSE; // using mIRC dcc reverse protocol
|
||
|
}
|
||
|
|
||
|
if ($host == NULL || $port == NULL)
|
||
|
{
|
||
|
$conn = new connection(null, null, 0);
|
||
|
$listening = true;
|
||
|
$status = DCC_LISTENING;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$conn = new connection($host, $port, CONNECT_TIMEOUT);
|
||
|
$listening = false;
|
||
|
$status = DCC_CONNECTING;
|
||
|
}
|
||
|
|
||
|
$conn->setSocketClass($this->socketClass);
|
||
|
$conn->setIrcClass($this->ircClass);
|
||
|
$conn->setCallbackClass($this);
|
||
|
$conn->setTimerClass($this->timerClass);
|
||
|
$port = $conn->init();
|
||
|
|
||
|
if ($conn->getError())
|
||
|
{
|
||
|
$this->ircClass->log("Start Chat Error: " . $conn->getErrorMsg());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$sockInt = $conn->getSockInt();
|
||
|
|
||
|
$this->chatCount++;
|
||
|
|
||
|
$id = $this->highestId();
|
||
|
|
||
|
$chat = new chat($id, $nick, $admin, $sockInt, $host, $port, $handler, $reverse);
|
||
|
$chat->setIrcClass($this->ircClass);
|
||
|
$chat->setDccClass($this);
|
||
|
$chat->setParserClass($this->parserClass);
|
||
|
$chat->setSocketClass($this->socketClass);
|
||
|
$chat->setTimerClass($this->timerClass);
|
||
|
$chat->connection = $conn;
|
||
|
$chat->status = $status;
|
||
|
$chat->removed = false;
|
||
|
|
||
|
$this->dccList[$sockInt] = $chat;
|
||
|
|
||
|
$chat->initialize();
|
||
|
|
||
|
$conn->setCallbackClass($chat);
|
||
|
|
||
|
if ($listening == true)
|
||
|
{
|
||
|
$this->timerClass->addTimer(irc::randomHash(), $this, "checkDccTimeout", $chat, 30, true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$conn->connect();
|
||
|
}
|
||
|
|
||
|
return $port;
|
||
|
}
|
||
|
|
||
|
public function addFile($nick, $host, $port, $type, $filename, $size, $fromTimer = false) // <-- ignore fromTimer, it is sent by reverseTimer() above
|
||
|
{
|
||
|
$reverse = false;
|
||
|
|
||
|
if ($this->ircClass->getClientConf("mircdccreverse") != "" && $fromTimer == false && $type != DOWNLOAD)
|
||
|
{
|
||
|
$port = intval($this->ircClass->getClientConf("mircdccreverse"));
|
||
|
if ($port == 0)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
$args = new argClass;
|
||
|
|
||
|
$args->arg1 = $nick;
|
||
|
$args->arg2 = $host;
|
||
|
$args->arg3 = $port;
|
||
|
$args->arg4 = $type;
|
||
|
$args->arg5 = $filename;
|
||
|
$args->arg6 = $size;
|
||
|
$args->arg7 = time();
|
||
|
$args->arg8 = FILE;
|
||
|
|
||
|
$this->ircClass->notice($nick, "DCC: NOTICE: This server is using the mIRC File Server Protocol. Please use ' /dccserver +s on " . $this->ircClass->getClientConf("mircdccreverse") . " ' to recieve files from me! Starting 6 second delay...", 0);
|
||
|
|
||
|
$this->ircClass->sendRaw("WHOIS " . $nick);
|
||
|
$this->timerClass->addTimer(irc::randomHash(), $this, "reverseTimer", $args, 6);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ($fromTimer == true)
|
||
|
{
|
||
|
$reverse = DCC_REVERSE; // using mIRC dcc reverse protocol
|
||
|
}
|
||
|
|
||
|
if ($host == NULL || $port == NULL)
|
||
|
{
|
||
|
$conn = new connection(null, null, 0);
|
||
|
$listening = true;
|
||
|
$status = DCC_LISTENING;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$conn = new connection($host, $port, CONNECT_TIMEOUT);
|
||
|
$listening = false;
|
||
|
$status = DCC_CONNECTING;
|
||
|
}
|
||
|
|
||
|
$conn->setSocketClass($this->socketClass);
|
||
|
$conn->setIrcClass($this->ircClass);
|
||
|
$conn->setCallbackClass($this);
|
||
|
$conn->setTransTimeout(30);
|
||
|
$conn->setTimerClass($this->timerClass);
|
||
|
$port = $conn->init();
|
||
|
|
||
|
if ($conn->getError())
|
||
|
{
|
||
|
$this->ircClass->log("File transfer start error: " . $conn->getErrorMsg());
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$sockInt = $conn->getSockInt();
|
||
|
|
||
|
$id = $this->highestId();
|
||
|
|
||
|
$file = new file($id, $nick, $sockInt, $host, $port, $type, $reverse);
|
||
|
|
||
|
if ($file->transferType == UPLOAD)
|
||
|
{
|
||
|
$this->fileUlCount++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$this->fileDlCount++;
|
||
|
}
|
||
|
|
||
|
$file->setIrcClass($this->ircClass);
|
||
|
$file->setDccClass($this);
|
||
|
$file->setSocketClass($this->socketClass);
|
||
|
$file->setProcQueue($this->procQueue);
|
||
|
$file->setTimerClass($this->timerClass);
|
||
|
$file->connection = $conn;
|
||
|
$file->status = $status;
|
||
|
$file->removed = false;
|
||
|
|
||
|
$this->dccList[$sockInt] = $file;
|
||
|
|
||
|
$file->initialize($filename, $size);
|
||
|
|
||
|
$conn->setCallbackClass($file);
|
||
|
|
||
|
if ($listening == true)
|
||
|
{
|
||
|
$this->timerClass->addTimer(irc::randomHash(), $this, "checkDccTimeout", $file, 30, true);
|
||
|
}
|
||
|
|
||
|
if ($reverse == true)
|
||
|
{
|
||
|
$conn->connect();
|
||
|
}
|
||
|
|
||
|
return $port;
|
||
|
}
|
||
|
|
||
|
|
||
|
public function alterSocket($sockInt, $level, $opt, $val)
|
||
|
{
|
||
|
return $this->socketClass->alterSocket($sockInt, $level, $opt, $val);
|
||
|
}
|
||
|
|
||
|
|
||
|
public function reverseTimer($args)
|
||
|
{
|
||
|
$memData = $this->ircClass->getUserData($args->arg1);
|
||
|
|
||
|
if ($memData == NULL || ($memData->host == "" || $memData->host == NULL))
|
||
|
{
|
||
|
$this->ircClass->notice($args->arg1, "DCC: ERROR: Couldn't resolve your hostname. Try again?");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
if ($args->arg8 == FILE)
|
||
|
{
|
||
|
$this->addFile( $args->arg1,
|
||
|
$memData->host,
|
||
|
$this->ircClass->getClientConf("mircdccreverse"),
|
||
|
$args->arg4,
|
||
|
$args->arg5,
|
||
|
$args->arg6,
|
||
|
true);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$this->addChat( $args->arg1,
|
||
|
$memData->host,
|
||
|
$this->ircClass->getClientConf("mircdccreverse"),
|
||
|
$args->arg4,
|
||
|
$args->arg5,
|
||
|
true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
public function sendFile($nick, $file)
|
||
|
{
|
||
|
return $this->addFile($nick, null, null, UPLOAD, $file, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
public function dccResume($port, $size)
|
||
|
{
|
||
|
foreach ($this->dccList AS $dcc)
|
||
|
{
|
||
|
if ($dcc->type == FILE)
|
||
|
{
|
||
|
if ($dcc->port == $port)
|
||
|
{
|
||
|
$dcc->resume($size);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function dccAccept($port)
|
||
|
{
|
||
|
foreach ($this->dccList AS $dcc)
|
||
|
{
|
||
|
if ($dcc->type == FILE)
|
||
|
{
|
||
|
if ($dcc->port == $port)
|
||
|
{
|
||
|
$dcc->accepted();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function disconnect($dcc)
|
||
|
{
|
||
|
|
||
|
switch ($dcc->type)
|
||
|
{
|
||
|
case CHAT:
|
||
|
$this->chatCount--;
|
||
|
break;
|
||
|
case FILE:
|
||
|
switch($dcc->transferType)
|
||
|
{
|
||
|
case UPLOAD:
|
||
|
$this->fileUlCount--;
|
||
|
break;
|
||
|
case DOWNLOAD:
|
||
|
$this->fileDlCount--;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$dcc->removed = true;
|
||
|
|
||
|
$dcc->connection->disconnect();
|
||
|
$this->removeDcc($dcc);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
?>
|