/***************************************************************************
 *   Copyright (C) 2008 by SK Communications.                              *
 *   http://kldp.net/projects/nateon/                                      *
 *                                                                         *
 *   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 3 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 <stdlib.h>
#include "knateoncommon.h"
#include "nateondpconnection.h"
#include "util/common.h"

extern nmconfig stConfig;

NateonDPConnection::NateonDPConnection(QObject *parent, const char *name)
: NateonConnection("nateondpconnection"),
m_pBuddyList(0),
m_pGroupList(0),
m_pAccount(0),
m_SSConnection(0),
m_pCommon(0)
{
	Q_UNUSED( parent );
	Q_UNUSED( name );
	
    m_pBuddyList = new BuddyList();
#if 0
    if ( 0 != m_pBuddyList )
    {
        //m_pBuddyList->addGroup( SpecialGroups::ETC, UTF8("etc") );
        //m_pBuddyList->addGroup( SpecialGroups::ETC, UTF8("etc") );	// just test
    }
#endif
    m_pGroupList = new GroupList();
#if 0
    if ( 0 != m_pGroupList )
    {
        //m_pBuddyList->addGroup( SpecialGroups::ETC, UTF8("etc") );
        //m_pBuddyList->addGroup( SpecialGroups::ETC, UTF8("etc") ); // just test
    }
#endif
}


NateonDPConnection::~NateonDPConnection()
{
	if (0 != m_pBuddyList) delete m_pBuddyList;
	if (0 != m_pGroupList) delete m_pGroupList;
	if (0 != m_pCommon) delete m_pCommon;
}


/*!
  \fn NateonDPConnection::openConnection()
*/
bool NateonDPConnection::openConnection()
{
	/*!
	 * connect to dp server
	 * TEST Server
	 * connectToServer( "192.168.196.40", 5022);
	 */
#ifdef NETDEBUG
	kdDebug() << "stConfig.dplconnectionfail : " << stConfig.dplconnectionfail << ", DPIP : " << m_pCurrentAccount->getDPip() << ", DPPort : " << m_pCurrentAccount->getDPport() << endl;
#endif
	if ( stConfig.dplconnectionfail == TRUE )
		return connectToServer( stConfig.prsserver, stConfig.prsport ); /*! PRS서버 경유 DP서버 접속 */ 
	else
		return connectToServer( m_pCurrentAccount->getDPip(), m_pCurrentAccount->getDPport());
}


/*!
  \fn NateonDPConnection::initialize()
*/
void NateonDPConnection::initialize()
{
    NateonConnection::initialize();

    // Pass the current contactlist reference to the currentaccount
    // so other classes can access contacts from a central point.
    m_pCurrentAccount->setBuddyList( m_pBuddyList );
    m_pCurrentAccount->setGroupList( m_pGroupList );

}


bool NateonDPConnection::parseCommand(const QStringList& slCommand)
{
	// parse every command :)

	if (  slCommand[0] == "RCON" ) {
		putLSIN();
	}
	else if ( slCommand[0] == "LSIN" ){
		gotLSIN( slCommand );
	}
	else if ( slCommand[0] == "GLST") {
		gotGLST( slCommand );
	}
	else if ( slCommand[0] == "LIST") {
		gotLIST( slCommand );
	}
	else if ( slCommand[0] == "PING" ) {
		gotPING( slCommand );
	}
	else if ( slCommand[0] == "PACK" ) {
		gotPACK( slCommand, slCommand[1]);
	}
	else if ( slCommand[0] == "RESS" ) {
		gotRESS( slCommand );
	}
	else if ( (slCommand[0] == "INFY") || (slCommand[0] == "NTFY") ) {
		gotINFY( slCommand );
	}
	else if ( slCommand[0] == "ADDG" ) {
		gotADDG( slCommand );
	}
	else if ( slCommand[0] == "RMVG" ) {
		gotRMVG( slCommand );
	}
	else if ( slCommand[0] == "RENG" ) {
		gotRENG( slCommand );
	}
	else if ( slCommand[0] == "ADSB" ) {
		gotADSB( slCommand );
	}
	else if ( slCommand[0] == "ADDB" ) {
		gotADDB( slCommand );
	}
	else if ( slCommand[0] == "200" ) {
		emit err200();
	}
	else if ( slCommand[0] == "201" ) {
		emit err201();
	}
	else if ( slCommand[0] == "202" ) {
		emit err202();
	}
	else if ( slCommand[0] == "300" ) {
		/*!
		 * _T("존재하지 않는 아이디입니다. 확인후 다시 시도해 주십시오.\r\n\r\n추가 정보가 필요하시면 \"자세히\" 버튼을 눌러 주세요.")
		 */
		emit err300();
	}
	else if ( slCommand[0] == "301" ) {
		/*!
		 * _T("비밀번호가 틀렸습니다. 확인후 다시 시도해 주십시오.\r\n\r\n추가 정보가 필요하시면 \"자세히\" 버튼을 눌러 주세요.")
		 */
		emit err301( slCommand );
	}
	else if ( slCommand[0] == "302" ) {
		emit err302();
	}
	else if ( slCommand[0] == "304" ) {
		/*!
		 * 아이디를 찾을 수 없습니다.
		 */
		Buddy* pBuddy = m_pBuddyList->getBuddyByHandle( slCommand[1] );
		if (pBuddy) {
			pBuddy->setUID("XXX");
		}
		emit err304();
	}
	else if ( slCommand[0] == "306" ) {
		/*!
		 * invalid sesssion 세션이 잘못되어있음.
		 */
		emit err306();
	}
	else if ( slCommand[0] == "309" ) {
		/*!
		 * #define NATE_CODE_COMM_STOP           "309"   // Communication Stop 
		 */
		emit err309();
	}
	else if ( slCommand[0] == "418" ) {
		/*!
		 * _T("현재 지원되지 않는 버전으로 로그인 시도를\n하였습니다.\n로그인을 하기 위해서는 업그레이드를 해야합니다.\n네이트온을 재실행하면 자동으로\n업그레이드가 됩니다.\n")
		 */
	}
	else if ( slCommand[0] == "420" ) {
		/*!
		 * _T("현재 지원되지 않는 버전으로 로그인 시도를\n하였습니다.\n로그인을 하기 위해서는 업그레이드를 해야합니다.\n")
		 */
	}
	else if ( slCommand[0] == "421" ) {
		/*!
		 * cannot connect back-end server error mr, css, cfr, ipml등에 연결할 수 없을 때.
		 */
		emit err421();
	}
	else if ( slCommand[0] == "500" ) {
		/*!
		 * #define NATE_CODE_DB_ERROR "500" // general db error
		 */
		emit err500( slCommand );
	}
	else if ( slCommand[0] == "977" ) {
		/*!
		 * 997 TRID ErrCode ErrorMsg
		 * 윈도우즈 네이트온에서는 로그인 실패창이 뜨고 자세히를 누르면 ErrorMsg가 노출
		 * 로그인 실패창의 내용은 ErrCode에 따라 뿌려줌.( ex. 300/301/418/309)
		 */
	}
	else if ( slCommand[0] == "998" ) {
		/*!
		 * 998 : 브라우져를 띄워줌
		 * 998 [TRID] [BrCode] [BrParam] [TOOLBAR_YN] [Width] [Height]
		 * Brcode에 해당하는 페이지로 BrParam을 파라미터로 브라우져를 실행
		 * TOOLBAR_YN : Y(전체창) N(팝업)
		 * Width, Height : 팝업일 경우 팝업 사이즈 
		 */
		emit err998( slCommand );
	}
	else if ( slCommand[0] == "REFR" ) {
		emit receivedREFR( slCommand );
	}
	else if ( slCommand[0] == "CPRF" ) {
		/*!
		 * 싸이연동 변경 결과 
		 */
		emit receivedCPRF( slCommand );
	} else if ( slCommand[0] == "NNIK" ) {
		/*!
		 * 버디 닉 변경 
		 */
		emit receivedNNIK( slCommand );
	} else if ( slCommand[0] == "NPRF" ) {
		/*!
		 * 싸이연동 버디의 변경 내용
		 */
		emit receivedNPRF( slCommand );
	} else if ( slCommand[0] == "TICK" ) {
		/*!
		 * 싸이연동 티켓값 받기
		 */
		m_pCurrentAccount->setMyTicket( slCommand[2] );
	} else if ( slCommand[0] == "KILL" ) {
		/*!
		 * 다른사용자 로그인 해서 끊김.
		 */
		emit kill();
	} else if ( slCommand[0] == "ALRM" ) {
		/*!
		 * 알람패킷을 받았을때
		 */
		emit receivedALRM( slCommand );
	} else if ( slCommand[0] == "CALM" ) {
		/*!
		 * 버디에 알람패킷을 받았을때
		 */
		emit receivedCALM( slCommand );
	} else if ( slCommand[0] == "RMVB" ) {
		/*!
		 * 서버에서 보내는 것은 TID가 0으로 넘어옴.
		 * 본인이 코멘드를 날리고 리턴으로 받는 메시지는 TID가 0이 아님.
		 */
		if ( slCommand[1] == "0" ) {
			Buddy *pBuddy = m_pBuddyList->getBuddyByID( slCommand[4] );
			if ( pBuddy ) {
				if ( slCommand[2] == "RL" )
					pBuddy->setRL( FALSE );
				else if ( slCommand[2] == "BL" )
					pBuddy->setBL( FALSE );
				else if ( slCommand[2] == "AL" )
					pBuddy->setAL( FALSE );
				else if ( slCommand[2] == "FL" )
					pBuddy->setFL( FALSE );
			}
		}
	}
	return true;
}


bool NateonDPConnection::parseMessage(const QString &sCommand, const QStringList& slCommand, const MimeMessage& message)
{
	if ( slCommand[0] == "CONF" )
	{
		gotCONF( slCommand );
	}
	else if ( slCommand[0] == "CTOC" || slCommand[0] == "CMSG" )
	{
		if ( sCommand == "IMSG" ) {
			// gotMemoCTOC( message );
			emit receivedMemoCTOC( message );
		}
		else if ( sCommand == "AMSG" ) {
			emit receivedCTOCAMSG( message );
		}

		message.print();
#ifdef NETDEBUG
		kdDebug() << "MESSAGE : [" << sCommand << "]" << endl;
#endif
	}

	return true;
}


/*!
  \fn NateonDPConnection::closeConnection()
*/
void NateonDPConnection::closeConnection()
{
	pBList.clear();
	slFixHandle.clear();
  pGroupList.clear();
  pBuddyList.clear();

	setSendPings( FALSE );
	// m_pingTimer.stop();
	// Disconnect from the server
	disconnectFromServer();

	emit disconnected();
}


void NateonDPConnection::connectionSuccess()
{
	connectionTimer_.stop();
	if ( stConfig.dplconnectionfail == TRUE )
		putRCON();
	else
		putLSIN();
}


/*!
  \fn NateonDPConnection::putLSIN()
*/
#include <errno.h>
#include <qfile.h>

#define MAXLINE 256

void NateonDPConnection::putLSIN()
{
	QString sID = m_pCurrentAccount->getID();
	QString sOrgPasswd = m_pCurrentAccount->getPassword();
	QString sCommand;
	QString filename;
	if ( !QFile::exists( "/bin/nateongen" ) && !QFile::exists( "/usr/bin/nateongen" ) && !QFile::exists( "/usr/local/bin/nateongen" ) && !QFile::exists( "/opt/kde/bin/nateongen" ))
	{
		KMessageBox::error( 0, "Not Found 'nateongen', check file : /bin/nateongen or /usr/bin/nateongen or /usr/local/bin/nateongen or /opt/kde/bin/nateongen" );
		exit(0);
	}
	
	sCommand = "nateongen";
	sCommand += " ";
	sCommand += sID;
	sCommand += " ";
	sCommand += sOrgPasswd;

	FILE *fp;
	
	char buff[MAXLINE];
	fp = popen( sCommand.ascii() , "r");
	if (fp == NULL)
	{
		KMessageBox::error( 0, strerror( errno) );
		exit(0);
	}
	fgets(buff, MAXLINE, fp);
	
	int i, num = 0;
	char a[2];
	char out[33];
	memset( out, 0x00, 33 );
	for ( i = 0; i < 32; i++ )
	{
		memset( a, 0x00, 2 );
		snprintf( a, 2,"%c", ( buff[(i*2)] ) );
		num = atoi( a ) * 16;
		memset( a, 0x00, 2 );
		snprintf( a, 2,"%c", ( buff[(i*2) + 1] ) );
		num += atoi( a );
		
		sprintf( out + i, "%c", num );
	}
	
	sendCommand( "LSIN", m_pCurrentAccount->getID() + " " + out + " " + "MD5 3.871 UTF8 ko.linux\r\n" );
}


/*!
  \fn NateonDPConnection::gotLSIN()
*/
void NateonDPConnection::gotLSIN(const QStringList& slCommand)
{
	// LSIN 0 902126197 장두현 ring0320@nate.com%20으로%20이전했어요~ 0168524207 %00 9774A1E4C0E826950E2927AF06FEC99A030796FB88A6A9858A8E52D66D5EEF939C6F0A2C5B7B51C834C76467BE80C99E1904DFCC66F6395F2A559F8C1000F70DA195D40902E6F9F3C42BAF66895C02DD98B3D900166F7E567940611BDAFA496CCC84F5C234D8AFD8A21839DF01C6E0C785D960AFA00FC59E055EA7C31E5A79F0B9CCA920C3AC8C6E92F7DF3DCC60E3D557EF652134A02A59 %00 1 %00 %00 N 902126197 ring0320@lycos.co.kr %00 Y N KR %00 %00

	m_pCurrentAccount->setMyCMN( slCommand[2] );
	m_pCurrentAccount->setMyName( slCommand[3] );
	/*! 닉이 없으면 이름으로 대체 */
	if ( slCommand[4] != "%00")
	{
		QString mTemp(slCommand[4]);
		/*! %20 과 같은것을 공백(" ")으로 변환 */
		removePercents(mTemp);
		m_pCurrentAccount->setMyNickName( mTemp );
	}
	else
	{
		m_pCurrentAccount->setMyNickName( slCommand[3] );
	}
	m_pCurrentAccount->setMyPhone( slCommand[5] );
	m_pCurrentAccount->setMyEmail( slCommand[6] );
	m_pCurrentAccount->setMyTicket( slCommand[7] );
	m_pCurrentAccount->setMyCyworldCMN( slCommand[8] );
	m_pCurrentAccount->setMyAuthYN( atoi(slCommand[9]) );
	m_pCurrentAccount->setMyMIMID( slCommand[10] );
	m_pCurrentAccount->setMyMusicDate( slCommand[11] );
	m_pCurrentAccount->setMyLoginType( slCommand[12][0] ); /*! 네이트닷컴아이디 : 'N', 싸이월드아이디 : 'C' */
	m_pCurrentAccount->setMyNateCMN( slCommand[13] );
	m_pCurrentAccount->setMyNateID( slCommand[14] );
	m_pCurrentAccount->setMyCyworldID( slCommand[15] );
	m_pCurrentAccount->setMyTongYN( (slCommand[16] == "Y") );
	m_pCurrentAccount->setMyTownYN( (slCommand[17] == "Y") );

	// kdDebug() << "LSIN size : " << slCommand.size() << endl;

	if ( slCommand.size() > 18 ) {
		m_pCurrentAccount->setMyArea( slCommand[18] );
		if ( slCommand.size() > 19 )
		{
			m_pCurrentAccount->setMyEmpasCMN( slCommand[19] );
			m_pCurrentAccount->setMyEmpasID( slCommand[20] );
		}
	}	// slCommand[18] , O_AREA
	// slCommand[19] , EMPAS-CMN
	// slCommand[20] , EMPAS-ID


	m_pCurrentAccount->setMyHompyNew( FALSE );

	sendCommand( "CONF", "0 0\r\n" );

	emit receivedLSIN();
	emit updateStatusText( UTF8("인증 성공") );
}


/*!
  \fn NateonDPConnection::gotCONF()
*/
void NateonDPConnection::gotCONF(const QStringList& slCommand)
{
	sendCommand( "GLST", "0\r\n" );
	
	Q_UNUSED( slCommand );
}


/*!
  \fn NateonDPConnection::gotGLST()
*/
void NateonDPConnection::gotGLST(const QStringList& slCommand)
{
	emit updateStatusText( UTF8("그룹 목록 받음") );
	
	if (0 == m_pGroupList)
	{
		return;
	}

	// if command is incoming GLST cache #
	if (3 == slCommand.size())
	{
		m_nGLSTCacheNum = slCommand[2].toInt() ;
	}
	// if command is GLST group list
	else if (8 == slCommand.size())
	{
		QString sGroupName( slCommand[6] );
		sGroupName.replace("%20", " ");
		pGroupList.insert( slCommand[5], new QStringList(sGroupName) );
	}
	// Edit by Doo-Hyun Jang
	// if command is GLST belong list
	else if (7 == slCommand.size())
	{
		QStringList* tempStringList = pGroupList.find( slCommand[6] );
		tempStringList->append( slCommand[5] );
		pGroupList.replace( slCommand[6], tempStringList );
	}
	// if last group list item received
	if  (slCommand.count() > 3 && (atoi(slCommand[2]) + 1 == atoi(slCommand[3])))
	{
		sendCommand( "LIST", "\r\n" );
	}
}


/*!if (0 != m_pLoginView)
  \fn NateonDPConnection::gotLIST()
*/
void NateonDPConnection::gotLIST(const QStringList& slCommand)
{
	emit updateStatusText( UTF8("버디 목록 받음") );
	
	pBuddyList.insert( slCommand[6], new QStringList(slCommand) );

#ifdef NETDEBUG
	kdDebug() << "SLCOMMAND : " << slCommand << endl;
#endif
    
    bool isAll = FALSE;
    
    if ( slCommand.count() > 2 ) {
        int nCnt = atoi(slCommand[2]);
        int nTot = atoi(slCommand[3]);
        
        if ( nTot == 0 ) { /*! 버디가 하나도 없을때 */
            isAll = TRUE;
        } else if ( ( nCnt + 1 ) == nTot ) {
            isAll = TRUE;
        }
    }
    
	/*! 버디리스트를 모두 받았나? */ 
	if  ( isAll )
	{
		Group* pGroup = NULL;
		Buddy* pBuddy = NULL;

		//  그룹 리스트 생성
		QDictIterator<QStringList> iterGList(pGroupList);
		for(; iterGList.current(); ++iterGList)
		{
			QStringList slValue( *iterGList.current() );
#ifdef NETDEBUG
			kdDebug() << "SLVALUE : " << slValue << endl;
#endif
			pGroup = new Group( iterGList.currentKey(), slValue.first() );

#ifdef NETDEBUG
			//kdDebug() << "그룹 " << pGroup->getGName() << "의 key : " << pGroup->getGID() << endl;
#endif

			//  생성된 그룹(pGroup)에 속한 친구 리스트 생성
			for(QStringList::Iterator iterBList=slValue.begin(); iterBList != slValue.end(); ++iterBList)
			{
				if( *iterBList == slValue.first() )
					continue;
				else if( pBuddyList.find(*iterBList) )
				{
					QStringList slBuddyData( *pBuddyList.find(*iterBList) );

#ifdef NETDEBUG
					kdDebug() << "SLBUDDYDATA : " << slBuddyData << endl;
#endif
				
					pBuddy = new Buddy();
					pBuddy->setStatus("F");
					pBuddy->setBuddyData( slBuddyData );
					/*!
					Buddy는 여러개의 GID를 가질 수 있다.
					*/
					if( slBuddyData[4] == "0001" )
					{
						pBuddy->setGID("0");
						emit addCommandQueue( slBuddyData );
					}
			
					if( pBList.find( slBuddyData[6].data() ) == 0 )
					{
						slFixHandle.append( slBuddyData[6] );
#ifdef NETDEBUG
						kdDebug() << "Error No Group : " << slCommand[6] << endl;
#endif
					}
					// 전체 친구 리스트에 친구 추가
					m_pBuddyList->addBuddy( pBuddy );
#ifdef NETDEBUG
					kdDebug() << "그룹 " << pGroup->getGName() << "에 버디 " << pBuddy->getUID() << "를 추가함" << endl;
#endif
				
					// 소속된 그룹에 친구 추가 
					pGroup->addBuddy( pBuddy );
				}
			}
#ifdef NETDEBUG
			kdDebug() << "그룹 " << pGroup->getGName() << " 의 멤버 수 [" << QString::number(pGroup->getBuddyList().count()) << "]" << endl;
#endif
			m_pGroupList->addGroup( pGroup );
		}

		emit connected();
		setSendPings( true );
	}

#ifdef NETDEBUG
	kdDebug() << "gotLIST에서 총 버디 수 : [" << QString::number(m_pBuddyList->count()) << "]" << endl;
#endif
}


/*!
  \fn NateonDPConnection::gotPING()
*/
void NateonDPConnection::gotPING(const QStringList& slCommand)
{
	sendCommand( "PING", "\r\n" );
	
	Q_UNUSED( slCommand );
}


#include "nateondpconnection.moc"

/*!
  \fn NateonDPConnection::messageSent(const QString &)
*/
void NateonDPConnection::messageSent(const QString &m_cMessageQS)
{
	// sendCommand("CTOC", m_cMessageQS + "\r\n");
	sendCommand( "CTOC", m_cMessageQS );
}


/*!
  \fn NateonDPConnection::messageReceived(const QString &)
*/
void NateonDPConnection::messageReceived(const QString &m_cMessageQS)
{
    sendCommand("CTOC", m_cMessageQS + "\r\n");
}


/*!
  \fn NateonDPConnection::gotPACK(const QStringList& slCommand)
*/
void NateonDPConnection::gotPACK(const QStringList& slCommand, const QString& sTid)
{
	sendCommand_noTid("PNAK ", sTid + "\r\n");
	
	Q_UNUSED( slCommand );
}


/*!
  \fn NateonDPConnection::getRESS( QStringList& slCommand )
  대화를 하기 위해 SS서버 IP와 Port 값을 받습니다.
*/
void NateonDPConnection::gotRESS(const QStringList& slCommand )
{
    m_SSConnection = new SSConnection();

    m_SSConnection->setTID( atoi(slCommand[1]) );
    m_SSConnection->setServer( slCommand[2] );
    m_SSConnection->setPort( atoi(slCommand[3]) );
    m_SSConnection->setAuthKey( slCommand[4] );

    emit ReceiveRESS(m_SSConnection);
}


/*!
  \fn NateonDPConnection::putRESS()
*/
int NateonDPConnection::putRESS()
{
    int m_nTID;
    m_nTID = sendCommand("RESS", "\r\n");

    return m_nTID;
}

void NateonDPConnection::gotINFY(const QStringList & slCommand)
{
	emit receivedINFY(slCommand);
}

void NateonDPConnection::gotMemoCTOC(const MimeMessage& sMemo)
{
	emit receivedMemoCTOC(sMemo);
}

void NateonDPConnection::gotADDG(const QStringList & slCommand)
{
	m_nGLSTCacheNum = slCommand[2].toInt();

	emit receivedADDG( slCommand );
}

void NateonDPConnection::gotRMVG(const QStringList & slCommand)
{
	m_nGLSTCacheNum = slCommand[2].toInt();

	emit receivedRMVG( slCommand );
}

void NateonDPConnection::gotRENG(const QStringList & slCommand)
{
	m_nGLSTCacheNum = slCommand[2].toInt();

	emit receivedRENG( slCommand );
}

int NateonDPConnection::putADDG(QString sCommand)
{
	return sendCommand("ADDG", sCommand);
}

int NateonDPConnection::putRENG(QString sCommand)
{
	return sendCommand("RENG", sCommand);
}

int NateonDPConnection::putRMVG(QString sCommand)
{
	return sendCommand("RMVG", sCommand);
}

int NateonDPConnection::putADSB(QString sCommand)
{
	return sendCommand("ADSB", sCommand);
}


int NateonDPConnection::putCTOC_INVT(QString sCommand)
{
	return sendCommand("CTOC", sCommand);
}

bool NateonDPConnection::parseBuffer( const QStringList & slCommand, QString m_Buffer )
{
	if ( slCommand[0] == "CTOC" )
	{

		if ( m_Buffer.left(4) == "INVT" )
		{
			QStringList slCommand;
			slCommand = QStringList::split(" ", m_Buffer);
			emit receivedINVT(slCommand);
		}
		else if ( m_Buffer.left(4) == "REQC" )
		{
			m_Buffer.stripWhiteSpace();
			QStringList slBody = QStringList::split( " ",  m_Buffer );

			QStringList slHeader( slCommand );

			for ( QStringList::Iterator it = slBody.begin(); it != slBody.end(); ++it )
			{
				slHeader.append( QString(*it).stripWhiteSpace() );
			}

			gotREQCCTOC( slHeader );
		}
	}
	return TRUE;
}

void NateonDPConnection::gotADSB(const QStringList & slCommand)
{
	if ( slCommand[2] == "REQST" )
	{
		emit receivedREQST( slCommand );
#if 0
		if ( slCommand[1] == "0" )
		{
			emit receivedREQST( slCommand );
		}
		else
		{
			emit addBuddyADSB_REQST( slCommand );
		}
#endif
	}
	else if ( slCommand[2] == "ACCPT" )
	{
		if ( slCommand[1] == "0" )
		{
			// Buddy* pBuddy = m_pBuddyList->getBuddyByHandle( slCommand[3] );
			Buddy* pBuddy = m_pBuddyList->getBuddyByHandle( slCommand[1] );
			if ( pBuddy )
			{
				emit allowAccept( 0, pBuddy );
			}
		}
		else
		{
			Buddy* pBuddy = m_pBuddyList->getBuddyByHandle( slCommand[3] );
			if ( pBuddy )
			{
				pBuddy->setName( slCommand[4] );
				emit refreshBuddyList();
			}
		}
	}
	else if ( slCommand[2] == "REJCT" )
	{
		if ( slCommand[1] == "0" )
		{
			Buddy* pBuddy = m_pBuddyList->getBuddyByHandle( slCommand[1] );
			if (pBuddy)
			{
				pBuddy->setUID("XXX");
			}  
			emit receivedREJCT( slCommand );
		}
	}
#ifdef NETDEBUG
	else
	{
		kdDebug() << slCommand[2] << endl;
	}
#endif
}

int NateonDPConnection::putCTOC(QString sCommand)
{
	return sendCommand("CTOC", sCommand);
}

/*!
  knateon: [0]:CTOC
  knateon: [1]:0
  knateon: [2]:ring0320@nate.com
  knateon: [3]:57
  knateon: [4]:REQC
  knateon: [5]:NEW
  knateon: [6]:211.234.239.173:5004
  knateon: [7]:10014827278:7579
  knateon: [8]:645073501
*/
void NateonDPConnection::gotREQCCTOC( QStringList & slCommand )
{
	
	if (slCommand[5] == "NEW") {
		/*! 
		 * 내가 보내는 경우 상대로 부터 REQC NEW를 받음. 
		 */
#if 0
		if (!m_pCommon)
			m_pCommon = new Common();
		/*!
		 * TODO: all ip?
		 * IP리스트로 받음.
		 * 모든 IP에 대해서 접속 시도 해보는것은???
		 */
		QStringList slIPs = m_pCommon->getLocalIP();
#endif
		QString sIP( getLocalIP() );

		QString sHeader;
		QString sBody;
		/*!
		  ex>
		  CTOC 446 ring0320@nate.com N 57
		  REQC RES 124.136.183.198:5004 10014827278:7579
		*/
		sBody = slCommand[4] + " RES " + sIP /* slIPs[0] */ + ":5004" + " " + slCommand[7] + "\r\n";
		sHeader = slCommand[2] + " N " + QString::number( sBody.length() ) + "\r\n";
		sendCommand("CTOC", sHeader + sBody);

		// emit connectToP2P( slCommand );
        emit gotREQCNEW( slCommand );
        
	} else if (slCommand[5] == "FR") {
		/*! 상대가 REQC FR을 보냈을때, */
		emit connectP2PFR( slCommand );
	} else if (slCommand[5] == "RES") {
		/*! 
		 * 상대편에서 파일을 보내는경우,
		 * 내가 파일을 받는경우
		 * REQC RES 를 받음
		 */
		// emit connectToP2P( slCommand );
        kdDebug() << "Got REQC RES!!!" << endl;
        
        emit gotREQCRES( slCommand );
        
	}
}

void NateonDPConnection::slotChangeStatusOnline()
{
	sendCommand("ONST", "O 0 %00 1\r\n");
}

void NateonDPConnection::slotChangeStatusAway()
{
	sendCommand("ONST", "A 0 %00 1\r\n");
}

void NateonDPConnection::slotChangeStatusBusy()
{
	sendCommand("ONST", "B 0 %00 1\r\n");
}

void NateonDPConnection::slotChangeStatusPhone()
{
	sendCommand("ONST", "P 0 %00 1\r\n");
}

void NateonDPConnection::slotChangeStatusMeeting()
{
	sendCommand("ONST", "M 0 %00 1\r\n");
}

void NateonDPConnection::slotChangeStatusOffline()
{
	sendCommand("ONST", "F 0 %00 1\r\n");
}

void NateonDPConnection::gotADDB(const QStringList & slCommand)
{
	/*!
	 * 서버에서 보내는 것은 TID가 0으로 넘어옴.
	 * 본인이 코멘드를 날리고 리턴으로 받는 메시지는 TID가 0이 아님.
	 */
	if ( slCommand[1] == "0" )
	{
		Buddy *pBuddy = m_pBuddyList->getBuddyByID( slCommand[4] );
		if ( pBuddy )
		{
			if ( slCommand[2] == "RL" )
				pBuddy->setRL( FALSE );
			else if ( slCommand[2] == "BL" )
				pBuddy->setBL( FALSE );
			else if ( slCommand[2] == "AL" )
				pBuddy->setAL( FALSE );
			else if ( slCommand[2] == "FL" )
				pBuddy->setFL( FALSE );
		}
		else
		{
			if (slCommand[2] == "RL")
				emit showAddConfirm( slCommand );
		}
	}
}

void NateonDPConnection::slotAddAccept(QString& sCMN, QString& sUID)
{
	/*! ADSB [TID] ACCPT [CMN] [UID] 0 %00 \r\n */
	QString sCommand("ACCPT");
	sCommand += " ";
	sCommand += sCMN;
	sCommand += " ";
	sCommand += sUID;
	sCommand += " 0 %00 \r\n";
	sendCommand("ADSB", sCommand);
}

void NateonDPConnection::slotAddReject(QString& sCMN, QString& sUID)
{
	/*! ADSB [TID] REJCT [CMN] [UID] 0 %00 \r\n */
	QString sCommand("REJCT");
	sCommand += " ";
	sCommand += sCMN;
	sCommand += " ";
	sCommand += sUID;
	sCommand += " 0 %00 \r\n";
	sendCommand("ADSB", sCommand);
}

void NateonDPConnection::sendMsg(QString sCommand)
{
	sendCommand_noTid("", sCommand);
}

void NateonDPConnection::slotChangeNick(QString sNick)
{
	QString sCommand;
	/*
	  sCommand = m_pCurrentAccount->getMyNateID();
	  sCommand += " ";
	*/
	// sNick.replace("&gt;", ">");
	// sNick.replace("&lt;", "<");
	addPercents(sNick);
	sCommand = sNick;
	sCommand += "\r\n";

	sendCommand("CNIK", sCommand);
}

int NateonDPConnection::putLock(const QString & sLock)
{
	QString sCommand("BL");
	sCommand += " ";
	sCommand += sLock;
	sCommand += "\r\n";
  
	return sendCommand("ADDB", sCommand);;
}

int NateonDPConnection::putUnlock(const QString & sUnlock)
{
	QString sCommand("AL");
	sCommand += " ";
	sCommand += sUnlock;
	sCommand += "\r\n";

	return sendCommand("ADDB", sCommand);;
}

void NateonDPConnection::slotPutLockList(QStringList & slList)
{
	for ( QStringList::Iterator it = slList.begin(); it != slList.end(); ++it )
		putLock( *it );
}

void NateonDPConnection::slotPutUnlockList(QStringList & slList)
{
	for ( QStringList::Iterator it = slList.begin(); it != slList.end(); ++it )
		putUnlock( *it );
}

void NateonDPConnection::setGroup0(Buddy* pBuddy)
{
	if (pBList.find( pBuddy->getHandle() ) == 0 )
	{
		Group* pGroup = m_pGroupList->getGroupByID( "0" );
		pGroup->addBuddy( pBuddy );
#ifdef NETDEBUG
		//kdDebug() << "Add New Buddy on 0-Group : " << *pBuddy << endl;
#endif
	}
}

/*!
 * RMVB 239 BL %00 ring0320@lycose.co.kr\r\n
 */
void NateonDPConnection::slotRealDelete(const QString & sID)
{
	QString sCommand;
	sCommand = "BL";
	sCommand += " ";
	sCommand += "%00";
	sCommand += " ";
	sCommand += sID;
	sCommand += "\r\n";
	sendCommand("RMVB", sCommand );

	Buddy *pBuddy = m_pBuddyList->getBuddyByID( sID );
	if ( pBuddy )
	{
		m_pBuddyList->remove( pBuddy );
	}
}

void NateonDPConnection::slotSendLock(const QString & sID)
{
	Buddy *pBuddy = m_pBuddyList->getBuddyByID( sID );
	if ( pBuddy )
	{
		QString sCommand;
		sCommand = "BL";
		sCommand += " ";
		sCommand += pBuddy->getHandle();
		sCommand += " ";
		sCommand += pBuddy->getUID();
		sCommand += "\r\n";
		
		sendCommand("ADDB", sCommand );
	}
}

void NateonDPConnection::slotSendUnlock(const QString & sID)
{
	Buddy *pBuddy = m_pBuddyList->getBuddyByID( sID );
	if ( pBuddy )
	{
		QString sCommand;
		sCommand = "AL";
		sCommand += " ";
		sCommand += pBuddy->getHandle();
		sCommand += " ";
		sCommand += pBuddy->getUID();
		sCommand += "\r\n";
		
		sendCommand("ADDB", sCommand );
	}
}

void NateonDPConnection::putRCON()
{
	QString sCommand( m_pCurrentAccount->getDPip() );
	sCommand += " ";
	sCommand += QString::number( m_pCurrentAccount->getDPport() );
	sCommand += "\r\n";
	sendCommand("RCON", sCommand );
}

