From 912092425248f7fc5155b4c7c46b7d00ec2676bc Mon Sep 17 00:00:00 2001
From: wazlaf <wazlaf>
Date: Fri, 20 Sep 2002 23:28:14 +0000
Subject: support for client commands (only /join implemented so far), crash bugfix, fixed 2 leaks, server browser now includes a channel list

---
diff --git a/noncore/net/opieirc/ircchannel.cpp b/noncore/net/opieirc/ircchannel.cpp
index 71ec03b..9814a26 100644
--- a/noncore/net/opieirc/ircchannel.cpp
+++ b/noncore/net/opieirc/ircchannel.cpp
@@ -6,6 +6,11 @@ IRCChannel::IRCChannel(QString channelname) {
     m_channelname = channelname;
 }
 
+IRCChannel::~IRCChannel() {
+    /* We want this to get deleted */
+    m_people.setAutoDelete(TRUE);
+}
+
 QString IRCChannel::channelname() {
     return m_channelname;
 }
diff --git a/noncore/net/opieirc/ircchannel.h b/noncore/net/opieirc/ircchannel.h
index c800b99..e78f182 100644
--- a/noncore/net/opieirc/ircchannel.h
+++ b/noncore/net/opieirc/ircchannel.h
@@ -47,6 +47,7 @@ class IRCChannel : public QObject {
     Q_OBJECT
 public:
     IRCChannel(QString channelname);
+    ~IRCChannel();
    
     void addPerson(IRCChannelPerson *person);
     void removePerson(IRCChannelPerson *person);
diff --git a/noncore/net/opieirc/ircchanneltab.cpp b/noncore/net/opieirc/ircchanneltab.cpp
index c96a365..754442a 100644
--- a/noncore/net/opieirc/ircchanneltab.cpp
+++ b/noncore/net/opieirc/ircchanneltab.cpp
@@ -38,11 +38,23 @@ IRCChannelTab::~IRCChannelTab() {
 }
 
 void IRCChannelTab::processCommand() {
-    if (m_field->text().length()>0) {
-        session()->sendMessage(m_channel, m_field->text());
-        appendText("&lt;<font color=\"#dd0000\">"+m_parentTab->server()->nick()+"</font>&gt; "+m_field->text()+"<br>");
-        m_field->clear();
+    QString text = m_field->text();
+    if (text.length()>0) {
+        if (session()->isSessionActive()) {
+            if (text.startsWith("/") && !text.startsWith("//")) {
+                /* Command mode */
+                m_parentTab->executeCommand(this, text);;
+            } else {
+                if (session()->isSessionActive()) {
+                    session()->sendMessage(m_channel, m_field->text());
+                    appendText("&lt;<font color=\"#dd0000\">"+m_parentTab->server()->nick()+"</font>&gt; "+m_field->text()+"<br>");
+                }
+            }
+        } else {
+            appendText("<font color=\"#ff0000\">"+tr("Disconnected")+"</font><br>");
+        }
     }
+    m_field->clear();
 }
 
 void IRCChannelTab::toggleList() {
@@ -65,7 +77,11 @@ IRCSession *IRCChannelTab::session() {
 }
 
 void IRCChannelTab::remove() {
-    session()->part(m_channel);
+    if (session()->isSessionActive()) {
+        session()->part(m_channel);
+    } else {
+        m_mainWindow->killTab(this);
+    }
 }
 
 IRCChannel *IRCChannelTab::channel() {
diff --git a/noncore/net/opieirc/ircconnection.cpp b/noncore/net/opieirc/ircconnection.cpp
index 02c4897..5eb0cf2 100644
--- a/noncore/net/opieirc/ircconnection.cpp
+++ b/noncore/net/opieirc/ircconnection.cpp
@@ -60,6 +60,14 @@ void IRCConnection::dataReady() {
     while(m_socket->canReadLine()) {
         IRCMessage message(m_socket->readLine());
         if (!m_loggedIn && message.isNumerical() && message.commandNumber() == 1) {
+            /* Now autojoin all channels specified inside the server profile */
+            QStringList channels = QStringList::split(QChar(','), m_server->channels());
+            for (QStringList::Iterator it = channels.begin(); it != channels.end(); ++it) {
+                QString channelName = (*it).stripWhiteSpace();
+                if (channelName.startsWith("#")) {
+                    sendLine("JOIN "+ channelName); 
+                }
+            }
             m_loggedIn = TRUE;
             emit outputReady(IRCOutput(OUTPUT_CLIENTMESSAGE, tr("Successfully logged in.")));
         }
diff --git a/noncore/net/opieirc/ircmessage.cpp b/noncore/net/opieirc/ircmessage.cpp
index 74e9c6f..9c2869c 100644
--- a/noncore/net/opieirc/ircmessage.cpp
+++ b/noncore/net/opieirc/ircmessage.cpp
@@ -24,6 +24,7 @@ IRCMessage::IRCMessage(QString line) {
         m_command = temp.upper();
         m_allParameters = line.right(line.length() - m_command.length() - 1);
     }
+    
     /* Create a list of all parameters */
     while(!(stream.atEnd())) {
         stream >> temp;
@@ -36,6 +37,8 @@ IRCMessage::IRCMessage(QString line) {
             m_parameters << temp;
         }
     }
+
+    
     m_commandNumber = m_command.toInt(&m_isNumerical);
     /* Is this a CTCP command */
     if ((m_command == "PRIVMSG" || m_command == "NOTICE") && m_trailing.length()>0 && m_trailing.left(1) == QChar(1)) {
diff --git a/noncore/net/opieirc/ircmessageparser.cpp b/noncore/net/opieirc/ircmessageparser.cpp
index a2be5a4..4038673 100644
--- a/noncore/net/opieirc/ircmessageparser.cpp
+++ b/noncore/net/opieirc/ircmessageparser.cpp
@@ -26,6 +26,7 @@ IRCCTCPMessageParserStruct IRCMessageParser::ctcpParserProcTable[] = {
     { "ACTION",  FUNC(parseCTCPAction) },
     { 0 , 0 }
 };
+
 /* Lookup table for numerical commands */
 IRCNumericalMessageParserStruct IRCMessageParser::numericalParserProcTable[] = { 
     { 1,   FUNC(parseNumerical001) },           // RPL_WELCOME
@@ -228,11 +229,13 @@ void IRCMessageParser::parseLiteralQuit(IRCMessage *message) {
         for (;it.current(); ++it) { 
             IRCChannelPerson *chanperson = it.current()->getPerson(mask.nick());
             it.current()->removePerson(chanperson);
+            delete chanperson;
         }
         m_session->removePerson(person);
         IRCOutput output(OUTPUT_QUIT, mask.nick() + tr(" has quit ") + "(" + message->param(0) + ")");
         output.addParam(person);
         emit outputReady(output);
+        delete person;
     } else {
          emit outputReady(IRCOutput(OUTPUT_ERROR, tr("Unknown person quit - desynchronized?")));
     }
diff --git a/noncore/net/opieirc/ircoutput.cpp b/noncore/net/opieirc/ircoutput.cpp
index aa57d86..878bc9b 100644
--- a/noncore/net/opieirc/ircoutput.cpp
+++ b/noncore/net/opieirc/ircoutput.cpp
@@ -13,6 +13,13 @@ QString IRCOutput::message() {
     return m_message;
 }
 
+QString IRCOutput::htmlMessage() {
+    QString htmlMessage =m_message.replace(QRegExp("&"), "&amp;");
+    htmlMessage = htmlMessage.replace(QRegExp(">"), "&gt;");
+    htmlMessage = htmlMessage.replace(QRegExp("<"), "&lt;");
+    return htmlMessage;
+}
+
 void IRCOutput::addParam(void *data) {
     m_parameters.append(data);
 }
diff --git a/noncore/net/opieirc/ircoutput.h b/noncore/net/opieirc/ircoutput.h
index 4b757ed..72361d4 100644
--- a/noncore/net/opieirc/ircoutput.h
+++ b/noncore/net/opieirc/ircoutput.h
@@ -60,6 +60,8 @@ public:
     
     IRCOutputType type();
     QString message();
+    /* Return the message with all HTML code escaped (for example &lt; instead of '<') */
+    QString htmlMessage();
     void *getParam(int index);
 protected:
     IRCOutputType      m_type;
diff --git a/noncore/net/opieirc/ircserver.cpp b/noncore/net/opieirc/ircserver.cpp
index e16e2b2..e27e41d 100644
--- a/noncore/net/opieirc/ircserver.cpp
+++ b/noncore/net/opieirc/ircserver.cpp
@@ -4,6 +4,8 @@ IRCServer::IRCServer() {
     m_port = 6667;
 }
 
+/* Setter implementations */
+
 void IRCServer::setHostname(QString hostname) {
     m_hostname = hostname;
 }
@@ -32,6 +34,12 @@ void IRCServer::setRealname(QString realname) {
     m_realname = realname;
 }
 
+void IRCServer::setChannels(QString channels) {
+    m_channels = channels;
+}
+
+/* Getter implementations */
+
 QString IRCServer::hostname() {
     return m_hostname;
 }
@@ -60,3 +68,7 @@ QString IRCServer::realname() {
     return m_realname;
 }
 
+QString IRCServer::channels() {
+    return m_channels;
+}
+
diff --git a/noncore/net/opieirc/ircserver.h b/noncore/net/opieirc/ircserver.h
index f56f231..0bc7d4c 100644
--- a/noncore/net/opieirc/ircserver.h
+++ b/noncore/net/opieirc/ircserver.h
@@ -28,8 +28,10 @@
 
 class IRCServer {
 public:
+    /* Initialize to the default values */
     IRCServer();
 
+    /* Setters */
     void setName(QString name);
     void setHostname(QString hostname);
     void setPort(int port);
@@ -37,7 +39,9 @@ public:
     void setPassword(QString password);
     void setNick(QString nick);
     void setRealname(QString realname);
+    void setChannels(QString channels);
 
+    /* Getters */
     QString hostname();
     QString name();
     unsigned short int port();
@@ -45,6 +49,7 @@ public:
     QString password();
     QString nick();
     QString realname();
+    QString channels();
 protected:
     QString             m_hostname;
     QString             m_name;
@@ -53,6 +58,7 @@ protected:
     QString             m_password;
     QString             m_nick;
     QString             m_realname;
+    QString             m_channels;
 };
 
 #endif /* __IRCSERVER_H */
diff --git a/noncore/net/opieirc/ircservereditor.cpp b/noncore/net/opieirc/ircservereditor.cpp
index 798081f..c3a444d 100644
--- a/noncore/net/opieirc/ircservereditor.cpp
+++ b/noncore/net/opieirc/ircservereditor.cpp
@@ -4,7 +4,7 @@
 #include "ircservereditor.h"
 
 IRCServerEditor::IRCServerEditor(IRCServer server, QWidget* parent, const char* name, bool modal = FALSE, WFlags f) : QDialog(parent, name, modal, f) {
-    QGridLayout *layout = new QGridLayout(this, 6, 2, 5, 5);
+    QGridLayout *layout = new QGridLayout(this, 7, 2, 5, 5);
     QLabel *label = new QLabel(tr("Profile name :"), this);
     m_name = new QLineEdit(server.name(), this);
     layout->addWidget(label, 0, 0);
@@ -29,6 +29,10 @@ IRCServerEditor::IRCServerEditor(IRCServer server, QWidget* parent, const char*
     m_password = new QLineEdit(server.password(), this);
     layout->addWidget(label, 5, 0);
     layout->addWidget(m_password, 5, 1);
+    label = new QLabel(tr("Channels :"), this);
+    m_channels = new QLineEdit(server.channels(), this);
+    layout->addWidget(label, 6, 0);
+    layout->addWidget(m_channels, 6, 1);
     showMaximized();
 }
 
@@ -44,8 +48,18 @@ void IRCServerEditor::accept() {
         QMessageBox::critical(this, tr("Error"), tr("Nickname required"));
     else if (m_realname->text().length()==0)
         QMessageBox::critical(this, tr("Error"), tr("Realname required"));
-    else
+    else {
+        /* Now verify whether the channel list has a valid format */
+        QStringList channels = QStringList::split(QChar(','), m_channels->text());
+        for (QStringList::Iterator it = channels.begin(); it != channels.end(); ++it) {
+            QString channelName = (*it).stripWhiteSpace();
+            if (!channelName.startsWith("#")) {
+                QMessageBox::critical(this, tr("Error"), tr("The channel list needs to contain a\ncomma separated list of channel\n names which start with '#'"));
+                return;
+            }
+        }
         QDialog::accept();
+    }
 }
 
 IRCServer IRCServerEditor::getServer() {
@@ -57,5 +71,6 @@ IRCServer IRCServerEditor::getServer() {
     server.setRealname(m_realname->text());
     server.setUsername(m_nickname->text());
     server.setPassword(m_password->text());
+    server.setChannels(m_channels->text());
     return server;
 }
diff --git a/noncore/net/opieirc/ircservereditor.h b/noncore/net/opieirc/ircservereditor.h
index 20c94f7..22311f7 100644
--- a/noncore/net/opieirc/ircservereditor.h
+++ b/noncore/net/opieirc/ircservereditor.h
@@ -39,6 +39,7 @@ protected:
     QLineEdit *m_nickname;
     QLineEdit *m_password;
     QLineEdit *m_realname;
+    QLineEdit *m_channels;
 };
 
 #endif /* __IRCSERVEREDITOR_H */
diff --git a/noncore/net/opieirc/ircserverlist.cpp b/noncore/net/opieirc/ircserverlist.cpp
index b2d746a..e664ba1 100644
--- a/noncore/net/opieirc/ircserverlist.cpp
+++ b/noncore/net/opieirc/ircserverlist.cpp
@@ -59,6 +59,7 @@ IRCServerList::IRCServerList(QWidget* parent, const char *name, bool modal, WFla
                 server.setPassword(m_config->readEntry("Password"));
                 server.setNick(m_config->readEntry("Nick"));
                 server.setRealname(m_config->readEntry("Realname"));
+                server.setChannels(m_config->readEntry("Channels"));
                 m_list->insertItem(new IRCListBoxServer(server));
             }
         }
@@ -114,6 +115,7 @@ int IRCServerList::exec() {
         m_config->writeEntry("Password", server.password());
         m_config->writeEntry("Nick", server.nick());
         m_config->writeEntry("Realname", server.realname());
+        m_config->writeEntry("Channels", server.channels());
     }
     return returncode;
 }
diff --git a/noncore/net/opieirc/ircservertab.cpp b/noncore/net/opieirc/ircservertab.cpp
index 724f4bd..2ad56a8 100644
--- a/noncore/net/opieirc/ircservertab.cpp
+++ b/noncore/net/opieirc/ircservertab.cpp
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <qtextstream.h>
 #include "ircservertab.h"
 
 IRCServerTab::IRCServerTab(IRCServer server, MainWindow *mainWindow, QWidget *parent, const char *name, WFlags f) : IRCTab(parent, name, f) {
@@ -25,10 +26,6 @@ void IRCServerTab::appendText(QString text) {
 }
 
 IRCServerTab::~IRCServerTab() {
-    QListIterator<IRCChannelTab> it(m_channelTabs);
-    for (; it.current(); ++it) {
-        m_mainWindow->killTab(it.current());
-    }
     delete m_session;
 }
 
@@ -48,9 +45,32 @@ IRCServer *IRCServerTab::server() {
     return &m_server;
 }
 
+void IRCServerTab::executeCommand(IRCTab *tab, QString line) {
+    QTextIStream stream(&line);
+    QString command;
+    stream >> command;
+    command = command.upper().right(command.length()-1);
+    
+    if (command == "JOIN") {
+        QString channel;
+        stream >> channel;
+        if (channel.length() > 0 && channel.startsWith("#")) {
+            m_session->join(channel);
+        } else {
+            tab->appendText("<font color=\"#ff0000\">Unknown channel format!</font><br>"); 
+        }
+    } else {
+        tab->appendText("<font color=\"#ff0000\">Unknown command</font><br>"); 
+    }
+}
+
 void IRCServerTab::processCommand() {
+    QString text = m_field->text();
+    if (text.startsWith("/") && !text.startsWith("//")) {
+        /* Command mode */
+        executeCommand(this, text);
+    }
     m_field->clear();
-    appendText("<font color=\"#ff0000\">Not supported yet</font><br>"); 
 }
 
 void IRCServerTab::doConnect() {
@@ -58,10 +78,17 @@ void IRCServerTab::doConnect() {
 }
 
 void IRCServerTab::remove() {
+    /* Close requested */
     if (m_session->isSessionActive()) {
+        /* While there is a running session */
         m_close = TRUE;
         m_session->endSession();
     } else {
+        /* Session has previously been closed */
+        m_channelTabs.first();
+        while (m_channelTabs.current() != 0) {
+            m_mainWindow->killTab(m_channelTabs.current());
+        }
         m_mainWindow->killTab(this);
     }
 }
@@ -77,12 +104,23 @@ IRCChannelTab *IRCServerTab::getTabForChannel(IRCChannel *channel) {
 }
 
 void IRCServerTab::display(IRCOutput output) {
+
+    /* All messages to be displayed inside the GUI get here */
     switch (output.type()) {
         case OUTPUT_CONNCLOSE:
-            if (m_close)
+            if (m_close) {
+                m_channelTabs.first();
+                while (m_channelTabs.current() != 0) {
+                    m_mainWindow->killTab(m_channelTabs.current());
+                }
                 m_mainWindow->killTab(this);
-            else
-                appendText("<font color=\"#0000dd\">" + output.message() +"</font><br>");
+            } else {
+                appendText("<font color=\"#0000dd\">" + output.htmlMessage() +"</font><br>");
+                QListIterator<IRCChannelTab> it(m_channelTabs);
+                for (; it.current(); ++it) {
+                    it.current()->appendText("<font color=\"#0000dd\">" + output.htmlMessage() +"</font><br>");
+                }
+            }
             break;
         case OUTPUT_SELFJOIN: {
                 IRCChannelTab *channeltab = new IRCChannelTab((IRCChannel *)output.getParam(0), this, m_mainWindow, (QWidget *)parent());
@@ -92,7 +130,7 @@ void IRCServerTab::display(IRCOutput output) {
             break;
         case OUTPUT_CHANPRIVMSG: {
                 IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0));
-                channelTab->appendText("&lt;<font color=\"#0000dd\">"+((IRCChannelPerson *)output.getParam(1))->person->nick()+"</font>&gt; "+output.message()+"<br>");
+                channelTab->appendText("&lt;<font color=\"#0000dd\">"+((IRCChannelPerson *)output.getParam(1))->person->nick()+"</font>&gt; "+output.htmlMessage()+"<br>");
             }
             break;
         case OUTPUT_SELFPART: {
@@ -102,7 +140,7 @@ void IRCServerTab::display(IRCOutput output) {
             }
             break;
         case OUTPUT_SELFKICK: {
-                appendText("<font color=\"#ff0000\">" + output.message() + "</font><br>");
+                appendText("<font color=\"#ff0000\">" + output.htmlMessage() + "</font><br>");
                 IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0));
                 if (channelTab)
                     m_mainWindow->killTab(channelTab);
@@ -110,7 +148,7 @@ void IRCServerTab::display(IRCOutput output) {
             break;
         case OUTPUT_CHANACTION: {
                 IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0));
-                channelTab->appendText("<font color=\"#cc0000\">"+output.message()+"</font><br>");
+                channelTab->appendText("<font color=\"#cc0000\">"+output.htmlMessage()+"</font><br>");
             }
             break;
         case OUTPUT_QUIT: {
@@ -118,7 +156,7 @@ void IRCServerTab::display(IRCOutput output) {
                 QListIterator<IRCChannelTab> it(m_channelTabs);
                 for (; it.current(); ++it) {
                     if (it.current()->list()->hasPerson(nick)) {
-                        it.current()->appendText("<font color=\"#aa3e00\">"+output.message()+"</font><br>");
+                        it.current()->appendText("<font color=\"#aa3e00\">"+output.htmlMessage()+"</font><br>");
                         it.current()->list()->update();
                     }
                 }
@@ -129,18 +167,18 @@ void IRCServerTab::display(IRCOutput output) {
         case OUTPUT_CHANPERSONMODE:
         case OUTPUT_OTHERPART: {
                 IRCChannelTab *channelTab = getTabForChannel((IRCChannel *)output.getParam(0));
-                channelTab->appendText("<font color=\"#aa3e00\">"+output.message()+"</font><br>");
+                channelTab->appendText("<font color=\"#aa3e00\">"+output.htmlMessage()+"</font><br>");
                 channelTab->list()->update();
             }
             break;
         case OUTPUT_CTCP:
-            appendText("<font color=\"#00bb00\">" + output.message() + "</font><br>");
+            appendText("<font color=\"#00bb00\">" + output.htmlMessage() + "</font><br>");
             break;
         case OUTPUT_ERROR:
-            appendText("<font color=\"#ff0000\">" + output.message() + "</font><br>");
+            appendText("<font color=\"#ff0000\">" + output.htmlMessage() + "</font><br>");
             break;
         default:
-            appendText("<font color=\"#0000dd\">" + output.message() + "</font><br>");
+            appendText("<font color=\"#0000dd\">" + output.htmlMessage() + "</font><br>");
             break;
     }
 }
diff --git a/noncore/net/opieirc/ircservertab.h b/noncore/net/opieirc/ircservertab.h
index fa9a0a3..cfa0832 100644
--- a/noncore/net/opieirc/ircservertab.h
+++ b/noncore/net/opieirc/ircservertab.h
@@ -39,6 +39,9 @@ public:
     /* Start the server session */
     void doConnect();
     void removeChannelTab(IRCChannelTab *tab);
+
+    /* Execute a user command such as /join */
+    void executeCommand(IRCTab *tab, QString line);
 protected:
     void appendText(QString text);
     IRCChannelTab *getTabForChannel(IRCChannel *channel);
diff --git a/noncore/net/opieirc/ircsession.cpp b/noncore/net/opieirc/ircsession.cpp
index b81038f..89df68c 100644
--- a/noncore/net/opieirc/ircsession.cpp
+++ b/noncore/net/opieirc/ircsession.cpp
@@ -12,6 +12,10 @@ IRCSession::IRCSession(IRCServer *server) {
 }
 
 IRCSession::~IRCSession() {
+    /* We want this to get deleted automatically */
+    m_channels.setAutoDelete(TRUE);
+    m_people.setAutoDelete(TRUE);
+        
     delete m_parser;
     delete m_connection;
 }
diff --git a/noncore/net/opieirc/irctab.h b/noncore/net/opieirc/irctab.h
index 3124980..0ce9777 100644
--- a/noncore/net/opieirc/irctab.h
+++ b/noncore/net/opieirc/irctab.h
@@ -37,6 +37,7 @@ public:
     IRCTab(QWidget *parent = 0, const char *name = 0, WFlags f = 0);
     virtual QString title() = 0;
     virtual IRCSession *session() = 0;
+    virtual void appendText(QString text) = 0;
 public slots:
     virtual void remove() = 0;
 protected:
diff --git a/noncore/net/opieirc/ircversion.h b/noncore/net/opieirc/ircversion.h
index 0ef0d2f..f8510e6 100644
--- a/noncore/net/opieirc/ircversion.h
+++ b/noncore/net/opieirc/ircversion.h
@@ -21,7 +21,7 @@
 #ifndef __IRCVERSION_H
 #define __IRCVERSION_H
 
-#define APP_VERSION "OpieIRC 0.1"
+#define APP_VERSION "OpieIRC 0.2"
 #define APP_COPYSTR "(c) 2002 by Wenzel Jakob"
 
 #endif /* __IRCVERSION_H */
--
cgit v0.9.0.2