Mercurial > hg > octave-lyh
changeset 13581:3e5a8ef9c76d
Completely rewrote IRC client backend to make it platform-independent. Not all functionality has been reimplemented as of yet, though.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Tue, 02 Aug 2011 02:59:25 +0200 |
parents | 64a3a1f23718 |
children | 61b06a397021 |
files | gui/octave-gui.pro gui/src/IRCWidget.cpp gui/src/IRCWidget.h gui/src/MainWindow.cpp gui/src/qirc/IClientSocket.cpp gui/src/qirc/IClientSocket.h gui/src/qirc/IRCClientImpl.cpp gui/src/qirc/IRCClientImpl.h gui/src/qirc/IRCClientInterface.h |
diffstat | 9 files changed, 527 insertions(+), 565 deletions(-) [+] |
line wrap: on
line diff
--- a/gui/octave-gui.pro +++ b/gui/octave-gui.pro @@ -85,8 +85,6 @@ src/BrowserWidget.cpp \ src/ImageViewerMdiSubWindow.cpp \ src/IRCWidget.cpp \ - src/qirc/IRCClient.cpp \ - src/qirc/IClientSocket.cpp \ src/SettingsDialog.cpp \ src/OctaveGUI.cpp \ src/ResourceManager.cpp \ @@ -133,8 +131,6 @@ src/ImageViewerMdiSubWindow.h \ src/IRCWidget.h \ src/qirc/IRCCodes.h \ - src/qirc/IRCClient.h \ - src/qirc/IClientSocket.h \ src/SettingsDialog.h \ src/ResourceManager.h \ src/CommandLineParser.h \
--- a/gui/src/IRCWidget.cpp +++ b/gui/src/IRCWidget.cpp @@ -28,7 +28,6 @@ IRCWidget::IRCWidget (QWidget * parent): QWidget (parent) { - m_alternatingColor = false; QSettings *settings = ResourceManager::instance ()->settings (); bool connectOnStartup = settings->value ("connectOnStartup").toBool (); m_autoIdentification = settings->value ("autoIdentification").toBool (); @@ -52,16 +51,17 @@ QHBoxLayout *bottomLayout = new QHBoxLayout (); m_nickButton = new QPushButton (bottomWidget); - m_nickButton-> - setStatusTip (tr ((char *) "Click here to change your nick.")); + m_nickButton->setStatusTip (tr ((char *) "Click here to change your nick.")); m_nickButton->setText (m_initialNick); m_inputLine = new QLineEdit (bottomWidget); m_inputLine->setStatusTip (tr ((char *) "Enter your message here.")); + bottomLayout->addWidget (m_nickButton); bottomLayout->addWidget (new QLabel (":", this)); bottomLayout->addWidget (m_inputLine); bottomLayout->setMargin (0); bottomWidget->setLayout (bottomLayout); + m_nickButton->setEnabled (false); m_inputLine->setEnabled (false); @@ -73,42 +73,28 @@ font.setFamily ("Courier"); font.setPointSize (11); m_chatWindow->setFont (font); - m_ircClient = new IRCClient (); + m_ircClientImpl = new IRCClientImpl (); + connect (m_ircClientImpl, SIGNAL (connected (QString)), + this, SLOT (handleConnected (QString))); + connect (m_ircClientImpl, SIGNAL(loggedIn(QString)), + this, SLOT (joinOctaveChannel (QString))); + connect (m_ircClientImpl, SIGNAL (error (QString)), + this, SLOT (showErrorMessage (QString))); + connect (m_ircClientImpl, SIGNAL (debugMessage (QString)), + this, SLOT (showStatusMessage (QString))); + connect (m_ircClientImpl, SIGNAL (message (QString, QString, QString)), + this, SLOT (showMessage (QString, QString, QString ))); + connect (m_ircClientImpl, SIGNAL (nicknameChanged (QString,QString)), + this, SLOT (handleNickChange (QString,QString))); + connect (m_ircClientImpl, SIGNAL (notification (QString,QString)), + this, SLOT (showNotification (QString,QString))); + connect (m_ircClientImpl, SIGNAL (loggedIn(QString)), + this, SLOT (handleLoggedIn(QString))); connect (m_nickButton, SIGNAL (clicked ()), this, SLOT (nickPopup ())); connect (m_inputLine, SIGNAL (returnPressed ()), this, SLOT (sendInputLine ())); - connect (m_ircClient, SIGNAL (nickInUseChanged ()), this, - SLOT (handleNickInUseChanged ())); - connect (m_ircClient, SIGNAL (connectionStatus (const char *)), this, - SLOT (showStatusMessage (const char *))); - connect (m_ircClient, SIGNAL (error (const char *)), this, - SLOT (showStatusMessage (const char *))); - connect (m_ircClient, SIGNAL (completedLogin (const char *)), this, - SLOT (loginSuccessful (const char *))); - connect (m_ircClient, SIGNAL (completedLogin (const char *)), this, - SLOT (joinOctaveChannel (const char *))); - connect (m_ircClient, - SIGNAL (topic (const char *, const char *, const char *)), this, - SLOT (showTopic (const char *, const char *, const char *))); - connect (m_ircClient, SIGNAL (join (const char *, const char *)), this, - SLOT (showJoin (const char *, const char *))); - connect (m_ircClient, SIGNAL (quit (const char *, const char *)), this, - SLOT (showQuit (const char *, const char *))); - connect (m_ircClient, - SIGNAL (privateMessage (const char *, const char *, const char *)), - this, - SLOT (showPrivateMessage - (const char *, const char *, const char *))); - connect (m_ircClient, - SIGNAL (notice (const char *, const char *, const char *)), this, - SLOT (showNotice (const char *, const char *, const char *))); - connect (m_ircClient, SIGNAL (nick (const char *, const char *)), this, - SLOT (showNickChange (const char *, const char *))); - connect (m_ircClient, SIGNAL (replyCode (IRCEvent *)), this, - SLOT (handleReplyCode (IRCEvent *))); - if (connectOnStartup) connectToServer (); } @@ -116,96 +102,74 @@ void IRCWidget::connectToServer () { - m_ircClient->connectToServer ("irc.freenode.net", 6667, - m_initialNick.toStdString ().c_str (), - m_initialNick.toStdString ().c_str (), - "Unknown", "Unknown", 0, 0); + showStatusMessage ("<font color=\"#990000\"><b>IMPORTANT: THE BACKEND FOR THE IRC CHAT HAS BEEN REWRITTEN COMPLETELY TO MAKE IT PLATFORM-INDEPENDENT.</b></font>"); + showStatusMessage ("<font color=\"#990000\"><b>IT WILL PROBABLY NOT WORK AS IT SHOULD UNTIL ALL BUGS HAVE BEEN FIXED.</b></font>"); + showStatusMessage ("Looking up irc.freenode.net."); + QHostInfo hostInfo = QHostInfo::fromName ("irc.freenode.net"); + QList<QHostAddress> hostAddresses = hostInfo.addresses(); + if (hostAddresses.isEmpty ()) + { + showStatusMessage ("Failed to lookup irc.freenode.net."); + } + else + { + showStatusMessage (QString ("Attempting to connect to %1.") + .arg (hostAddresses.at (0).toString ())); + m_ircClientImpl->connectToHost(hostAddresses.at (0), 6667, m_initialNick); + } } void -IRCWidget::showStatusMessage (const char *message) +IRCWidget::showStatusMessage (const QString& message) { m_chatWindow->append (QString ("<i>%1</i>").arg (message)); } void -IRCWidget::joinOctaveChannel (const char *) +IRCWidget::showErrorMessage (const QString& message) { - m_ircClient->joinChannel ("#octave"); + m_chatWindow->append (QString ("<i>Error: %1</i>").arg (message)); } void -IRCWidget::loginSuccessful (const char *nick) +IRCWidget::handleConnected (const QString &host) { - m_chatWindow-> - append (QString - ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). - arg (nick)); - m_nickButton->setEnabled (true); - m_inputLine->setEnabled (true); - m_chatWindow->setEnabled (true); - m_inputLine->setFocus (); + showStatusMessage (QString ("Connected to server %1.").arg (host)); +} - if (m_autoIdentification) - m_ircClient->sendCommand (2, COMMAND_PRIVMSG, - "NickServ", - QString ("identify %1"). - arg (m_nickServPassword).toStdString (). - c_str ()); +void +IRCWidget::joinOctaveChannel (const QString& nick) +{ + Q_UNUSED (nick); + showStatusMessage (QString ("Joining channel #octave.")); + m_ircClientImpl->sendJoinRequest ("#octave"); } void -IRCWidget::showPrivateMessage (const char *nick, const char *destination, - const char *message) +IRCWidget::showMessage (const QString& channel, const QString& sender, const QString& message) { - Q_UNUSED (destination); - QString msg(message); - msg.replace ("<", "<"); - msg.replace (">", ">"); - if (msg.contains (m_ircClient->nickInUse ())) + Q_UNUSED (channel); + QString output; + if (message.contains (m_ircClientImpl->nickname ())) { - msg = - QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (nick). - arg (msg); + output = + QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (sender). + arg (message); } else { - msg = - QString ("<font color=\"%3\"><b>%1:</b> %2</font>").arg (nick). - arg (msg).arg (getAlternatingColor ()); + output = + QString ("<b>%1:</b> %2").arg (sender). + arg (message); } - m_chatWindow->append (msg); + m_chatWindow->append (output); } void -IRCWidget::showNotice (const char *nick, const char *destination, - const char *message) -{ - Q_UNUSED (nick); - Q_UNUSED (destination); - m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>"). - arg (message)); -} - -void -IRCWidget::showTopic (const char *nick, const char *channel, - const char *message) +IRCWidget::showNotification (const QString& sender, const QString& message) { - QString msg (message); - msg.replace ("<", "<"); - msg.replace (">", ">"); - m_chatWindow->append (QString ("Topic for %2 was set by %1: %3").arg (nick). - arg (channel).arg (msg)); -} - -void -IRCWidget::showNickChange (const char *oldNick, const char *newNick) -{ - m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick). - arg (newNick)); - m_nickList.removeAll (QString (oldNick)); - m_nickList.append (QString (newNick)); - updateNickCompleter (); + Q_UNUSED (sender); + m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>").arg (message)); } void @@ -215,32 +179,14 @@ QString newNick = QInputDialog::getText (this, QString ("Nickname"), QString ("Type in your nickname:"), - QLineEdit::Normal, m_ircClient->nickInUse (), &ok); + QLineEdit::Normal, m_ircClientImpl->nickname (), &ok); if (ok) { - m_ircClient->sendNickChange (newNick); + m_ircClientImpl->sendNicknameChangeRequest (newNick); } } void -IRCWidget::showJoin (const char *nick, const char *channel) -{ - m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick). - arg (channel)); - m_nickList.append (QString (nick)); - updateNickCompleter (); -} - -void -IRCWidget::showQuit (const char *nick, const char *reason) -{ - m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick). - arg (reason)); - m_nickList.removeAll (QString (nick)); - updateNickCompleter (); -} - -void IRCWidget::sendMessage (QString message) { // Do not send empty messages. @@ -256,11 +202,11 @@ message.split (QRegExp ("\\s+"), QString::SkipEmptyParts); if (line.at (0) == "/join") { - m_ircClient->joinChannel (line.at (1)); + m_ircClientImpl->sendJoinRequest (line.at (1)); } else if (line.at (0) == "/nick") { - m_ircClient->sendNickChange (line.at (1)); + m_ircClientImpl->sendNicknameChangeRequest (line.at (1)); } else if (line.at (0) == "/msg") { @@ -272,18 +218,16 @@ pmsg += line.at (i); pmsg += " "; } - m_ircClient->sendCommand (2, COMMAND_PRIVMSG, - recipient.toStdString ().c_str (), - pmsg.toStdString ().c_str ()); + m_ircClientImpl->sendPrivateMessage(recipient, pmsg); } } else { - m_ircClient->sendPublicMessage (message); + m_ircClientImpl->sendPublicMessage (message); message.replace ("<", "<"); message.replace (">", ">"); m_chatWindow->append (QString ("<b>%1:</b> %2"). - arg (m_ircClient->nickInUse ()).arg (message)); + arg (m_ircClientImpl->nickname ()).arg (message)); } } @@ -295,51 +239,55 @@ } void -IRCWidget::handleNickInUseChanged () +IRCWidget::handleLoggedIn (const QString &nick) { - m_nickButton->setText (m_ircClient->nickInUse ()); - QSettings *settings = ResourceManager::instance ()->settings (); - settings->setValue ("IRCNick", m_ircClient->nickInUse ()); + m_chatWindow-> + append (QString + ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). + arg (nick)); + m_nickButton->setEnabled (true); + m_inputLine->setEnabled (true); + m_chatWindow->setEnabled (true); + m_inputLine->setFocus (); + + + if (m_autoIdentification) + { + m_ircClientImpl->sendPrivateMessage("NickServ", QString ("identify %1"). + arg (m_nickServPassword)); + } } void -IRCWidget::handleReplyCode (IRCEvent * event) +IRCWidget::handleNickChange (const QString &oldNick, const QString &newNick) { - QSettings *settings = ResourceManager::instance ()->settings (); + m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick).arg (newNick)); + m_nickList.removeAll (QString (oldNick)); + m_nickList.append (QString (newNick)); + updateNickCompleter (); - switch (event->getNumeric ()) - { - case RPL_MOTDSTART: - case RPL_MOTD: - case ERR_NOMOTD: - case RPL_ENDOFMOTD: - if (settings->value ("showMessageOfTheDay").toBool ()) - m_chatWindow->append (QString ("<font color=\"#777777\">%1</font>"). - arg (event->getParam (1))); - break; - case RPL_NOTOPIC: - case RPL_TOPIC: - if (settings->value ("showTopic").toBool ()) - m_chatWindow-> - append (QString ("<font color=\"#000088\"><b>%1</b></font>"). - arg (event->getParam (2))); - break; - case RPL_NAMREPLY: - m_chatWindow-> - append (QString ("<font color=\"#000088\">Users online: %1</font>"). - arg (event->getParam (3))); - m_nickList = - event->getParam (3).split (QRegExp ("\\s+"), QString::SkipEmptyParts); - updateNickCompleter (); - break; - case ERR_NICKNAMEINUSE: - case ERR_NICKCOLLISION: - m_chatWindow-> - append (QString ("<font color=\"#AA0000\">Nickname in use.</font>")); - break; - }; + //m_nickButton->setText (m_ircClient->nickInUse ()); + //QSettings *settings = ResourceManager::instance ()->settings (); + //settings->setValue ("IRCNick", m_ircClient->nickInUse ()); } +void +IRCWidget::handleUserJoined (const QString &nick, const QString &channel) +{ + m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick). + arg (channel)); + m_nickList.append (QString (nick)); + updateNickCompleter (); +} + +void +IRCWidget::handleUserQuit (const QString &nick, const QString &reason) +{ + m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick). + arg (reason)); + m_nickList.removeAll (QString (nick)); + updateNickCompleter (); +} void IRCWidget::updateNickCompleter ()
--- a/gui/src/IRCWidget.h +++ b/gui/src/IRCWidget.h @@ -24,7 +24,7 @@ #include <QPushButton> #include <QLineEdit> #include <QCompleter> -#include "IRCClient.h" +#include "IRCClientImpl.h" class IRCWidget:public QWidget { @@ -32,37 +32,30 @@ explicit IRCWidget (QWidget * parent); void connectToServer (); - signals:public slots:void showStatusMessage (const char *); - void joinOctaveChannel (const char *); - void loginSuccessful (const char *); - void showPrivateMessage (const char *, const char *, const char *); - void showNotice (const char *, const char *, const char *); - void showTopic (const char *, const char *, const char *); - void showJoin (const char *, const char *); - void showQuit (const char *, const char *); - void showNickChange (const char *, const char *); +public slots: + void showStatusMessage (const QString&); + void showErrorMessage (const QString&); + void showMessage (const QString& channel, const QString& sender, const QString& message); + void showNotification (const QString& sender, const QString& message); + + void handleConnected (const QString& host); + void joinOctaveChannel (const QString& nick); + + void handleLoggedIn (const QString& nick); + void handleNickChange (const QString& oldNick, const QString& newNick); + void handleUserJoined (const QString& nick, const QString& channel); + void handleUserQuit (const QString& nick, const QString& reason); + void nickPopup (); void sendMessage (QString); void sendInputLine (); - - void handleNickInUseChanged (); - void handleReplyCode (IRCEvent * event); + void updateNickCompleter (); - void updateNickCompleter (); private: - IRCClient * m_ircClient; + IRCClientImpl * m_ircClientImpl; QTextEdit *m_chatWindow; QPushButton *m_nickButton; QLineEdit *m_inputLine; - bool m_alternatingColor; - - QString getAlternatingColor () - { - m_alternatingColor = !m_alternatingColor; - if (m_alternatingColor) - return "#000077"; - return "#005533"; - } QString m_initialNick; bool m_autoIdentification;
--- a/gui/src/MainWindow.cpp +++ b/gui/src/MainWindow.cpp @@ -28,7 +28,7 @@ #include "SettingsDialog.h" #include "cmd-edit.h" -#define VERSION_STRING "Octave GUI (0.7.3)" +#define VERSION_STRING "Octave GUI (0.7.4)" MainWindow::MainWindow (QWidget * parent):QMainWindow (parent) {
deleted file mode 100644 --- a/gui/src/qirc/IClientSocket.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/*************************************************************************** - IClientSocket.cpp - description - ------------------- - begin : Fri Sep 15 2000 - copyright : (C) 2000 by gerardo Puga - email : gere@mailroom.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. * - * * - ***************************************************************************/ - - -#include <IClientSocket.h> - -#define ERROR_ICLIENTSOCKET_NOERROR 0 -#define ERROR_ICLIENTSOCKET_NOSOCKET 1 -#define ERROR_ICLIENTSOCKET_NOCONNECT 2 -#define ERROR_ICLIENTSOCKET_NORESOLV 3 -#define ERROR_ICLIENTSOCKET_NOREAD 4 -#define ERROR_ICLIENTSOCKET_NOWRITE 5 -#define ERROR_ICLIENTSOCKET_NOFCNTL 6 - -const char *ICLIENTSOCKET_MENSAJES[] = { "Nothing has happened, boss", - "Can't create the socket to initiate the connection", - "Can't connect to the destination", - "Can't resolv the server name", - "Problems during read operation", - "Problems during write operation", - "Can't make the socket non-blocking" -}; - -#define ICLIENT_MAX_MENSAJE_ERROR 300 - -char ICLIENTSOCKETmensajeError[ICLIENT_MAX_MENSAJE_ERROR + 1]; - -void -IClientSocket::inicializar () -{ - handler = 0; - puerto = 0; - bzero ((void *) &ip, sizeof (in_addr)); - - conectado = false; - socketCreado = false; - blocking = true; - lastError = ERROR_ICLIENTSOCKET_NOERROR; -} - -IClientSocket::IClientSocket () -{ - inicializar (); -} - - -IClientSocket::~IClientSocket () -{ - if (conectado == true) - { - close (); - } -} - -int -IClientSocket::getSocket () -{ - return handler; -} - -const char * -IClientSocket::strError () -{ - switch (lastError) - { - case ERROR_ICLIENTSOCKET_NORESOLV: - snprintf (ICLIENTSOCKETmensajeError, ICLIENT_MAX_MENSAJE_ERROR, "%s", - ICLIENTSOCKET_MENSAJES[lastError]); - break; - default: - snprintf (ICLIENTSOCKETmensajeError, ICLIENT_MAX_MENSAJE_ERROR, - "%s - %s", - ICLIENTSOCKET_MENSAJES[lastError],:: - strerror (lastErrnoValue)); - break; - } - return ICLIENTSOCKETmensajeError; -} - -int -IClientSocket::connect () -{ - if (conectado == true) - { - close (); - } - - if ((handler = socket (AF_INET, SOCK_STREAM, 0)) < 0) - { - lastError = ERROR_ICLIENTSOCKET_NOSOCKET; - lastErrnoValue = errno; - return -1; - } - socketCreado = true; - - if (blocking == false) - { - if (fcntl (handler, F_SETFL, O_NONBLOCK) < 0) - { - lastError = ERROR_ICLIENTSOCKET_NOFCNTL; - lastErrnoValue = errno; - } - } - - sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons (puerto); - addr.sin_addr = ip; - bzero (&(addr.sin_zero), 8); - int respuesta =::connect (handler, (sockaddr *) & addr, - sizeof (sockaddr_in)); - - if ((respuesta == 0) - || ((respuesta < 0) && (errno == EINPROGRESS) && (blocking == false))) - { - conectado = true; - } - else - { - lastError = ERROR_ICLIENTSOCKET_NOCONNECT; - lastErrnoValue = errno; - return -1; - } - - return 0; -} - - -int -IClientSocket::connect (int socket, bool block) -{ - if (socketCreado) - { - close (); - } - - handler = socket; - bzero ((void *) &ip, sizeof (in_addr)); - - conectado = true; - socketCreado = true; - blocking = block; - lastError = 0; - - if (block == false) - { - fcntl (handler, F_SETFL, O_NONBLOCK); - } - - return 0; -} - -int -IClientSocket::connect (in_addr addr, unsigned int p, bool block) -{ - if (socketCreado == true) - { - close (); - } - - ip = addr; - puerto = p; - blocking = block; - - return connect (); -} - -int -IClientSocket::connect (const char *server, unsigned int p, bool block) -{ - if (socketCreado == true) - { - close (); - } - - puerto = p; - blocking = block; - - if (resolv (server, &ip) < 0) - { - lastError = ERROR_ICLIENTSOCKET_NORESOLV; - return -1; - } - return connect (); -} - -long int -IClientSocket::read (char *data, long count) -{ - long done = 0; - long res = 0; - - do - { - res = recv (handler, data + done, count - done, 0); - - if (res > 0) - { - done += res; - } - } - while ((((done < count) && (res > 0)) && (blocking == true)) - || ((res < 0) && (errno == EINTR))); - - if (res < 0) - { - if (errno == EWOULDBLOCK) - { - return 0; - } - else - { - lastError = ERROR_ICLIENTSOCKET_NOREAD; - lastErrnoValue = errno; - return -1; - } - } - else - { - return done; - } -} - -long -IClientSocket::write (const char *data, long count) -{ - long sent = 0; - long response = 0; - - do - { - response = send (handler, data + sent, count - sent, 0); - - if (response > 0) - { - sent += response; - } - } - while (((sent < count) && (response >= 0)) - || ((response < 0) && (errno == EWOULDBLOCK))); - - if (response < 0) - { - lastError = ERROR_ICLIENTSOCKET_NOWRITE; - lastErrnoValue = errno; - return -1; - } - return sent; -} - -void -IClientSocket::close () -{ - if (socketCreado == true) - { - ::close (handler); - conectado = false; - socketCreado = false; - blocking = true; - } -} - -int -IClientSocket::resolv (const char *fqdn, in_addr * ip) -{ - hostent *host; - host = gethostbyname (fqdn); - if (host == NULL) - { - return -1; - } - - bcopy ((void *) host->h_addr, (void *) ip, sizeof (in_addr)); - return 0; -}
deleted file mode 100644 --- a/gui/src/qirc/IClientSocket.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - IClientSocket.h - description - ------------------- - begin : Fri Sep 15 2000 - copyright : (C) 2000 by gerardo Puga - email : gere@mailroom.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. * - * * - ***************************************************************************/ - -#ifndef ICLIENTSOCKET_H -#define ICLIENTSOCKET_H - -#include <netinet/in.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdio.h> - -class IClientSocket -{ -private: - int handler; - in_addr ip; - unsigned int puerto; - - int lastError, lastErrnoValue; - - bool conectado; - bool socketCreado; - bool blocking; - - void inicializar (); - int connect (); - -public: - IClientSocket (); - ~IClientSocket (); - - int getSocket (); - const char *strError (); - - int connect (int socket, bool block = true); - int connect (in_addr addr, unsigned int puerto, bool blocking = true); - int connect (const char *server, unsigned int puerto, bool blocking = true); - - long int read (char *, long count); - long int write (const char *, long count); - - void close (); - - int resolv (const char *fqdn, in_addr * ip); -}; - -#endif
--- a/gui/src/qirc/IRCClientImpl.cpp +++ b/gui/src/qirc/IRCClientImpl.cpp @@ -1,5 +1,145 @@ #include "IRCClientImpl.h" +IRCEvent::IRCEvent (const char *serverMessage) +{ + char prefix[MAX_LINE_LEN]; + int index = 0; + + nick = ""; + user = ""; + host = ""; + for (int i = 0; i < 15; i++) + { + param[i] = ""; + } + + if (serverMessage[0] == CHR_COLON) + { + index++; + strcpy (prefix, + getStringToken (serverMessage, index).toStdString ().c_str ()); + + int etapa = 0; + for (unsigned int i = 0; i < strlen (prefix); i++) + { + switch (prefix[i]) + { + case '!': + etapa = 1; + break; + case '@': + etapa = 2; + break; + default: + switch (etapa) + { + case 0: + nick += prefix[i]; + break; + case 1: + user += prefix[i]; + break; + default: + host += prefix[i]; + break; + } + } + } + } + + command = getStringToken (serverMessage, index); + command = command.toUpper (); + + paramCount = 0; + while (serverMessage[index] != 0) + { + if ((serverMessage[index] == CHR_COLON) || (paramCount == 14)) + { + + if (serverMessage[index] == CHR_COLON) + { + index++; + } + + param[paramCount] = (const char *) (serverMessage + index); + index += strlen (serverMessage + index); + } + else + { + param[paramCount] = getStringToken (serverMessage, index); + } + paramCount++; + } + + if (strlen (command.toStdString ().c_str ()) == + strspn (command.toStdString ().c_str (), DIGITS)) + { + numeric = true; + codeNumber = atoi (command.toStdString ().c_str ()); + } + else + { + numeric = false; + } +} + +int +IRCEvent::getNumeric () +{ + if (!numeric) + { + return -1; + } + else + { + return codeNumber; + } +} + +QString +IRCEvent::getParam (int index) +{ + if ((index < 0) || (index > 14)) + { + return QString (); + } + else + { + return param[index]; + } +} + +int +IRCEvent::skipSpaces (const char *line, int &index) +{ + while (line[index] == CHR_SPACE) + { + index++; + } + return index; +} + +QString +IRCEvent::getStringToken (const char *line, int &index) +{ + QString token (""); + skipSpaces (line, index); + while ((line[index] != CHR_SPACE) && (line[index] != CHR_ZERO)) + { + token += line[index]; + index++; + } + + skipSpaces (line, index); + return token; +} + +QString +IRCEvent::getStringToken (QString line, int &index) +{ + return getStringToken (line.toStdString ().c_str (), index); +} + IRCClientImpl::IRCClientImpl () : IRCClientInterface () { @@ -9,9 +149,11 @@ } void -IRCClientImpl::connectToServer (const QHostAddress& server, int port) +IRCClientImpl::connectToHost (const QHostAddress& host, int port, const QString& initialNick) { - m_tcpSocket.connectToHost(server, port); + m_host = host; + m_nickname = initialNick; + m_tcpSocket.connectToHost(host, port); } void @@ -45,9 +187,10 @@ } void -IRCClientImpl::enterChannel (const QString& channel) +IRCClientImpl::sendJoinRequest (const QString& channel) { - Q_UNUSED (channel); + sendCommand (1, COMMAND_JOIN, channel.toStdString ().c_str ()); + focusChannel (channel); } void @@ -60,19 +203,28 @@ void IRCClientImpl::focusChannel (const QString& channel) { - Q_UNUSED (channel); + m_focussedChannel = channel; } void IRCClientImpl::sendNicknameChangeRequest (const QString &nickname) { - Q_UNUSED (nickname); + sendCommand (1, COMMAND_NICK, nickname.toStdString ().c_str ()); } void -IRCClientImpl::sendMessage (const QString& message) +IRCClientImpl::sendPublicMessage (const QString& message) { - Q_UNUSED (message); + sendCommand (2, COMMAND_PRIVMSG, m_focussedChannel.toStdString ().c_str (), + message.toStdString ().c_str ()); +} + +void +IRCClientImpl::sendPrivateMessage (const QString &recipient, const QString &message) +{ + sendCommand (2, COMMAND_PRIVMSG, + recipient.toStdString ().c_str (), + message.toStdString ().c_str ()); } const QString& @@ -85,12 +237,16 @@ IRCClientImpl::handleConnected () { m_connected = true; + sendCommand (4, COMMAND_USER, "na", "0", "0", "na"); + sendNicknameChangeRequest (m_nickname); + emit connected (m_host.toString ()); } void IRCClientImpl::handleDisconnected () { m_connected = false; + emit disconnected (); } void @@ -111,6 +267,157 @@ void IRCClientImpl::handleIncomingLine (const QString &line) { - if (line.isEmpty()) - return; + if (m_connected && !line.isEmpty()) + { + IRCEvent ircEvent(line.toStdString().c_str()); + if (ircEvent.isNumeric () == true) + { + switch (ircEvent.getNumeric ()) + { + case RPL_WELCOME: + emit loggedIn (nickname ()); + break; + case ERR_NICKNAMEINUSE: + case ERR_NICKCOLLISION: + emit debugMessage ("FIXME: Received nickname in use reply."); + break; + case ERR_PASSWDMISMATCH: + emit debugMessage ("FIXME: Received password mismatch reply."); + break; + case RPL_MOTDSTART: + case RPL_MOTD: + case ERR_NOMOTD: + case RPL_ENDOFMOTD: + break; + case RPL_NOTOPIC: + case RPL_TOPIC: + break; + case RPL_NAMREPLY: + /* + m_nickList = + event->getParam (3).split (QRegExp ("\\s+"), QString::SkipEmptyParts); + updateNickCompleter ();*/ + break; + } + } + else + { + QString command = ircEvent.getCommand (); + if (command == COMMAND_NICK) + { + emit nicknameChanged (ircEvent.getParam(0), ircEvent.getParam(1)); + } + else if (command == COMMAND_QUIT) + { + emit userQuit (ircEvent.getNick (), ircEvent.getParam (0)); + } + else if (command == COMMAND_JOIN) + { + emit userJoined (ircEvent.getNick (), ircEvent.getParam (0)); + } + else if (command == COMMAND_PART) + { + emit debugMessage ("WRITEME: Received part."); + //emit part (ircEvent.getNick ().toStdString ().c_str (), + // ircEvent.getParam (0).toStdString ().c_str (), + // ircEvent.getParam (1).toStdString ().c_str ()); + } + else if (command == COMMAND_MODE) + { + emit debugMessage ("WRITEME: Received mode."); + //emit mode (&ircEvent); + } + else if (command == COMMAND_TOPIC) + { + emit debugMessage ("WRITEME: Received topic."); + //emit topic (ircEvent.getNick ().toStdString ().c_str (), + // ircEvent.getParam (0).toStdString ().c_str (), + // ircEvent.getParam (1).toStdString ().c_str ()); + } + else if (command == COMMAND_KICK) + { + emit debugMessage ("WRITEME: Received kick."); + //emit kick (ircEvent.getNick ().toStdString ().c_str (), + // ircEvent.getParam (0).toStdString ().c_str (), + // ircEvent.getParam (1).toStdString ().c_str (), + // ircEvent.getParam (2).toStdString ().c_str ()); + } + else if (command == COMMAND_INVITE) + { + emit debugMessage ("WRITEME: Received invite."); + //emit invite (ircEvent.getNick ().toStdString ().c_str (), + // ircEvent.getParam (1).toStdString ().c_str ()); + } + else if (command == COMMAND_PRIVMSG) + { + emit message (ircEvent.getParam (0), ircEvent.getNick (), ircEvent.getParam (1)); + } + else if (command == COMMAND_NOTICE) + { + emit notification (ircEvent.getNick ().toStdString ().c_str (), + ircEvent.getParam (1).toStdString ().c_str ()); + } + else if (command == COMMAND_PING) + { + sendCommand (1, COMMAND_PONG, m_nickname.toStdString ().c_str ()); + } + else if (command == COMMAND_ERROR) + { + emit error (ircEvent.getParam (0)); + } + else + { + emit debugMessage (QString("FIXME: Received unknown reply: %1").arg(command)); + // not recognized. + } + } + } } + +void +IRCClientImpl::sendLine (const QString &line) +{ + if (m_connected) + m_tcpSocket.write ((line + "\r\n").toStdString ().c_str ()); +} + +void +IRCClientImpl::sendCommand (int numberOfCommands, const char *command, ...) +{ + char linea[513]; + char *parametro; + va_list lp; + + strncpy (linea, command, 512); + linea[512] = 0; + va_start (lp, command); + for (int i = 0; i < numberOfCommands; i++) + { + if (i == 15) + break; + parametro = va_arg (lp, char *); + if (i == numberOfCommands - 1) + { + if (strlen (linea) + strlen (parametro) + 2 > 512) + break; + if (strchr (parametro, ' ') != NULL) + { + strcat (linea, " :"); + } + else + { + strcat (linea, " "); + } + strcat (linea, parametro); + } + else + { + if (strlen (linea) + strlen (parametro) + 1 > 512) + break; + strcat (linea, " "); + strcat (linea, parametro); + } + } + va_end (lp); + sendLine (linea); +}
--- a/gui/src/qirc/IRCClientImpl.h +++ b/gui/src/qirc/IRCClientImpl.h @@ -2,8 +2,70 @@ #define IRCCLIENTIMPL_H #include <QTcpSocket> +#include <QHostInfo> #include "IRCClientInterface.h" +#define MAX_LINE_LEN 512 +#define PARAM_MAX_COUNT 15 +#define CHR_COLON ':' +#define CHR_SPACE ' ' +#define CHR_ZERO '\0' +#ifdef Q_OS_LINUX +#define CRLF "\n" +#else +#define CRLF "\r\n" +#endif +#define DIGITS "0123456789" + +class IRCEvent +{ +private: + int codeNumber; + bool numeric; + + QString nick, user, host; + QString command; + int paramCount; + QString param[PARAM_MAX_COUNT]; + +protected: + int skipSpaces (const char *linea, int &index); + QString getStringToken (const char *linea, int &index); + QString getStringToken (QString linea, int &index); + +public: + IRCEvent (const char *serverMessage); + + bool isNumeric () + { + return numeric; + } + + QString getNick () + { + return nick; + } + QString getUser () + { + return user; + } + QString getHost () + { + return host; + } + QString getCommand () + { + return command; + } + int getNumeric (); + + int getParamCount () + { + return paramCount; + } + QString getParam (int index); +}; + class IRCClientImpl : public IRCClientInterface { Q_OBJECT @@ -11,7 +73,7 @@ IRCClientImpl(); public slots: - void connectToServer (const QHostAddress& host, int port); + void connectToHost (const QHostAddress& host, int port, const QString& initialNick); void disconnect (); void reconnect (); @@ -19,15 +81,19 @@ const QHostAddress& host(); int port(); - void enterChannel (const QString& channel); + void sendJoinRequest (const QString& channel); void leaveChannel (const QString& channel, const QString& reason); void focusChannel (const QString& channel); void sendNicknameChangeRequest (const QString &nickname); - void sendMessage (const QString& message); + void sendPublicMessage (const QString& message); + void sendPrivateMessage (const QString &recipient, const QString &message); const QString& nickname (); +signals: + void debugMessage (const QString& message); + private slots: void handleConnected (); void handleDisconnected (); @@ -35,11 +101,14 @@ private: void handleIncomingLine (const QString& line); + void sendLine (const QString& line); + void sendCommand (int numberOfCommands, const char *command, ...); QHostAddress m_host; int m_port; QString m_nickname; bool m_connected; + QString m_focussedChannel; QTcpSocket m_tcpSocket; };
--- a/gui/src/qirc/IRCClientInterface.h +++ b/gui/src/qirc/IRCClientInterface.h @@ -38,7 +38,7 @@ public slots: // Connection state: - virtual void connectToServer (const QHostAddress& host, int port) = 0; + virtual void connectToHost (const QHostAddress& host, int port, const QString& initialNick) = 0; virtual void disconnect () = 0; virtual void reconnect () = 0; @@ -46,21 +46,27 @@ virtual const QHostAddress& host() = 0; virtual int port() = 0; - virtual void enterChannel (const QString& channel) = 0; + virtual void sendJoinRequest (const QString& channel) = 0; virtual void leaveChannel (const QString& channel, const QString& reason) = 0; // Messaging: virtual void focusChannel (const QString& channel) = 0; virtual void sendNicknameChangeRequest (const QString& nickname) = 0; - virtual void sendMessage (const QString& message) = 0; - + virtual void sendPublicMessage (const QString& message) = 0; + virtual void sendPrivateMessage (const QString& recipient, const QString& message) = 0; virtual const QString& nickname () = 0; signals: void newMessage (const QString& channel, const QString& sender, const QString& message); void connected (const QString& server); void disconnected (); - + void error (const QString& message); + void notification (const QString& sender, const QString& message); + void message (const QString& channel, const QString& sender, const QString& message); + void nicknameChanged (const QString& oldNick, const QString& newNick); + void userJoined (const QString& nick, const QString& channel); + void userQuit (const QString& nick, const QString& reason); + void loggedIn (const QString& nick); }; #endif // IRCCLIENTINTERFACE_H