?? irc.cpp
字號(hào):
// ========================================================
// Internet Relay Chat Protocol Handler
//
// Based on RFC1459 (http://www.faqs.org/rfcs/rfc1459.html)
//
// Design and Implementation by Floris van den Berg
// ========================================================
#pragma warning (disable : 4275)
#pragma warning (disable : 4786)
#include <vector>
#include <string>
#include "..\OpenNet.h"
#include "..\OpenNetExtensions.h"
#include "Cabinet.h"
// --------------------------------------------------------
class CIRCProtocol : public IProtocol {
public :
CIRCProtocol();
virtual unsigned long DLL_CALLCONV AddRef();
virtual unsigned long DLL_CALLCONV Release();
virtual HRESULT DLL_CALLCONV QueryInterface(REFIID guid, void **iif);
virtual void DLL_CALLCONV Initialize(TRANSPORT_HANDLE m_transport);
virtual void DLL_CALLCONV Receive(unsigned char *data, int size);
virtual void DLL_CALLCONV Send(EpAction *action);
virtual void DLL_CALLCONV Reset();
virtual int DLL_CALLCONV GetName(char *name, int size);
virtual int DLL_CALLCONV GetMessageName(int msg, char *name, int size);
private :
void NoticeAuthDecode(_STL::string line);
void DecodeStatusMessage(_STL::string line, _STL::string server);
void DecodeCommand(_STL::string line, _STL::string server);
void Decode(_STL::string line);
void PingDecode(_STL::string line);
void IrcDecode(_STL::string line);
private :
int m_ref_count;
TRANSPORT_HANDLE m_transport;
char data[8192];
int data_size;
int data_pos;
};
// --------------------------------------------------------
CIRCProtocol::CIRCProtocol() :
m_ref_count(0),
m_transport(NULL),
data(),
data_size(0),
data_pos(0) {
memset(&data, 0, sizeof(data));
}
unsigned long DLL_CALLCONV
CIRCProtocol::AddRef() {
return ++m_ref_count;
}
unsigned long DLL_CALLCONV
CIRCProtocol::Release() {
int ref_count = --m_ref_count;
if (ref_count == 0)
delete this;
return ref_count;
}
HRESULT DLL_CALLCONV
CIRCProtocol::QueryInterface(REFIID guid, void **iif) {
if (IsEqualGUID(guid, CLSID_SYSTEM_PROTOCOL)) {
AddRef();
*iif = this;
return S_OK;
} else if (IsEqualGUID(guid, GUID_OBJECT)) {
AddRef();
*iif = this;
return S_OK;
}
return E_NOINTERFACE;
}
void DLL_CALLCONV
CIRCProtocol::Initialize(TRANSPORT_HANDLE transport) {
m_transport = transport;
}
void DLL_CALLCONV
CIRCProtocol::Receive(unsigned char *data, int size) {
// copy the data into the buffer
memcpy(data + data_size, data, size);
data_size += size;
// search for 0x0D's. if found we found a valid SMTP reply
int i = 0;
int pos = 0;
// strip any pending 0x0A and 0x0D chars
while (pos < data_size) {
if ((data[pos] != 0x0A) && (data[pos] != 0x0D))
break;
++pos;
}
// search for the next 0x0A or 0x0D
while (pos + i < data_size) {
if (data[pos + i] == 0x0D) {
// copy the found string into a temporary buffer for easier processing
char tmp_buffer[8192];
memcpy(tmp_buffer, data + pos, i - pos);
tmp_buffer[i - pos] = 0;
// decode the found line
if (strlen(tmp_buffer) > 0) {
// send the raw irc string to the user
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_IRC_PROTOCOL;
pm_event.msg = IRC_RAW;
pm_event.data = (unsigned char *)tmp_buffer;
pm_event.size = strlen(tmp_buffer) + 1;
EpDispatchEvent(m_transport, &pm_event);
// decode the string
IrcDecode(_STL::string(tmp_buffer));
}
// skip end of line characters
while ((pos + i < data_size) && ((data[pos + i] == 0x0D) || (data[pos + i] == 0x0A)))
++i;
memcpy(data, data + i, data_size - i);
data_size -= i;
i = 0;
} else {
++i;
}
}
}
void DLL_CALLCONV
CIRCProtocol::Send(EpAction *action) {
_STL::string complete;
switch(action->msg) {
case IRC_CMD_NICK :
{
complete = "NICK " + _STL::string((char *)action->data) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
case IRC_CMD_PASS :
{
complete = "PASS " + _STL::string((char *)action->data) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
case IRC_CMD_USER :
{
IRCUser *msg = (IRCUser *)action->data;
complete = "USER " + _STL::string(msg->username) + _STL::string(" ") +
_STL::string(msg->hostname) + _STL::string(" ") + _STL::string(msg->servername)
+ _STL::string(" : ") + _STL::string(msg->realname) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
case IRC_CMD_PONG :
{
complete = "PONG " + _STL::string((char *)action->data) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
case IRC_CMD_JOIN :
{
complete = "JOIN " + _STL::string((char *)action->data) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
case IRC_CMD_PRIVMSG :
{
IRCPrivateMsg *msg = (IRCPrivateMsg *)action->data;
complete = "PRIVMSG " + _STL::string((char *)msg->target) + _STL::string(" :") + _STL::string((char *)msg->message) + _STL::string("\r\n");
EpCompleteAction(m_transport, (unsigned char *)complete.c_str(), complete.length());
break;
}
};
}
void DLL_CALLCONV
CIRCProtocol::Reset() {
data_pos = 0;
data_size = 0;
memset(&data, 0, sizeof(data));
}
// --------------------------------------------------------
void
CIRCProtocol::NoticeAuthDecode(_STL::string line) {
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_IRC_PROTOCOL;
pm_event.msg = IRC_NOTICEAUTH;
pm_event.data = (unsigned char *)line.c_str();
pm_event.size = line.length() + 1;
EpDispatchEvent(m_transport, &pm_event);
}
void
CIRCProtocol::DecodeStatusMessage(_STL::string line, _STL::string server) {
_STL::string command;
_STL::vector<_STL::string> middle;
_STL::string params;
unsigned i = 0;
// retrieve all the command data stuff
while ((i < line.length()) && (isdigit(line[i])))
command += line[i++];
while ((i < line.length()) && (line[i] == ' '))
++i;
while ((i < line.length()) && (line[i] == '*'))
++i;
while ((i < line.length()) && (line[i] == ' '))
++i;
while ((i < line.length()) && (line[i] != ':')) {
_STL::string tmp;
while ((i < line.length()) && (line[i] != ' ') && (line[i] != ':'))
tmp += line[i++];
middle.push_back(tmp);
while ((i < line.length()) && (line[i] == ' '))
++i;
}
++i; // skip ':'
while ((i < line.length()) && (line[i] == ' '))
++i;
while (i < line.length())
params += line[i++];
// use the command string to create an event
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_IRC_PROTOCOL;
switch(atoi(command.c_str())) {
case 365 : // [RPL_ENDOFLINKS]
case 366 : // [RPL_ENDOFNAMES]
case 368 : // [RPL_ENDOFBANLIST]
break;
case 332 : // [RPL_TOPIC]
{
IRCChannelTopic msg;
strcpy(msg.server, server.c_str());
strcpy(msg.channel, middle[0].c_str());
strcpy(msg.topic, params.c_str());
pm_event.msg = IRC_CHANNEL_TOPIC;
pm_event.data = (unsigned char *)&msg;
pm_event.size = sizeof(IRCChannelTopic);
EpDispatchEvent(m_transport, &pm_event);
break;
}
case 353 : // [RPL_NAMREPLY]
{
IRCNick ircnick;
strcpy(ircnick.channel, middle[2].c_str());
pm_event.msg = IRC_NICK_ENTRY;
unsigned i = 0;
while (i < params.length()) {
_STL::string nick;
while ((i < params.length()) && (params[i] != ' '))
nick += params[i++];
while ((i < params.length()) && (params[i] == ' '))
++i;
strcpy(ircnick.nick, nick.c_str());
pm_event.data = (unsigned char *)&ircnick;
pm_event.size = sizeof(IRCNick);
EpDispatchEvent(m_transport, &pm_event);
}
break;
}
case 252 : // [RPL_LUSEROP]
case 253 : // [RPL_LUSERUNKNOWN]
case 254 : // [RPL_LUSERCHANNELS]
{
_STL::string tmp = middle[1] + _STL::string(" ") + params;
IRCStatusMessage msg;
strcpy(msg.message, tmp.c_str());
strcpy(msg.server, server.c_str());
pm_event.msg = IRC_STATUS_MESSAGE;
pm_event.data = (unsigned char *)&msg;
pm_event.size = sizeof(IRCStatusMessage);
EpDispatchEvent(m_transport, &pm_event);
break;
}
default :
{
IRCStatusMessage msg;
strcpy(msg.message, params.c_str());
strcpy(msg.server, server.c_str());
pm_event.msg = IRC_STATUS_MESSAGE;
pm_event.data = (unsigned char *)&msg;
pm_event.size = sizeof(IRCStatusMessage);
EpDispatchEvent(m_transport, &pm_event);
break;
}
}
}
void
CIRCProtocol::DecodeCommand(_STL::string line, _STL::string server) {
_STL::string command;
_STL::vector<_STL::string> middle;
_STL::string params;
unsigned i = 0;
// retrieve all the command data stuff
while ((i < line.length()) && (line[i] != ' '))
command += line[i++];
while ((i < line.length()) && (line[i] == ' '))
++i;
while ((i < line.length()) && (line[i] != ':')) {
_STL::string tmp;
while ((i < line.length()) && (line[i] != ' ') && (line[i] != ':'))
tmp += line[i++];
middle.push_back(tmp);
while ((i < line.length()) && (line[i] == ' '))
++i;
}
++i; // skip ':'
while ((i < line.length()) && (line[i] == ' '))
++i;
while (i < line.length())
params += line[i++];
// use the command string to create an event
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_IRC_PROTOCOL;
if (strncmp(command.c_str(), "PRIVMSG", 7) == 0) {
IRCReplyPrivateMsg msg;
int find = server.find("!");
strcpy(msg.nick, server.substr(0, find).c_str());
strcpy(msg.mask, server.substr(find + 1, server.length() - find - 1).c_str());
strcpy(msg.channel, middle[0].c_str());
strcpy(msg.message, params.c_str());
pm_event.msg = IRC_PRIVMSG;
pm_event.data = (unsigned char *)&msg;
pm_event.size = sizeof(IRCReplyPrivateMsg);
EpDispatchEvent(m_transport, &pm_event);
return;
}
if (strncmp(command.c_str(), "JOIN", 4) == 0) {
IRCNick nick;
int find = server.find("!");
strcpy(nick.nick, server.substr(0, find).c_str());
strcpy(nick.mask, server.substr(find + 1, server.length() - find - 1).c_str());
strcpy(nick.channel, params.c_str());
pm_event.msg = IRC_JOIN;
pm_event.data = (unsigned char *)&nick;
pm_event.size = sizeof(IRCNick);
EpDispatchEvent(m_transport, &pm_event);
return;
};
if (strncmp(command.c_str(), "PART", 4) == 0) {
IRCNick nick;
int find = server.find("!");
strcpy(nick.nick, server.substr(0, find).c_str());
strcpy(nick.mask, server.substr(find + 1, server.length() - find - 1).c_str());
strcpy(nick.channel, params.c_str());
pm_event.msg = IRC_PART;
pm_event.data = (unsigned char *)&nick;
pm_event.size = sizeof(IRCNick);
EpDispatchEvent(m_transport, &pm_event);
return;
};
if (strncmp(command.c_str(), "QUIT", 4) == 0) {
IRCNick nick;
int find = server.find("!");
strcpy(nick.nick, server.substr(0, find).c_str());
strcpy(nick.mask, server.substr(find + 1, server.length() - find - 1).c_str());
strcpy(nick.channel, params.c_str());
pm_event.msg = IRC_QUIT;
pm_event.data = (unsigned char *)&nick;
pm_event.size = sizeof(IRCNick);
EpDispatchEvent(m_transport, &pm_event);
return;
};
}
void
CIRCProtocol::Decode(_STL::string line) {
_STL::string nickserver;
// prefix part
unsigned i = 0;
if (line[i] == ':') {
++i;
while ((i < line.length()) && (line[i] != ' '))
nickserver += line[i++];
while ((i < line.length()) && (line[i] == ' '))
++i;
}
// command part (3 digits or a string)
if (isdigit(line[i]))
DecodeStatusMessage(line.substr(i, line.length() - i), nickserver);
else
DecodeCommand(line.substr(i, line.length() - i), nickserver);
}
void
CIRCProtocol::PingDecode(_STL::string line) {
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_IRC_PROTOCOL;
pm_event.msg = IRC_PING;
pm_event.data = (unsigned char *)line.c_str();
pm_event.size = line.length() + 1;
EpDispatchEvent(m_transport, &pm_event);
}
void
CIRCProtocol::IrcDecode(_STL::string line) {
if (strncmp(line.c_str(), "NOTICE AUTH", 11) == 0) {
unsigned i = 11;
while ((i < line.length()) && (line[i] != ':'))
++i;
while ((i < line.length()) && (line[i] == ':'))
++i;
NoticeAuthDecode(line.substr(i, line.length() - i));
} else if (strncmp(line.c_str(), "PING", 4) == 0) {
unsigned i = 4;
while ((i < line.length()) && (line[i] != ':'))
++i;
while ((i < line.length()) && (line[i] == ':'))
++i;
PingDecode(line.substr(i, line.length() - i));
} else {
Decode(line);
}
int i[] = { 0, 1, 2 };
}
int DLL_CALLCONV
CIRCProtocol::GetName(char *name, int size) {
if (size >= 4)
strcpy(name, "IRC");
return 4;
}
int DLL_CALLCONV
CIRCProtocol::GetMessageName(int msg, char *name, int size) {
return 0;
}
// --------------------------------------------------------
// Instantation function
// --------------------------------------------------------
static HRESULT DLL_CALLCONV
IRCProtocolCreate(void **iif) {
CIRCProtocol *object = new CIRCProtocol;
if (object) {
object->AddRef();
*iif = object;
return S_OK;
}
return E_FAIL;
}
// --------------------------------------------------------
// Discover function
// --------------------------------------------------------
void DLL_CALLCONV
IRCProtocolInitialize() {
EpRegisterProtocol(CLSID_IRC_PROTOCOL, IRCProtocolCreate);
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -