summaryrefslogtreecommitdiffstats
path: root/knights/io_internet.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 01:24:36 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 01:24:36 +0000
commita8c9924456e5335c964e4e55b2dde1963c88726f (patch)
treef5bf107ba079ae460536da778ce2da5e6c68aa69 /knights/io_internet.cpp
downloadknights-a8c9924456e5335c964e4e55b2dde1963c88726f.tar.gz
knights-a8c9924456e5335c964e4e55b2dde1963c88726f.zip
Added KDE3 version of Knights
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/knights@1091568 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'knights/io_internet.cpp')
-rw-r--r--knights/io_internet.cpp1138
1 files changed, 1138 insertions, 0 deletions
diff --git a/knights/io_internet.cpp b/knights/io_internet.cpp
new file mode 100644
index 0000000..e5325cd
--- /dev/null
+++ b/knights/io_internet.cpp
@@ -0,0 +1,1138 @@
+/***************************************************************************
+ io_internet.cpp - description
+ -------------------
+ begin : Thu Aug 16 2001
+ copyright : (C) 2003 by Troy Corbin Jr.
+ email : tcorbin@users.sourceforge.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. *
+ * *
+ ***************************************************************************/
+
+/* KDE */
+#include <ksock.h>
+#include <kprocess.h>
+#include <kmessagebox.h>
+
+/* Qt */
+#include <qobject.h>
+#include <qwidget.h>
+#include <qregexp.h>
+#include <qdns.h>
+#include <qsocket.h>
+#include <qptrlist.h>
+
+/* Local */
+#include "io_internet.moc"
+#include "resource.h"
+#include "dlg_login.h"
+#include "dlg_challenge.h"
+#include "match.h"
+#include "core.h"
+#include "audio.h"
+#include "../config.h"
+
+static const int TXT_Std = 0;
+static const int TXT_Pvt = 1;
+static const int TXT_Ch = 2;
+static const int TXT_Sht = 3;
+static const int TXT_Wsp = 4;
+static const int TXT_Not = 5;
+
+io_internet::io_internet( QWidget *parent, resource *rsrc )
+{
+ myResource = rsrc;
+ challenge = NULL;
+ myTimeseal = NULL;
+ socket = NULL;
+ loginStage = LOGIN_STAGE_NAME;
+ lineBuffer = "";
+ Log = NULL;
+
+ /* set type */
+ this->myType = io_base::INTERNET;
+
+ /* initialize various variables */
+ this->waiting_for_move_list = false;
+ this->myParent = parent;
+ connected = false; /* we are not connected to a server */
+
+ /* create the login dialog and show it to the user */
+ loginDlg = new dlg_login( myParent, "LoginDialog", myResource);
+ connect(loginDlg, SIGNAL( okClicked() ), this, SLOT( connectToServer() ) );
+ connect(loginDlg, SIGNAL( cancelClicked() ), this, SLOT( selfDestruct() ) );
+ connect(loginDlg, SIGNAL( login(QString, QString) ), this, SLOT( setUserInfo(QString, QString) ) );
+}
+
+///////////////////////////////////////////////////////////
+// Destructor
+///////////////////////////////////////////////////////////
+io_internet::~io_internet()
+{
+ TabMap::Iterator i;
+
+ /* Close and remove socket */
+ if( socket != NULL )
+ {
+ if(socket->socket() != -1)
+ {
+ send("quit");
+ }
+ delete socket;
+ }
+ /* Close and remove logfile */
+ if( Log )
+ {
+ Log->close();
+ delete Log;
+ Log = NULL;
+ }
+ /* Remove Timeseal */
+ if( myTimeseal != NULL )
+ {
+ myTimeseal->kill();
+ delete myTimeseal;
+ }
+ /* Close and remove Tabs */
+
+ for(i = myTabList.begin(); i != myTabList.end(); i++)
+ {
+ if(myResource->tabManager->isTab(*i))
+ {
+ myResource->tabManager->removeTab(*i);
+ }
+ }
+}
+
+void io_internet::connectToServer()
+{
+ serverList::iterator i;
+ QWidget *tempTab;
+ QWidget *consoleTab;
+ QValueList<Command>::iterator j;
+
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Thinking );
+ /* Get and parse server config from resource */
+ myServer = NULL;
+ for( i = myResource->servers.begin(); i != myResource->servers.end(); i++ )
+ {
+ if( (*i).CurrentRef )
+ {
+ myServer = &(*i);
+ }
+ }
+ if(myServer == NULL)
+ {
+ /* No server configured. Notify User and die gracefully */
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+ kdError() << "internetio::internetio: Can not find server resource CurrentRef " << endl;
+ KMessageBox::sorry( (QWidget*)myParent, i18n( "There are no servers configured.\nPlease make sure you have at least one server configured." ), i18n( "Cannot find a server."));
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+ return;
+ }
+
+ if(myServer->Port == 0)
+ {
+ myServer->Port = 5000;
+ }
+
+ if(!myServer->Timeseal.isEmpty())
+ {
+ myTimeseal = new KProcess();
+ (*myTimeseal) << myServer->Timeseal << myServer->URL << QString().setNum( myServer->Port )
+ << QString( "-p" ) << QString().setNum(myServer->Port + 1);
+ if(!myTimeseal->start())
+ {
+ /* Couldn't start Timeseal. Notify User and die gracefully */
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+ KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights can not start Timeseal.\nPlease make sure you have the correct path and filename configured." ), i18n( "Cannot find Timeseal."));
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+ return;
+ }
+ socket = new KSocket("127.0.0.1", myServer->Port + 1, 30);
+ if(socket->socket() == -1)
+ {
+ /* try again on a different port, somehow the port hasn't been freed yet */
+ delete socket;
+ myTimeseal->kill();
+
+ myTimeseal = new KProcess();
+ (*myTimeseal) << myServer->Timeseal << myServer->URL << QString().setNum( myServer->Port )
+ << QString( "-p" ) << QString().setNum(myServer->Port + 2);
+ if(!myTimeseal->start())
+ {
+ /* Couldn't start Timeseal. Notify User and die gracefully */
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+ KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights can not start Timeseal.\nPlease make sure you have the correct path and filename configured." ), i18n( "Cannot find Timeseal."));
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+ return;
+ }
+ socket = new KSocket("127.0.0.1", myServer->Port + 2, 30);
+ if(socket->socket() == -1)
+ {
+ /* if we can't do it the second time, give up */
+ /* Couldn't connect to server through Timeseal. Notify User and die gracefully */
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+ KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights is unable to connect to the server.\n Please make sure your internet connection is working and try again."), i18n( "Cannot connect to server(timeseal)."));
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+ return;
+ }
+ }
+ }
+ else
+ {
+ socket = new KSocket(myServer->URL, myServer->Port, 30);
+ if(socket->socket() == -1)
+ {
+ /* Couldn't connect to server. Notify User and die gracefully */
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+ KMessageBox::sorry( (QWidget*)myParent, i18n( "Knights is unable to connect to the server.\n Please make sure your internet connection is working and try again."), i18n( "Cannot connect to server."));
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+ return;
+ }
+ }
+ socket->enableRead(true);
+ socket->enableWrite(true);
+
+ /* connect a signal to readReady */
+ connect(socket, SIGNAL(readEvent(KSocket *)), this, SLOT(readCommand(KSocket *)));
+
+ /* setup the seekTimer and turn it off by default */
+ seekTimer = new QTimer(this);
+ connect(seekTimer, SIGNAL(timeout()), this, SLOT(processSeekTimer()));
+
+ /* succesfully connected to the server, turn connected on and flush the command buffer */
+ connected = true;
+ for(j = myCommandBuffer.begin(); j != myCommandBuffer.end(); j++)
+ {
+ recvCMD(*j);
+ }
+
+ /*
+ Create ICS Related Tabs
+
+ These will need to be moved into thier own functions because we want to be able to open
+ and close these tabs at will, or have multiple open at once. ALL communication to our tabs
+ needs to be done with SIGNALS & SLOTS to facilitate this.
+ */
+ consoleTab = new Console( 0, myServer->Name, myResource );
+ myTabList[consoleTab] = consoleTab;
+ myResource->tabManager->addTab( myTabList[consoleTab], i18n( "%1 Console" ).arg( myServer->Name ) );
+ connect( myTabList[consoleTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) );
+ connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[consoleTab], SLOT( recvCMD( const Command& ) ) );
+
+ tempTab = new tab_SeekList( 0, "seekList", myResource );
+ myTabList[tempTab] = tempTab;
+ myResource->tabManager->addTab( myTabList[tempTab], i18n( "Sought Matches List" ) );
+ connect( myTabList[tempTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) );
+ connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[tempTab], SLOT( recvCMD( const Command& ) ) );
+
+ tempTab = new Challenge_Graph( 0, "seekGraph", myResource );
+ myTabList[tempTab] = tempTab;
+ myResource->tabManager->addTab( myTabList[tempTab], i18n( "Sought Matches Graph" ) );
+ connect( myTabList[tempTab], SIGNAL( sendCMD( const Command& ) ), this, SLOT( recvCMD( const Command& ) ) );
+ connect( this, SIGNAL( sendCMD( const Command& ) ), myTabList[tempTab], SLOT( recvCMD( const Command& ) ) );
+
+ myResource->tabManager->showTab(consoleTab);
+
+ /* ...log file */
+ if( !myServer->LogFile.isEmpty() )
+ {
+ Log = new QFile( myServer->LogFile );
+ if( !Log->open( IO_WriteOnly | IO_Append ) )
+ {
+ if( !Log->open( IO_WriteOnly ) )
+ {
+ kdError() << "Can not open " << myServer->LogFile << " for writing." << endl;
+ }
+ }
+ }
+ qApp->mainWidget()->setCursor( myResource->CURSOR_Standard );
+}
+
+void io_internet::recvCMD(const Command& command)
+{
+ QString error_message;
+
+ if(!connected)
+ {
+ myCommandBuffer.push_back(command);
+ return;
+ }
+
+ switch(((Command)command).getCommand())
+ {
+ case CMD_Move:
+ send(((Command)command).getMove().SAN);
+ break;
+ case CMD_Reset_Server:
+ sendUserSettings();
+ break;
+ case CMD_Toggle_Seek:
+ if(seekTimer->isActive())
+ {
+ /* timer running stop it */
+ seekTimer->stop();
+ emit sendCMD( Command( 0, CMD_Hide_Sought_List ) );
+ }
+ else
+ {
+ /* timer not running start it */
+ seekTimer->start(myResource->Seek_Timer * 100);
+ /* send a sought now */
+ processSeekTimer();
+ }
+ break;
+ case CMD_Player_Finger:
+ send("$finger " + ((Command)command).getData());
+ break;
+ case CMD_Add_Friend:
+ send("$+notify " + ((Command)command).getData());
+ break;
+ case CMD_Ignore_Player:
+ send("$+censor " + ((Command)command).getData());
+ break;
+ case CMD_Player_History:
+ send("$history " + ((Command)command).getData());
+ break;
+ case CMD_Start_Match:
+ send("$play " + ((Command)command).getData());
+ break;
+ case CMD_Assess:
+ send("$assess " + ((Command)command).getData());
+ break;
+ case CMD_Set_Input:
+ sendCMD( command );
+ break;
+ case CMD_Send_To_ICS:
+ if(((Command)command).getData().contains(QRegExp("^(?:\\.|tell)")))
+ {
+ writeToConsole(((Command)command).getData(), "K_PVT");
+ }
+ send(((Command)command).getData());
+ break;
+ case CMD_Examine_Forward:
+ send("$forward 1");
+ break;
+ case CMD_Examine_Backward:
+ send("$backward 1");
+ break;
+ case CMD_White_Resign:
+ case CMD_Black_Resign:
+ send("$resign");
+ break;
+ case CMD_Offer_Draw:
+ send("$draw");
+ break;
+ case CMD_Reject_Draw:
+ send("$decline t draw");
+ break;
+ default:
+ /* do nothing unknown command */
+ kdWarning() << "InternetIO::sendCMD received an unknown command: " << ((Command)command).getCommand() << endl;
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::send
+//
+///////////////////////////////////////
+void io_internet::send(const QString& msg)
+{
+ QString tmp(msg);
+ ssize_t len;
+
+ /* Attach events to specific outgoing text */
+ if( ( tmp == "accept" ) ||
+ ( tmp == "decline" ) ||
+ ( tmp.left(6) == "match " ) )
+ {
+ if( challenge != NULL )
+ {
+ delete challenge;
+ nullifyChallenge();
+ }
+ }
+ if( tmp.right(1) != "\n" )
+ {
+ tmp += "\n";
+ }
+
+ len = write(socket->socket(), tmp.latin1(), tmp.length() );
+
+ if( Log )
+ {
+ Log->writeBlock( QString("<< ").latin1(), 3 );
+ Log->writeBlock( tmp.latin1(), tmp.length() );
+ }
+ if( len < (signed)tmp.length() )
+ {
+ kdWarning() << "io_internet::Send: Failed to write full block of data to socket." << endl;
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::readCommand
+//
+///////////////////////////////////////
+void io_internet::readCommand(KSocket* socket)
+{
+ char buffer[READ_BUFFER_SIZE];
+ QString tmp;
+ QStringList lines;
+
+ memset(buffer, 0, READ_BUFFER_SIZE);
+ read(socket->socket(), buffer, READ_BUFFER_SIZE);
+ tmp = buffer;
+
+ tmp = lineBuffer + tmp;
+ if( Log )
+ {
+ Log->writeBlock( tmp.latin1(), tmp.length() );
+ }
+ if(loginStage != LOGIN_STAGE_LOGGED_IN)
+ {
+ // route all the data to the login parser
+ parseLoginData(tmp);
+ this->parseMode = NORMAL_MODE;
+ }
+ else
+ {
+ lines = QStringList::split( QRegExp("\n\r?"), tmp, FALSE );
+ if(!(tmp.endsWith("\n\r") || tmp.endsWith("\n")))
+ {
+ lineBuffer = (*(--lines.end()));
+ }
+ else
+ {
+ lineBuffer = "";
+ }
+ for(QStringList::iterator i = lines.begin(); i != lines.end(); i++)
+ {
+ if(lineBuffer == "" || i != --lines.end())
+ {
+ (*i).replace( QRegExp( "\\a" ), "" );
+ parseLine(*i);
+ }
+ }
+ }
+}
+///////////////////////////////////////
+//
+// io_internet::sendUserName
+//
+///////////////////////////////////////
+void io_internet::sendUserName()
+{
+ loginStage = LOGIN_STAGE_PASSWORD;
+ send(userName);
+}
+///////////////////////////////////////
+//
+// io_internet::sendPassword
+//
+///////////////////////////////////////
+void io_internet::sendPassword()
+{
+ send(passWord);
+}
+
+///////////////////////////////////////
+//
+// io_internet::parseLoginData
+//
+///////////////////////////////////////
+void io_internet::parseLoginData( QString data )
+{
+ QStringList lines;
+
+ if(loginStage == LOGIN_STAGE_NAME)
+ {
+ if(data.contains( "login:" ))
+ {
+ sendUserName();
+ }
+ lines = QStringList::split( QRegExp("\n\r?"), data, FALSE );
+ for(QStringList::iterator i = lines.begin(); i != lines.end(); i++)
+ {
+ writeToConsole((*i), "K_STD");
+ }
+ }
+ else if(loginStage == LOGIN_STAGE_PASSWORD)
+ {
+ if(data.contains("**** Invalid password! ****") ||
+ data.contains("Sorry, names can only consist of lower and upper case letters. Try again.") ||
+ data.contains("If you are not a registered player, enter guest or a unique ID."))
+ {
+ loginDlg = new dlg_login( myParent, "LoginDialog", myResource);
+ loginDlg->disableServerSelect();
+ connect(loginDlg, SIGNAL( okClicked() ), this, SLOT( sendUserName() ) );
+ connect(loginDlg, SIGNAL( cancelClicked() ), this, SLOT( selfDestruct() ) );
+ connect(loginDlg, SIGNAL( login(QString, QString) ), this, SLOT( setUserInfo(QString, QString) ) );
+ }
+ else if(data.contains("Press return to enter the server as"))
+ {
+ QRegExp guestName("Logging you in as \"(\\w*)\"");
+ int pos = guestName.search(data);
+ if(pos > -1)
+ {
+ userName = guestName.cap(1);
+ }
+ send("\n");
+ }
+ else if(data.contains("password:"))
+ {
+ sendPassword();
+ }
+ else
+ {
+ loginStage = LOGIN_STAGE_LOGGED_IN;
+ sendUserSettings();
+ }
+ lines = QStringList::split( QRegExp("\n\r?"), data, FALSE );
+ for(QStringList::iterator i = lines.begin(); i != lines.end(); i++)
+ {
+ writeToConsole((*i), "K_STD");
+ }
+ }
+ else
+ {
+ lines = QStringList::split( QRegExp("\n\r?"), data, FALSE );
+ for(QStringList::iterator i = lines.begin(); i != lines.end(); i++)
+ {
+ writeToConsole((*i), "K_STD");
+ }
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::ParseLine
+//
+///////////////////////////////////////
+void io_internet::parseLine( QString line )
+{
+ int i, j;
+ QString tmp;
+
+ switch(parseMode)
+ {
+ case NORMAL_MODE: /* determine which mode we should go into */
+ if(line.contains(QRegExp("^\\s*\\d{1,3}\\s+(?:\\d{1,4}|\\+\\+\\+\\+|\\-\\-\\-\\-)\\s+\\w{3,17}(\\(C\\))?\\s+\\d{1,3}\\s+\\d{1,3}")))
+ {
+ updateSoughtList(line);
+ parseMode = UPDATE_SOUGHT_MODE;
+ }
+ /* CHALLENGE */
+ else if( line.contains(QRegExp("^\\s*Challenge: ")))
+ {
+ myResource->play( SND_CHALLENGE );
+ if( challenge != NULL )
+ {
+ delete challenge;
+ }
+ challenge = new dlg_challenge( 0, "Challenge", myResource );
+ connect( challenge, SIGNAL( destroyed() ), this, SLOT( nullifyChallenge() ) );
+ connect( challenge, SIGNAL( user1Clicked() ), this, SLOT( acceptChallenge() ) );
+ connect( challenge, SIGNAL( user2Clicked() ), this, SLOT( declineChallenge() ) );
+ line.replace(QRegExp("^\\s*Challenge: "), "");
+ challenge->setValues( line, userName );
+ parseMode = CHALLENGE_MODE;
+ }
+ else if( ( line.left(15) == "Challenge from " ) && ( line.right(9) == " removed." ) )
+ {
+ if( challenge != NULL )
+ {
+ delete challenge;
+ }
+ }
+ /* SOUGHT GAME */
+ else if(line.contains("seeking"))
+ {
+ // writeToConsole("seeking", "K_CH");
+ }
+ /* PRIVATE TELL */
+ else if(line.contains(QRegExp(".+ tells you: .*")))
+ {
+ /* First grab the user name so we can auto-respond later */
+ emit sendCMD( Command( 0, CMD_Set_Src_Tell, line.section(' ', 0, 0) ) );
+ myResource->play( SND_TELL );
+ writeToConsole(line, "K_PVT");
+ }
+ /* SAY */
+ else if(line.contains( QRegExp(".+ says: .*")))
+ {
+ myResource->play(SND_SAY);
+ writeToConsole(line, "K_PVT");
+ return;
+ }
+ /* WHISPER & KIBITZ */
+ else if(line.contains(QRegExp(".+ whispers: .*")) || line.contains(QRegExp(".+ kibitzes: .*")))
+ {
+ writeToConsole(line, "K_WSP");
+ }
+ /* Important System Messages: Use Whisper Color */
+ else if(line.contains(QRegExp("declines the draw request\\.$" )))
+ {
+ writeToConsole(line, "K_WSP");
+ }
+ /* DRAW OFFER */
+ else if(line.right(19) == " offers you a draw.")
+ {
+ writeToConsole(line, "K_WSP");
+ }
+ else if( line.contains( QRegExp(".+rating adjustment:.+" ) ) )
+ {
+ writeToConsole(line, "K_WSP");
+ }
+ /* SHOUTS */
+ else if( line.contains( QRegExp("^c?t?s?-?shouts: ") ) )
+ {
+ writeToConsole(line, "K_SHT");
+ }
+ /* NOTIFY */
+ else if((line.contains(QRegExp("\\s*Notification:"))) ||
+ (line.contains(QRegExp("\\s*Present company includes:"))) ||
+ (line.contains(QRegExp("\\s*Your arrival was noted by:"))))
+ {
+ writeToConsole(line, "K_NOT");
+ myResource->play( SND_NOTIFICATION );
+ }
+ /* CHANNEL TELLS */
+ else if(line.contains(QRegExp( ".\\(\\d+\\):" )))
+ {
+ /* First grab the channel # so we can auto-respond later */
+ j = line.find(QString("):"));
+ i = line.findRev(QString("("), j) + 1;
+ emit sendCMD( Command( 0, CMD_Set_Src_Channel, line.mid(i, j - i) ) );
+ writeToConsole(line, "K_CH");
+ }
+ else if(line.contains(QRegExp("^<12>\\s")))
+ {
+ /* a game move */
+ parseStyle12(line, PARSE12_MODE_MOVE);
+ }
+ else if(line.contains(QRegExp("^<b1>\\s")))
+ {
+ /* a bughouse piece has been passed or a piece has been captured in crazyhouse */
+ writeToConsole(line, "K_CH");
+ }
+ else if(line.contains(QRegExp("^\\\\")))
+ {
+ writeToConsole(line, lastTag);
+ }
+ else if(line.contains(QRegExp("^\\{?Game \\d+")) && line.contains("Creating", TRUE))
+ {
+ parseMode = NEW_GAME_MODE;
+ }
+ else if(line.contains("You are now observing game"))
+ {
+ parseMode = OBSERVE_GAME_MODE;
+ }
+ else if(line.startsWith("Movelist for game"))
+ {
+ QRegExp gameNumber("\\d+");
+ int pos = gameNumber.search(line);
+ if(pos > -1)
+ {
+ ficsMoveListNumber = gameNumber.cap(0).toInt();
+ }
+ parseMode = PARSE_MOVE_LIST_MODE;
+ }
+ else if((line.contains(QRegExp("^\\{?Game \\d+")) || line.contains(QRegExp("Game \\d+"))) &&
+ (
+ line.contains(" forfeits by disconnection", TRUE) ||
+ line.contains(" forfeits by disconnection}", TRUE) ||
+ line.contains(" forfeits on time} ", TRUE) ||
+ line.contains(" forfeits on time ", TRUE) ||
+ line.contains(" resigns} ", TRUE) ||
+ line.contains(" resigns ", TRUE) ||
+ line.contains(" Game drawn by mutual agreement ", TRUE) ||
+ line.contains(" Game drawn by mutual agreement} ", TRUE) ||
+ line.contains(", has lost contact or quit.", TRUE) ||
+ line.contains(" checkmated ", TRUE) ||
+ line.contains(" checkmated} ", TRUE) ||
+ line.contains("lost connection", TRUE) ||
+ line.contains("has no material to mate", TRUE)
+ )
+ )
+ {
+ sendEndOfGameCommand(line);
+ }
+ else
+ {
+ /* don't know what to do with it, just send it to the console */
+ /* don't write the prompt to the console */
+ if( line.contains( QRegExp( "^a?d?f?g?s?z?ics% " ) ) ||
+ line.contains( QRegExp( "^cex% " ) ) ||
+ line.contains( QRegExp( "^chess% " ) ) )
+ break;
+ writeToConsole(line, "K_STD");
+ }
+ break;
+ case UPDATE_SOUGHT_MODE:
+ if(line.contains(QRegExp("\\d+\\s+ads? displayed.")))
+ {
+ updateSoughtList(line);
+ parseMode = NORMAL_MODE;
+ }
+ else
+ {
+ updateSoughtList(line);
+ }
+ break;
+ case NEW_GAME_MODE:
+ if(line.contains(QRegExp("<12>\\s")))
+ {
+ /* a game move */
+ parseStyle12(line, PARSE12_MODE_NEW);
+ }
+ else if((line.startsWith("fics%") && line.length() == 6))
+ {
+ parseMode = NORMAL_MODE;
+ }
+ break;
+ case OBSERVE_GAME_MODE:
+ if(line.contains(QRegExp("<12>\\s")))
+ {
+ /* a game move */
+ parseStyle12(line, PARSE12_MODE_NEW);
+ send("moves");
+ parseMode = NORMAL_MODE;
+ }
+ break;
+ case CHALLENGE_MODE:
+ if(line.startsWith("You can \"accept\" or \"decline\", or propose"))
+ {
+ parseMode = NORMAL_MODE;
+ }
+ break;
+ case PARSE_MOVE_LIST_MODE:
+ if(!line.contains("{Still in progress}"))
+ {
+ if(line.contains(QRegExp("\\d\\.")))
+ {
+ parseMoveList(line);
+ }
+ }
+ else
+ {
+ parseMode = NORMAL_MODE;
+ }
+ break;
+ default: /* do nothing */
+ break;
+ };
+}
+
+///////////////////////////////////////
+//
+// io_internet::ParseStyle12
+//
+///////////////////////////////////////
+void io_internet::parseStyle12(QString line, const unsigned int Mode)
+{
+// kdWarning() << line << endl;
+
+ struct ChessMove move;
+ QStringList fields;
+ QString position_line = "";
+ match_param *param = NULL;
+ Command::clearMove(&move);
+ switch(Mode)
+ {
+ case PARSE12_MODE_NEW:
+ {
+ /* a new game that we are playing, or observing */
+ param = new match_param(this->myResource);
+ fields = QStringList::split( QChar(' '), line, FALSE );
+
+ /* set white time control */
+ TCPList tmpListWhite(param->time(WHITE));
+ TCP tmpTCPWhite = tmpListWhite[0];
+ tmpTCPWhite.Seconds = fields[20].toInt() * 60;
+ tmpTCPWhite.Increment = fields[21].toInt();
+ tmpListWhite[0] = tmpTCPWhite;
+ param->setTime(WHITE, tmpListWhite);
+
+ /* set black time control */
+ TCPList tmpListBlack(param->time(BLACK));
+ TCP tmpTCPBlack = tmpListBlack[0];
+ tmpTCPBlack.Seconds = fields[20].toInt() * 60;
+ tmpTCPBlack.Increment = fields[21].toInt();
+ tmpListBlack[0] = tmpTCPBlack;
+ param->setTime(BLACK, tmpListBlack);
+
+ if((userName.upper() == fields[17].upper()) &&
+ ((fields[19].toInt() == -1) || (fields[19].toInt() == 1)))
+ {
+ /* I am playing white */
+ param->setType(WHITE, PLAYERLOCAL);
+ }
+ else if(fields[19].toInt() != 2)
+ {
+ /* I am not playing white */
+ param->setType(WHITE, PLAYERTCP);
+ }
+
+ if((userName.upper() == fields[18].upper()) &&
+ ((fields[19].toInt() == -1) || (fields[19].toInt() == 1)))
+ {
+ /* I am playing black */
+ param->setType(BLACK, PLAYERLOCAL);
+ }
+ else if(fields[19].toInt() != 2)
+ {
+ /* I am not playing black */
+ param->setType(BLACK, PLAYERTCP);
+ }
+
+ if(fields[19].toInt() == 2)
+ {
+ param->setType(WHITE, PLAYEREXAMINE);
+ param->setType(BLACK, PLAYEREXAMINE);
+ }
+ //param->setVariation(something); figure out how to get the variation
+ param->setName(WHITE, fields[17]);
+ param->setName(BLACK, fields[18]);
+ /* tell core to connect us to a new match */
+ fics_to_knights[fields[16].toInt()] = ((core*)myParent)->newMatch(param)->getID();
+ }
+ case PARSE12_MODE_MOVE:
+ {
+ fields = QStringList::split( QChar(' '), line, FALSE );
+
+ /* various ICS stuff for ChessMove */
+ move.ICS_ClockTicking = fields[31].toInt();
+ move.ICS_PawnPushFile = fields[10].toShort();
+ move.ICS_MoveCounter = fields[15].toInt();
+ if(fields[9] == "W")
+ {
+ move.ICS_OnMove = BLACK;
+ }
+ else if( fields[9] == "B" )
+ {
+ move.ICS_OnMove = WHITE;
+ }
+
+ switch( fields[19].toInt() )
+ {
+ /* Examining a game */
+ case 2:
+ move.ICS_Mode = ICS_Examine;
+ if(fics_to_knights[fields[16].toInt()] == 0)
+ {
+ /* no new game started yet, call parsestyle 12 with a different mode */
+ parseStyle12(line, PARSE12_MODE_NEW);
+ return;
+ }
+ break;
+ /* Observing a game */
+ case -2:
+ case 0:
+ move.ICS_Mode = ICS_Observe;
+ break;
+ /* Playing a game */
+ default:
+ move.ICS_Mode = ICS_Normal;
+ break;
+ }
+
+ /* Verbose Coordinate Notation of previous move ( USE AS CAN ) */
+ strcpy(move.CAN, fields[27].right(fields[27].length() - 2).replace(QRegExp("-"), ""));
+ /* SAN */
+ strcpy(move.SAN, fields[29].replace(QRegExp("\\+"), "").replace(QRegExp("#"), ""));
+
+ /* fill the line for the command */
+ position_line += fields[1]; /* Internal Rank #7 */
+ position_line += fields[2]; /* Internal Rank #6 */
+ position_line += fields[3]; /* Internal Rank #5 */
+ position_line += fields[4]; /* Internal Rank #4 */
+ position_line += fields[5]; /* Internal Rank #3 */
+ position_line += fields[6]; /* Internal Rank #2 */
+ position_line += fields[7]; /* Internal Rank #1 */
+ position_line += fields[8]; /* Internal Rank #0 */
+ /* Can White Castle Short (boolean) */
+ position_line += fields[11];
+ /* Can White Castle Long (boolean) */
+ position_line += fields[12];
+ /* Can Black Castle Short (boolean) */
+ position_line += fields[13];
+ /* Can Black Castle Long (boolean) */
+ position_line += fields[14];
+
+ Command command(fics_to_knights[fields[16].toInt()], CMD_Move, fields[24].toInt() * 100,
+ fields[25].toInt() * 100, move);
+ command.setData(position_line);
+ emit sendCMD(command);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::ParsePlayer
+//
+///////////////////////////////////////
+//void io_internet::ParsePlayer( QString Handle )
+//{
+// player.Raw = Handle;
+ /* SysAdmin */
+// if( Handle.contains( QRegExp("\\(\\*\\)") ) )
+// {
+// player.SysAdmin = TRUE;
+// Handle.replace( QRegExp("\\(\\*\\)"), QString("") );
+// }
+// else player.SysAdmin = FALSE;
+ /* ServiceRep */
+// if( Handle.contains( QRegExp("\\(SR\\)") ) )
+// {
+// player.ServiceRep = TRUE;
+// Handle.replace( QRegExp("\\(SR\\)"), QString("") );
+// }
+// else player.ServiceRep = FALSE;
+ /* Computer */
+// if( Handle.contains( QRegExp("\\(C\\)") ) )
+// {
+// player.Computer = TRUE;
+// Handle.replace( QRegExp("\\(C\\)"), QString("") );
+// }
+// else player.Computer = FALSE;
+ /* Unregistered */
+// if( Handle.contains( QRegExp("\\(U\\)") ) )
+// {
+// player.Unregistered = TRUE;
+// Handle.replace( QRegExp("\\(U\\)"), QString("") );
+// }
+// else player.Unregistered = FALSE;
+// return;
+//}
+///////////////////////////////////////
+//
+// io_internet::nullifyChallenge
+//
+///////////////////////////////////////
+void io_internet::nullifyChallenge( void )
+{
+ challenge = NULL;
+}
+
+///////////////////////////////////////
+//
+// io_internet::declineChallenge
+//
+///////////////////////////////////////
+void io_internet::declineChallenge( void )
+{
+ send( "decline" );
+ delete challenge;
+ challenge = NULL;
+}
+///////////////////////////////////////
+//
+// io_internet::acceptChallenge
+//
+///////////////////////////////////////
+void io_internet::acceptChallenge( void )
+{
+ send( challenge->values() );
+ delete challenge;
+ challenge = NULL;
+}
+
+///////////////////////////////////////
+//
+// io_internet::writeToConsole
+//
+///////////////////////////////////////
+void io_internet::writeToConsole(QString text, QString tag)
+{
+ lastTag = tag;
+ /* Remove Bells */
+ text.replace( QRegExp("\\x0007") , "" );
+ /* Replace misc characters with rich-text friendly counterparts */
+ text.replace( QRegExp("\\x003c"), "&#60;" );
+ text.replace( QRegExp("\\x007c"), "&#124;" );
+ text.replace( QRegExp( "\\f"), "");
+ text.replace( QRegExp( "\\n"), "");
+ text.replace( QRegExp( "\\r*" ), "" );
+ emit sendCMD( Command( 0, CMD_Append_To_Console, "<" + tag + ">" + text + "</" + tag + ">" ) );
+}
+
+///////////////////////////////////////
+//
+// io_internet::updateSoughtList
+//
+///////////////////////////////////////
+void io_internet::updateSoughtList(QString soughtLine)
+{
+ /* "ADS DISPLAYED" MESSAGE */
+ if(soughtLine.contains(QRegExp("\\d+\\s+ads? displayed.")))
+ {
+ emit sendCMD( Command( 0, CMD_Show_Sought_List ) );
+ }
+ else
+ {
+ emit sendCMD( Command( 0, CMD_Add_Sought_Match, soughtLine ) );
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::sendUserSettings()
+//
+///////////////////////////////////////
+void io_internet::sendUserSettings()
+{
+ send("set style 12");
+ send(QString("set interface Knights %1").arg(_VERSION_));
+ send(QString("set private %1").arg(myResource->OPTION_Private));
+ send(QString("set kibitz %1").arg(myResource->OPTION_Kibitz));
+ send(QString("set tell %1").arg(myResource->OPTION_Tell));
+ send(QString("set shout %1").arg(myResource->OPTION_Shout));
+ send(QString("set seek %1").arg(myResource->OPTION_Seek));
+ send(QString("set tolerance %1").arg(myResource->OPTION_Profanity));
+}
+
+///////////////////////////////////////
+//
+// io_internet::parseMoveList(QString data)
+//
+///////////////////////////////////////
+void io_internet::parseMoveList(QString line)
+{
+ QStringList two_plys;
+ struct ChessMove move;
+ Command command;
+ int move_counter = 0;
+
+ /* white */
+ two_plys = QStringList::split(QRegExp("\\s+"), line, FALSE);
+ Command::clearMove(&move);
+ move_counter = two_plys[0].left(two_plys[0].length() - 1).length(); /* remove the . */
+ move.ICS_MoveCounter = move_counter;
+ move.ICS_Mode = ICS_Movelist;
+ move.ICS_OnMove = WHITE;
+ strcpy(move.SAN, two_plys[1]);
+ command.setCommand((int&)CMD_Move);
+ command.setID(fics_to_knights[ficsMoveListNumber]);
+ command.setMove(move);
+ emit sendCMD(command);
+
+ /* black */
+ if(two_plys.size() > 3)
+ {
+ Command::clearMove(&move);
+ move.ICS_MoveCounter = move_counter;
+ move.ICS_Mode = ICS_Movelist;
+ move.ICS_OnMove = BLACK;
+ strcpy(move.SAN, two_plys[3]);
+ command.setCommand((int&)CMD_Move);
+ command.setID(fics_to_knights[ficsMoveListNumber]);
+ command.setMove(move);
+ emit sendCMD(command);
+ }
+}
+
+///////////////////////////////////////
+//
+// io_internet::sendEndOfGameCommand(QString line)
+//
+///////////////////////////////////////
+void io_internet::sendEndOfGameCommand(QString line)
+{
+ QStringList fields;
+ Command command;
+
+ fields = QStringList::split( QChar(' '), line, FALSE );
+ if(fields[1].endsWith(":"))
+ {
+ fields[1] = fields[1].left(fields[1].length() - 1);
+ }
+ command.setID(fics_to_knights[fields[1].toInt()]);
+ fields[fields.count() - 1] = fields[fields.count() - 1].stripWhiteSpace();
+ if(fields[fields.count() - 1] == "1-0" )
+ {
+ if(fields[fields.count() - 2].contains("resigns"))
+ {
+ command.setCommand((int&)CMD_Black_Resign);
+ }
+ else if(fields[fields.count() - 2].contains("time"))
+ {
+ command.setCommand((int&)CMD_White_Called_Flag);
+ }
+ else
+ {
+ command.setCommand((int&)CMD_Result_White);
+ }
+ }
+ else if(fields[fields.count() - 1] == "0-1")
+ {
+ if(fields[fields.count() - 2].contains("resigns"))
+ {
+ command.setCommand((int&)CMD_White_Resign);
+ }
+ else if(fields[fields.count() - 2].contains("time"))
+ {
+ command.setCommand((int&)CMD_Black_Called_Flag);
+ }
+ else
+ {
+ command.setCommand((int&)CMD_Result_Black);
+ }
+ }
+ else if(fields[fields.count() - 1] == "1/2-1/2")
+ {
+ command.setCommand((int&)CMD_Result_Draw);
+ }
+ else
+ {
+ command.setCommand((int&)CMD_Lost_Contact);
+ }
+ emit sendCMD(command);
+}
+
+///////////////////////////////////////
+//
+// io_internet::processSeekTimer()
+//
+///////////////////////////////////////
+void io_internet::processSeekTimer()
+{
+ /* timer timed out, send out a sought */
+ send("sought");
+}
+
+///////////////////////////////////////
+//
+// io_internet::selfDestruct()
+//
+///////////////////////////////////////
+void io_internet::selfDestruct()
+{
+ /* cause the io_internet to delete itself */
+ QApplication::postEvent( qApp->mainWidget(), new QCustomEvent( EVENT_Del_IO_Net ) );
+}
+
+///////////////////////////////////////
+//
+// io_internet::setUserInfo()
+//
+///////////////////////////////////////
+void io_internet::setUserInfo(QString userName, QString passWord)
+{
+ this->userName = userName;
+ this->passWord = passWord;
+}
+