📄 ircmain.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//A lot of documentation for the IRC protocol within this code came
//directly from http://www.irchelp.org/irchelp/rfc/rfc2812.txt
//Much of it may never be used, but it's here just in case..
#include "stdafx.h"
#include <Mmsystem.h>
#include "emule.h"
#include "IRCMain.h"
#include "OtherFunctions.h"
#include "ED2KLink.h"
#include "DownloadQueue.h"
#include "Server.h"
#include "IRCSocket.h"
#include "MenuCmds.h"
#include "Sockets.h"
#include "FriendList.h"
#include "emuledlg.h"
#include "ServerWnd.h"
#include "IRCWnd.h"
#include "StringConversion.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CIrcMain::CIrcMain(void)
{
ircsocket = NULL;
m_pwndIRC = 0; // i_a
preParseBuffer = "";
srand( (unsigned)time( NULL ) );
SetVerify();
}
CIrcMain::~CIrcMain(void)
{
}
void CIrcMain::PreParseMessage( CStringA buffer )
{
try
{
CStringA rawMessage;
preParseBuffer += buffer;
int index = preParseBuffer.Find('\n');
try
{
while( index != -1 )
{
rawMessage = preParseBuffer.Left(index);
rawMessage.Remove('\n');
rawMessage.Remove('\r');
ParseMessage( rawMessage );
if( preParseBuffer != _T("") )
preParseBuffer = preParseBuffer.Mid(index+1);
index = preParseBuffer.Find('\n');
}
}
catch(...)
{
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Exception in CIrcMain::PreParseMessage(1)"));
}
}
catch(...)
{
if (thePrefs.GetVerbose())
AddDebugLogLine(false, _T("Exception in CIrcMain::PreParseMessage(2)"));
}
}
void CIrcMain::ProcessLink( CString ed2kLink )
{
try
{
CString link;
link = OptUtf8ToStr(URLDecode(ed2kLink));
CED2KLink* pLink = CED2KLink::CreateLinkFromUrl(link);
_ASSERT( pLink !=0 );
switch (pLink->GetKind())
{
case CED2KLink::kFile:
{
CED2KFileLink* pFileLink = pLink->GetFileLink();
_ASSERT(pFileLink !=0);
theApp.downloadqueue->AddFileLinkToDownload(pFileLink);
break;
}
case CED2KLink::kServerList:
{
CED2KServerListLink* pListLink = pLink->GetServerListLink();
_ASSERT( pListLink !=0 );
CString strAddress = pListLink->GetAddress();
if(strAddress.GetLength() != 0)
theApp.emuledlg->serverwnd->UpdateServerMetFromURL(strAddress);
break;
}
case CED2KLink::kServer:
{
CString defName;
CED2KServerLink* pSrvLink = pLink->GetServerLink();
_ASSERT( pSrvLink !=0 );
CServer* pSrv = new CServer(pSrvLink->GetPort(),ipstr(pSrvLink->GetIP()));
_ASSERT( pSrv !=0 );
pSrvLink->GetDefaultName(defName);
pSrv->SetListName(defName.GetBuffer());
// Barry - Default all new irc servers to high priority
if( thePrefs.GetManualHighPrio() )
pSrv->SetPreference(SRV_PR_HIGH);
if (!theApp.emuledlg->serverwnd->serverlistctrl.AddServer(pSrv,true))
delete pSrv;
else
AddLogLine(true,GetResString(IDS_SERVERADDED), pSrv->GetListName());
break;
}
default:
break;
}
delete pLink;
}
catch(...)
{
AddLogLine(true, GetResString(IDS_LINKNOTADDED));
ASSERT(0);
}
}
void CIrcMain::ParseMessage( CStringA rawMessage )
{
try
{
if( rawMessage.GetLength() < 6 )
{
//TODO : We probably should disconnect here as I don't know of anything that should
//come from the server this small..
return;
}
if( rawMessage.Left(6) == "PING :" )
{
//If the server pinged us, we must pong back or get disconnected..
//Anything after the ":" must be sent back or it will fail..
ircsocket->SendString( CString("PONG " + rawMessage.Right(rawMessage.GetLength()-6)) );
m_pwndIRC->AddStatus( _T("PING?/PONG") );
return;
}
//I temp replace % with \004 as it will mess up sending this string with parameters later.
rawMessage.Replace( "%", "\004" );
//Source of the message
CString source;
int sourceIndex = -1;
//IP address of the source of the message
CString sourceIp;
//Command that the message is sending
CString command;
int commandIndex = -1;
//Target of the message
CString target;
int targetIndex = -1;
CString target2;
int target2Index = -1;
//The actual message
CString message;
int messageIndex = -1;
//Check if there is a source which always ends with a !
//Messages without a source is usually a server message.
sourceIndex = rawMessage.Find( '!' );
if( rawMessage.Left(1) == ":" )
{
//If the message starts with a ":", the first space must be the beginning of the command
//Although, it seems some servers are miscofigured..
commandIndex = rawMessage.Find( ' ' );
}
else
{
//If the message doesn't start with a ":", the first word is the command.
commandIndex = 0;
}
if( commandIndex == -1 )
throw CString(_T("SMIRC Error: Received a message had no command."));
//The second space is the beginning of the target or message
targetIndex = rawMessage.Find( ' ', commandIndex + 1);
if( targetIndex == -1 )
throw CString(_T("SMIRC Errow: Received a message with no target or message."));
//This will pull out the command
if( commandIndex == 0 )
{
//Command is the first word.. Strange as I don't see this in any standard..
command = rawMessage.Mid( commandIndex, targetIndex - commandIndex);
}
else
{
//Command is where it should be.
command = rawMessage.Mid( commandIndex + 1, targetIndex - commandIndex - 1);
}
if( sourceIndex < commandIndex && sourceIndex > 0)
{
//Raw message had a source.
//Get source and IP of source
source = rawMessage.Mid( 1, sourceIndex - 1);
sourceIp = rawMessage.Mid( sourceIndex + 1, commandIndex - sourceIndex - 1);
messageIndex = rawMessage.Find( ' ', targetIndex + 1);
if( messageIndex > sourceIndex )
{
//Raw message had a message
//Get target and message
target = rawMessage.Mid( targetIndex + 1, messageIndex - targetIndex - 1);
message = rawMessage.Mid( messageIndex );
//I'm not sure why some messages have different formats, but this cleans them up.
if( target.Left(1) == _T(":") )
target = target.Mid(1);
if( message.Left(1) == _T(":") )
message = message.Mid(1);
if( target.Left(2) == _T(" :") )
target = target.Mid(2);
if( message.Left(2) == _T(" :") )
message = message.Mid(2);
}
else
{
//Raw message had no message
//Get target
target = rawMessage.Mid( targetIndex + 1, rawMessage.GetLength() - targetIndex - 1);
//I'm not sure why some messages have different formats, but this cleans them up.
if( target.Left(1) == _T(":") )
target = target.Mid(1);
if( target.Left(2) == _T(" :") )
target = target.Mid(2);
}
}
else
{
if( commandIndex == 0 )
{
//Raw message had no source, must be from the server
source = _T("");
}
else
{
//Get source
source = rawMessage.Mid( 1, commandIndex - 1);
}
message = rawMessage.Mid( targetIndex + 1);
}
if( command == _T("PRIVMSG") )
{
// Messages
if ( target.Left(1) == _T("#") )
{
//Belongs to a channel..
if( message.Left(1) == _T("\001") )
{
//This is a specal message.. Find out what kind..
if( message.GetLength() < 4 )
throw CString( _T("SMIRC Error: Received Invalid special channel message") );
message = message.Mid( 1, message.GetLength() - 2);
if( message.Left(6) == _T("ACTION") )
{
//Channel Action..
if( message.GetLength() < 8 )
throw CString( _T("SMIRC Error: Received Invalid channel action") );
m_pwndIRC->AddInfoMessage( target, _T("* %s %s"), source, message.Mid(7) );
return;
}
if( message.Left(5) == _T("SOUND"))
{
//Sound
if( message.GetLength() < 7 )
throw CString( _T("SMIRC Error: Received Invalid channel sound") );
message = message.Mid(6);
int soundlen = message.Find( _T(" ") );
CString sound;
CString strFileName;
if( soundlen != -1 )
{
//Sound event also had a message
strFileName = message.Left(soundlen);
message = message.Mid(soundlen);
}
else
{
//Sound event didn't have a message
strFileName = message;
message = _T(" [SOUND]");
}
//Check for proper form.
strFileName.Remove(_T('\\'));
strFileName.Remove(_T('/'));
if( (strFileName.Right(4) != _T(".wav")) && (strFileName.Right(4) != _T(".mp3")) && (strFileName.Right(4) != _T(".WAV")) && (strFileName.Right(4) != _T(".MP3")) )
throw CString( _T("SMIRC Error: Received invalid sound event.") );
sound.Format(_T("%sSounds\\IRC\\%s"), thePrefs.GetAppDir(), strFileName);
if(thePrefs.GetIrcSoundEvents())
{
PlaySound(sound, NULL, SND_FILENAME | SND_NOSTOP | SND_NOWAIT | SND_ASYNC);
}
m_pwndIRC->AddInfoMessage( target, _T("* %s%s"), source, message );
return;
}
if( message.Left(7) == _T("VERSION"))
{
//Get client version.
version = _T("eMule") + theApp.m_strCurVersionLong + _T(Irc_Version);
CString build;
build.Format( _T("NOTICE %s :\001VERSION %s\001"), source, version );
ircsocket->SendString( build );
return;
}
if( message.Left(4) == _T("PING"))
{
//TODO - Respond to a user ping.
return;
}
}
else
{
//This is a normal channel message..
m_pwndIRC->AddMessage( target, source, message);
return;
}
}
else
{
//Private Message
if( message.Left(1) == _T("\001") ){
//Special message
if( message.GetLength() < 4 )
throw CString( _T("SMIRC Error: Received Invalid special private message") );
message = message.Mid(1, message.GetLength() -2);
if( message.Left(6) == _T("ACTION"))
{
//Action
if( message.GetLength() < 8 )
throw CString( _T("SMIRC Error: Received Invalid private action") );
m_pwndIRC->AddInfoMessage( source, _T("* %s %s"), source, message.Mid(7) );
return;
}
if( message.Left(5) == _T("SOUND"))
{
//sound event
if( message.GetLength() < 7 )
throw CString( _T("SMIRC Error: Received Invalid private sound") );
message = message.Mid(6);
int soundlen = message.Find( _T(" ") );
CString sound;
CString strFileName;
if( soundlen != -1 )
{
//Sound event also had a message
strFileName = message.Left(soundlen);
message = message.Mid(soundlen);
}
else
{
//Sound event didn't have a message
strFileName = message;
message = _T(" [sound]");
}
//Check for proper form.
strFileName.Remove(_T('\\'));
strFileName.Remove(_T('/'));
if( (strFileName.Right(4) != _T(".wav")) && (strFileName.Right(4) != _T(".mp3")) && (strFileName.Right(4) != _T(".WAV")) && (strFileName.Right(4) != _T(".MP3")) )
throw CString( _T("SMIRC Error: Received invalid sound event") );
sound.Format(_T("%sSounds\\IRC\\%s"), thePrefs.GetAppDir(), strFileName);
if(thePrefs.GetIrcSoundEvents())
{
PlaySound(sound, NULL, SND_FILENAME | SND_NOSTOP | SND_NOWAIT | SND_ASYNC);
}
m_pwndIRC->AddInfoMessage( source, _T("* %s%s"), source, message );
return;
}
if( message.Left(7) == _T("VERSION"))
{
//Get client version.
version = _T("eMule") + theApp.m_strCurVersionLong + _T(Irc_Version);
CString build;
build.Format( _T("NOTICE %s :\001VERSION %s\001"), source, version );
ircsocket->SendString( build );
return;
}
if( message.Left(4) == _T("PING"))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -