📄 client.cpp
字号:
/*
* Copyright (C) 2001-2003 Jacek Sieka, j_s@telia.com
*
* 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.
*/
#include "stdinc.h"
#include "DCPlusPlus.h"
#include "Socket.h"
#include "Client.h"
#include "ClientManager.h"
#include "SearchManager.h"
#include "ShareManager.h"
Client::Counts Client::counts;
Client::~Client() throw() {
TimerManager::getInstance()->removeListener(this);
socket->removeListener(this);
removeListeners();
clearUsers();
updateCounts(true);
BufferedSocket::putSocket(socket);
socket = NULL;
};
void Client::updateCounts(bool aRemove) {
// We always remove the count and then add the correct one if requested...
if(countType == COUNT_NORMAL) {
Thread::safeDec(&counts.normal);
} else if(countType == COUNT_REGISTERED) {
Thread::safeDec(&counts.registered);
} else if(countType == COUNT_OP) {
Thread::safeDec(&counts.op);
}
countType = COUNT_UNCOUNTED;
if(!aRemove) {
if(op) {
Thread::safeInc(&counts.op);
countType = COUNT_OP;
} else if(registered) {
Thread::safeInc(&counts.registered);
countType = COUNT_REGISTERED;
} else {
Thread::safeInc(&counts.normal);
countType = COUNT_NORMAL;
}
}
}
void Client::connect(const string& aServer) {
string tmp;
port = 411;
Util::decodeUrl(aServer, server, port, tmp);
connect();
}
void Client::connect() {
op = false;
registered = false;
reconnect = true;
if(socket->isConnected()) {
disconnect();
}
state = STATE_LOCK;
socket->connect(server, port);
}
void Client::refreshUserList(bool unknownOnly /* = false */) {
Lock l(cs);
if(unknownOnly) {
for(User::NickIter i = users.begin(); i != users.end(); ++i) {
if(i->second->getConnection().empty()) {
getInfo(i->second);
}
}
} else {
clearUsers();
getNickList();
}
}
void Client::clearUsers() {
for(User::NickIter i = users.begin(); i != users.end(); ++i) {
ClientManager::getInstance()->putUserOffline(i->second);
}
users.clear();
}
void Client::onLine(const string& aLine) throw() {
lastActivity = GET_TICK();
if(aLine.length() == 0)
return;
if(aLine[0] != '$') {
// Check if we're being banned...
if(state != STATE_CONNECTED) {
if(Util::findSubString(aLine, "banned") != string::npos) {
reconnect = false;
}
}
fire(ClientListener::MESSAGE, this, Util::validateMessage(aLine, true));
return;
}
string cmd;
string param;
string::size_type x;
if( (x = aLine.find(' ')) == string::npos) {
cmd = aLine;
} else {
cmd = aLine.substr(0, x);
param = aLine.substr(x+1);
}
if(cmd == "$Search") {
if(state != STATE_CONNECTED) {
return;
}
string::size_type i = 0;
string::size_type j = param.find(' ', i);
if(j == string::npos || i == j)
return;
string seeker = param.substr(i, j-i);
i = j + 1;
{
Lock l(cs);
u_int32_t tick = GET_TICK();
seekers.push_back(make_pair(seeker, tick));
// First, check if it's a flooder
FloodIter fi;
for(fi = flooders.begin(); fi != flooders.end(); ++fi) {
if(fi->first == seeker) {
return;
}
}
int count = 0;
for(fi = seekers.begin(); fi != seekers.end(); ++fi) {
if(fi->first == seeker)
count++;
if(count > 7) {
if(seeker.find("Hub:") != string::npos)
fire(ClientListener::SEARCH_FLOOD, this, seeker.substr(4));
else
fire(ClientListener::SEARCH_FLOOD, this, seeker + STRING(NICK_UNKNOWN));
flooders.push_back(make_pair(seeker, tick));
return;
}
}
}
int a;
if(param[i] == 'F') {
a = SearchManager::SIZE_DONTCARE;
} else if(param[i+2] == 'F') {
a = SearchManager::SIZE_ATLEAST;
} else {
a = SearchManager::SIZE_ATMOST;
}
i += 4;
j = param.find('?', i);
if(j == string::npos || i == j)
return;
string size = param.substr(i, j-i);
i = j + 1;
j = param.find('?', i);
if(j == string::npos || i == j)
return;
int type = Util::toInt(param.substr(i, j-i)) - 1;
i = j + 1;
param = param.substr(i);
if(param.size() > 0) {
fire(ClientListener::SEARCH, this, seeker, a, size, type, param);
if(seeker.find("Hub:") != string::npos) {
User::Ptr u;
{
Lock l(cs);
User::NickIter ni = users.find(seeker.substr(4));
if(ni != users.end() && !ni->second->isSet(User::PASSIVE)) {
u = ni->second;
u->setFlag(User::PASSIVE);
}
}
if(u) {
updated(u);
}
}
}
} else if(cmd == "$MyINFO") {
string::size_type i, j;
i = 5;
string nick;
j = param.find(' ', i);
if( (j == string::npos) || (j == i) )
return;
nick = param.substr(i, j-i);
i = j + 1;
User::Ptr u;
dcassert(nick.size() > 0);
{
Lock l(cs);
User::NickIter ni = users.find(nick);
if(ni == users.end()) {
u = ClientManager::getInstance()->getUser(nick, this);
users[nick] = u;
} else {
u = ni->second;
}
}
j = param.find('$', i);
if(j == string::npos)
return;
string tmpDesc = Util::validateMessage(param.substr(i, j-i), true);
// Look for a tag...
if(tmpDesc.size() > 0 && tmpDesc[tmpDesc.size()-1] == '>') {
string::size_type x = tmpDesc.rfind('<');
if(x != string::npos) {
// Hm, we have something...
u->setTag(tmpDesc.substr(x));
tmpDesc.erase(x);
}
}
u->setDescription(tmpDesc);
i = j + 3;
j = param.find('$', i);
if(j == string::npos)
return;
u->setConnection(param.substr(i, j-i-1));
i = j + 1;
j = param.find('$', i);
if(j == string::npos)
return;
u->setEmail(Util::validateMessage(param.substr(i, j-i), true));
i = j + 1;
j = param.find('$', i);
if(j == string::npos)
return;
u->setBytesShared(param.substr(i, j-i));
fire(ClientListener::MY_INFO, this, u);
} else if(cmd == "$Quit") {
if(!param.empty()) {
User::Ptr u;
{
Lock l(cs);
User::NickIter i = users.find(param);
if(i == users.end()) {
dcdebug("C::onLine Quitting user %s not found\n", param.c_str());
return;
}
u = i->second;
users.erase(i);
}
fire(ClientListener::QUIT, this, u);
ClientManager::getInstance()->putUserOffline(u, true);
}
} else if(cmd == "$ConnectToMe") {
if(state != STATE_CONNECTED) {
return;
}
string::size_type i = param.find(' ');
string::size_type j;
if( (i == string::npos) || ((i + 1) >= param.size()) ) {
return;
}
i++;
j = param.find(':', i);
if(j == string::npos) {
return;
}
string server = param.substr(i, j-i);
if(j+1 >= param.size()) {
return;
}
fire(ClientListener::CONNECT_TO_ME, this, server, param.substr(j+1));
} else if(cmd == "$RevConnectToMe") {
if(state != STATE_CONNECTED) {
return;
}
User::Ptr u;
bool up = false;
{
Lock l(cs);
string::size_type j = param.find(' ');
if(j == string::npos) {
return;
}
User::NickIter i = users.find(param.substr(0, j));
if(i == users.end()) {
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -