X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fcoreuserinputhandler.cpp;h=ecab9e1052c8ccf329b1323bdb0a11bc210e5ae1;hp=ecff7ef835cf5464fe3377b3622064e7cb65738b;hb=6f0a153a674317d77233139fc50a2985af86e36e;hpb=651bcf1231e3641497437634f744407eade4950d diff --git a/src/core/coreuserinputhandler.cpp b/src/core/coreuserinputhandler.cpp index ecff7ef8..ecab9e10 100644 --- a/src/core/coreuserinputhandler.cpp +++ b/src/core/coreuserinputhandler.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-10 by the Quassel Project * + * Copyright (C) 2005-2010 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -22,12 +22,13 @@ #include "util.h" #include "ctcphandler.h" -#include "coreidentity.h" -#include "ircuser.h" -#include #include +#ifdef HAVE_QCA2 +# include "cipher.h" +#endif + CoreUserInputHandler::CoreUserInputHandler(CoreNetwork *parent) : CoreBasicHandler(parent) { @@ -51,16 +52,33 @@ void CoreUserInputHandler::handleUserInput(const BufferInfo &bufferInfo, const Q // ==================== void CoreUserInputHandler::handleAway(const BufferInfo &bufferInfo, const QString &msg) { Q_UNUSED(bufferInfo) + if(msg.startsWith("-all")) { + if(msg.length() == 4) { + coreSession()->globalAway(); + return; + } + Q_ASSERT(msg.length() > 4); + if(msg[4] == ' ') { + coreSession()->globalAway(msg.mid(5)); + return; + } + } + issueAway(msg); +} +void CoreUserInputHandler::issueAway(const QString &msg, bool autoCheck) { QString awayMsg = msg; IrcUser *me = network()->me(); // if there is no message supplied we have to check if we are already away or not - if(msg.isEmpty()) { + if(autoCheck && msg.isEmpty()) { if(me && !me->isAway()) { - awayMsg = network()->identityPtr()->awayReason(); + Identity *identity = network()->identityPtr(); + if(identity) { + awayMsg = identity->awayReason(); + } if(awayMsg.isEmpty()) { - awayMsg = tr("away"); + awayMsg = tr("away"); } } } @@ -140,6 +158,49 @@ void CoreUserInputHandler::handleCtcp(const BufferInfo &bufferInfo, const QStrin emit displayMsg(Message::Action, BufferInfo::StatusBuffer, "", verboseMessage, network()->myNick()); } +void CoreUserInputHandler::handleDelkey(const BufferInfo &bufferInfo, const QString &msg) { +#ifdef HAVE_QCA2 + if(!bufferInfo.isValid()) + return; + + QStringList parms = msg.split(' ', QString::SkipEmptyParts); + + if(parms.isEmpty() && !bufferInfo.bufferName().isEmpty()) + parms.prepend(bufferInfo.bufferName()); + + if(parms.isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), "", + tr("[usage] /delkey deletes the encryption key for nick or channel or just /delkey when in a channel or query.")); + return; + } + + QString target = parms.at(0); + + if(network()->cipherKey(target).isEmpty()) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("No key has been set for %1.").arg(target)); + return; + } + + network()->setCipherKey(target, QByteArray()); + + if(network()->isChannelName(target) && network()->channels().contains(target)) { + qobject_cast(network()->ircChannel(target))->setEncrypted(false); + } + else if(network()->nicks().contains(target)) { + qobject_cast(network()->ircUser(target))->setEncrypted(false); + } + + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been deleted.").arg(target)); + +#else + Q_UNUSED(msg) + emit displayMsg(Message::Error, bufferInfo.bufferName(), "", tr("Error: Setting an encryption key requires Quassel to have been built " + "with support for the Qt Cryptographic Architecture (QCA2) library. " + "Contact your distributor about a Quassel package with QCA2 " + "support, or rebuild Quassel with QCA2 present.")); +#endif +} + void CoreUserInputHandler::handleDeop(const BufferInfo &bufferInfo, const QString &msg) { QStringList nicks = msg.split(' ', QString::SkipEmptyParts); QString m = "-"; for(int i = 0; i < nicks.count(); i++) m += 'o'; @@ -257,8 +318,17 @@ void CoreUserInputHandler::handleMode(const BufferInfo &bufferInfo, const QStrin QStringList params = msg.split(' ', QString::SkipEmptyParts); // if the first argument is neither a channel nor us (user modes are only to oneself) the current buffer is assumed to be the target - if(!params.isEmpty() && !network()->isChannelName(params[0]) && !network()->isMyNick(params[0])) - params.prepend(bufferInfo.bufferName()); + if(!params.isEmpty()) { + if(!network()->isChannelName(params[0]) && !network()->isMyNick(params[0])) + params.prepend(bufferInfo.bufferName()); + if(network()->isMyNick(params[0]) && params.count() == 2) + network()->updateIssuedModes(params[1]); + if(params[0] == "-reset" && params.count() == 1) { + // FIXME: give feedback to the user (I don't want to add new strings right now) + network()->resetPersistentModes(); + return; + } + } // TODO handle correct encoding for buffer modes (channelEncode()) emit putCmd("MODE", serverEncode(params)); @@ -270,8 +340,14 @@ void CoreUserInputHandler::handleMsg(const BufferInfo &bufferInfo, const QString if(!msg.contains(' ')) return; - QByteArray target = serverEncode(msg.section(' ', 0, 0)); - putPrivmsg(target, userEncode(target, msg.section(' ', 1))); + QString target = msg.section(' ', 0, 0); + QByteArray encMsg = userEncode(target, msg.section(' ', 1)); + +#ifdef HAVE_QCA2 + encMsg = encrypt(target, encMsg); +#endif + + putPrivmsg(serverEncode(target), encMsg, false); } void CoreUserInputHandler::handleNick(const BufferInfo &bufferInfo, const QString &msg) { @@ -361,16 +437,67 @@ void CoreUserInputHandler::handleQuote(const BufferInfo &bufferInfo, const QStri void CoreUserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString &msg) { if(bufferInfo.bufferName().isEmpty()) return; // server buffer - putPrivmsg(serverEncode(bufferInfo.bufferName()), channelEncode(bufferInfo.bufferName(), msg)); + + QByteArray encMsg = channelEncode(bufferInfo.bufferName(), msg); +#ifdef HAVE_QCA2 + encMsg = encrypt(bufferInfo.bufferName(), encMsg); +#endif + + putPrivmsg(serverEncode(bufferInfo.bufferName()), encMsg, false); emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); } +void CoreUserInputHandler::handleSetkey(const BufferInfo &bufferInfo, const QString &msg) { +#ifdef HAVE_QCA2 + if(!bufferInfo.isValid()) + return; + + QStringList parms = msg.split(' ', QString::SkipEmptyParts); + + if(parms.count() == 1 && !bufferInfo.bufferName().isEmpty()) + parms.prepend(bufferInfo.bufferName()); + else if(parms.count() != 2) { + emit displayMsg(Message::Info, bufferInfo.bufferName(), + tr("[usage] /setkey sets the encryption key for nick or channel. " + "/setkey when in a channel or query buffer sets the key for it.")); + return; + } + + QString target = parms.at(0); + QByteArray key = parms.at(1).toLocal8Bit(); + + network()->setCipherKey(target, key); + + if(network()->isChannelName(target) && network()->channels().contains(target)) + qobject_cast(network()->ircChannel(target))->setEncrypted(true); + else if(network()->nicks().contains(target)) + qobject_cast(network()->ircUser(target))->setEncrypted(true); + + emit displayMsg(Message::Info, bufferInfo.bufferName(), tr("The key for %1 has been set.").arg(target)); +#else + Q_UNUSED(msg) + emit displayMsg(Message::Error, bufferInfo.bufferName(), tr("Error: Setting an encryption key requires Quassel to have been built " + "with support for the Qt Cryptographic Architecture (QCA) library. " + "Contact your distributor about a Quassel package with QCA " + "support, or rebuild Quassel with QCA present.")); +#endif +} + void CoreUserInputHandler::handleTopic(const BufferInfo &bufferInfo, const QString &msg) { - if(bufferInfo.bufferName().isEmpty()) return; + if(bufferInfo.bufferName().isEmpty()) + return; + QList params; params << serverEncode(bufferInfo.bufferName()); - if(!msg.isEmpty()) - params << channelEncode(bufferInfo.bufferName(), msg); + + if(!msg.isEmpty()) { +# ifdef HAVE_QCA2 + params << encrypt(bufferInfo.bufferName(), channelEncode(bufferInfo.bufferName(), msg)); +# else + params << channelEncode(bufferInfo.bufferName(), msg); +# endif + } + emit putCmd("TOPIC", params); } @@ -421,24 +548,28 @@ void CoreUserInputHandler::defaultHandler(QString cmd, const BufferInfo &bufferI emit putCmd(serverEncode(cmd.toUpper()), serverEncode(msg.split(" "))); } -void CoreUserInputHandler::putPrivmsg(const QByteArray &target, const QByteArray &message) { +// TODO: handle cutoff of encrypted messages +void CoreUserInputHandler::putPrivmsg(const QByteArray &target, const QByteArray &message, bool encrypted) { + + QByteArray temp = message; + static const char *cmd = "PRIVMSG"; - int overrun = lastParamOverrun(cmd, QList() << target << message); + int overrun = lastParamOverrun(cmd, QList() << target << temp); if(overrun) { static const char *splitter = " .,-"; - int maxSplitPos = message.count() - overrun; + int maxSplitPos = temp.count() - overrun; int splitPos = -1; for(const char *splitChar = splitter; *splitChar != 0; splitChar++) { - splitPos = qMax(splitPos, message.lastIndexOf(*splitChar, maxSplitPos)); + splitPos = qMax(splitPos, temp.lastIndexOf(*splitChar, maxSplitPos)); } if(splitPos <= 0) { splitPos = maxSplitPos; } - putCmd(cmd, QList() << target << message.left(splitPos)); - putPrivmsg(target, message.mid(splitPos)); + putCmd(cmd, QList() << target << temp.left(splitPos)); + putPrivmsg(target, temp.mid(splitPos), encrypted); return; } else { - putCmd(cmd, QList() << target << message); + putCmd(cmd, QList() << target << temp); } } @@ -471,6 +602,31 @@ int CoreUserInputHandler::lastParamOverrun(const QString &cmd, const QListcipherKey(target); + if(key.isEmpty()) + return message_; + + QByteArray message = message_; + + CoreIrcChannel *channel = qobject_cast(network()->ircChannel(target)); + if(channel) { + if(channel->cipher()->setKey(key)) + channel->cipher()->encrypt(message); + } else { + CoreIrcUser *user = qobject_cast(network()->ircUser(target)); + if(user && user->cipher()->setKey(key)) + user->cipher()->encrypt(message); + } + + return message; +} +#endif + void CoreUserInputHandler::timerEvent(QTimerEvent *event) { if(!_delayedCommands.contains(event->timerId())) { QObject::timerEvent(event);