Add handler for DCC-SEND
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 28 Dec 2013 19:35:51 +0000 (20:35 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 1 Jan 2014 22:15:15 +0000 (23:15 +0100)
This adds a basic handler for incoming DCC-SEND requests. Note that not
all features are supported yet, there are no settings and no way to disable
it. Also, the EventStringifier hasn't been adapted yet, so there will be
a warning about an unknown event in the status buffer...

src/core/coresessioneventprocessor.cpp
src/core/coresessioneventprocessor.h

index f8fd4d7..844155b 100644 (file)
 #include "coreirclisthelper.h"
 #include "corenetwork.h"
 #include "coresession.h"
 #include "coreirclisthelper.h"
 #include "corenetwork.h"
 #include "coresession.h"
+#include "coretransfermanager.h"
 #include "ctcpevent.h"
 #include "ircevent.h"
 #include "ircuser.h"
 #include "messageevent.h"
 #include "netsplit.h"
 #include "quassel.h"
 #include "ctcpevent.h"
 #include "ircevent.h"
 #include "ircuser.h"
 #include "messageevent.h"
 #include "netsplit.h"
 #include "quassel.h"
+#include "transfer.h"
 
 #ifdef HAVE_QCA2
 #  include "keyevent.h"
 
 #ifdef HAVE_QCA2
 #  include "keyevent.h"
@@ -1014,6 +1016,61 @@ void CoreSessionEventProcessor::handleCtcpClientinfo(CtcpEvent *e)
 }
 
 
 }
 
 
+// http://www.irchelp.org/irchelp/rfc/ctcpspec.html
+// http://en.wikipedia.org/wiki/Direct_Client-to-Client
+void CoreSessionEventProcessor::handleCtcpDcc(CtcpEvent *e)
+{
+    // normal:  SEND <filename> <ip> <port> [<filesize>]
+    // reverse: SEND <filename> <ip> 0 <filesize> <token>
+    QStringList params = e->param().split(' ');
+    if (params.count()) {
+        QString cmd = params[0].toUpper();
+        if (cmd == "SEND") {
+            if (params.count() < 4) {
+                qWarning() << "Invalid DCC SEND request:" << e;  // TODO emit proper error to client
+                return;
+            }
+            QString filename = params[1];
+            QHostAddress address;
+            quint16 port = params[3].toUShort();
+            quint64 size = 0;
+            QString numIp = params[2]; // this is either IPv4 as a 32 bit value, or IPv6 (which always contains a colon)
+            if (numIp.contains(':')) { // IPv6
+                if (!address.setAddress(numIp)) {
+                    qWarning() << "Invalid IPv6:" << numIp;
+                    return;
+                }
+            }
+            else {
+                address.setAddress(numIp.toUInt());
+            }
+
+            if (port == 0) { // Reverse DCC is indicated by a 0 port
+                emit newEvent(new MessageEvent(Message::Error, e->network(), tr("Reverse DCC SEND not supported"), e->prefix(), e->target(), Message::None, e->timestamp()));
+                return;
+            }
+            if (port < 1024) {
+                qWarning() << "Privileged port requested:" << port; // FIXME ask user if this is ok
+            }
+
+
+            if (params.count() > 4) { // filesize is optional
+                size = params[4].toULong();
+            }
+
+            // TODO: check if target is the right thing to use for the partner
+            Transfer *transfer = new Transfer(Transfer::Receive, e->target(), filename, address, port, size, this);
+            coreSession()->signalProxy()->synchronize(transfer);
+            coreSession()->transferManager()->addTransfer(transfer);
+        }
+        else {
+            emit newEvent(new MessageEvent(Message::Error, e->network(), tr("DCC %1 not supported").arg(cmd), e->prefix(), e->target(), Message::None, e->timestamp()));
+            return;
+        }
+    }
+}
+
+
 void CoreSessionEventProcessor::handleCtcpPing(CtcpEvent *e)
 {
     e->setReply(e->param().isNull() ? "" : e->param());
 void CoreSessionEventProcessor::handleCtcpPing(CtcpEvent *e)
 {
     e->setReply(e->param().isNull() ? "" : e->param());
index 6a163c6..b13f6e2 100644 (file)
@@ -97,6 +97,7 @@ public:
 
     Q_INVOKABLE void handleCtcpAction(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpClientinfo(CtcpEvent *event);
 
     Q_INVOKABLE void handleCtcpAction(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpClientinfo(CtcpEvent *event);
+    Q_INVOKABLE void handleCtcpDcc(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpPing(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpTime(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpPing(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpTime(CtcpEvent *event);
     Q_INVOKABLE void handleCtcpVersion(CtcpEvent *event);