/***************************************************************************
- * Copyright (C) 2005-08 by the Quassel Project *
+ * Copyright (C) 2005-09 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
***************************************************************************/
#include "ctcphandler.h"
-#include "global.h"
-#include "util.h"
#include "message.h"
#include "network.h"
+#include "quassel.h"
+#include "util.h"
-CtcpHandler::CtcpHandler(NetworkConnection *parent)
+CtcpHandler::CtcpHandler(CoreNetwork *parent)
: BasicHandler(parent),
XDELIM("\001")
{
QByteArray MQUOTE = QByteArray("\020");
- ctcpMDequoteHash[MQUOTE + '0'] = QByteArray("\000");
- ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray("\n");
- ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray("\r");
+ ctcpMDequoteHash[MQUOTE + '0'] = QByteArray(1, '\000');
+ ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray(1, '\n');
+ ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r');
ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
QByteArray XQUOTE = QByteArray("\134");
ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
}
-QByteArray CtcpHandler::dequote(const QByteArray &message) {
+QByteArray CtcpHandler::lowLevelQuote(const QByteArray &message) {
+ QByteArray quotedMessage = message;
+
+ QHash<QByteArray, QByteArray> quoteHash = ctcpMDequoteHash;
+ QByteArray MQUOTE = QByteArray("\020");
+ quoteHash.remove(MQUOTE + MQUOTE);
+ quotedMessage.replace(MQUOTE, MQUOTE + MQUOTE);
+
+ QHash<QByteArray, QByteArray>::const_iterator quoteIter = quoteHash.constBegin();
+ while(quoteIter != quoteHash.constEnd()) {
+ quotedMessage.replace(quoteIter.value(), quoteIter.key());
+ quoteIter++;
+ }
+ return quotedMessage;
+}
+
+QByteArray CtcpHandler::lowLevelDequote(const QByteArray &message) {
QByteArray dequotedMessage;
QByteArray messagepart;
QHash<QByteArray, QByteArray>::iterator ctcpquote;
-
+
// copy dequote Message
for(int i = 0; i < message.size(); i++) {
messagepart = message.mid(i,1);
return dequotedMessage;
}
+QByteArray CtcpHandler::xdelimQuote(const QByteArray &message) {
+ QByteArray quotedMessage = message;
+ QHash<QByteArray, QByteArray>::const_iterator quoteIter = ctcpXDelimDequoteHash.constBegin();
+ while(quoteIter != ctcpXDelimDequoteHash.constEnd()) {
+ quotedMessage.replace(quoteIter.value(), quoteIter.key());
+ quoteIter++;
+ }
+ return quotedMessage;
+}
QByteArray CtcpHandler::xdelimDequote(const QByteArray &message) {
QByteArray dequotedMessage;
void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const QString &target, const QByteArray &message) {
QByteArray ctcp;
-
+
//lowlevel message dequote
- QByteArray dequotedMessage = dequote(message);
+ QByteArray dequotedMessage = lowLevelDequote(message);
CtcpType ctcptype = messageType == Message::Notice
? CtcpReply
: CtcpQuery;
-
- quint8 flags = (messageType == Message::Notice && !network()->isChannelName(target))
+
+ Message::Flags flags = (messageType == Message::Notice && !network()->isChannelName(target))
? Message::Redirected
: Message::None;
xdelimEndPos = dequotedMessage.indexOf(XDELIM, xdelimPos + 1);
if(xdelimEndPos == -1) {
- // no matching end delimiter found...
- dequotedMessage = dequotedMessage.mid(xdelimPos + 1);
- break;
- } else {
- ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1));
- dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1);
+ // no matching end delimiter found... treat rest of the message as ctcp
+ xdelimEndPos = dequotedMessage.count();
}
+ ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1));
+ dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1);
//dispatch the ctcp command
QString ctcpcmd = userDecode(target, ctcp.left(spacePos));
handle(ctcpcmd, Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam));
}
-
+
if(!dequotedMessage.isEmpty())
displayMsg(messageType, target, userDecode(target, dequotedMessage), prefix, flags);
}
QByteArray CtcpHandler::pack(const QByteArray &ctcpTag, const QByteArray &message) {
- return XDELIM + ctcpTag + ' ' + message + XDELIM;
+ return XDELIM + ctcpTag + ' ' + xdelimQuote(message) + XDELIM;
}
-// TODO handle encodings correctly!
void CtcpHandler::query(const QString &bufname, const QString &ctcpTag, const QString &message) {
QList<QByteArray> params;
- params << serverEncode(bufname) << pack(serverEncode(ctcpTag), userEncode(bufname, message));
+ params << serverEncode(bufname) << lowLevelQuote(pack(serverEncode(ctcpTag), userEncode(bufname, message)));
emit putCmd("PRIVMSG", params);
}
void CtcpHandler::reply(const QString &bufname, const QString &ctcpTag, const QString &message) {
QList<QByteArray> params;
- params << serverEncode(bufname) << pack(serverEncode(ctcpTag), userEncode(bufname, message));
+ params << serverEncode(bufname) << lowLevelQuote(pack(serverEncode(ctcpTag), userEncode(bufname, message)));
emit putCmd("NOTICE", params);
}
void CtcpHandler::handleVersion(CtcpType ctcptype, const QString &prefix, const QString &target, const QString ¶m) {
Q_UNUSED(target)
if(ctcptype == CtcpQuery) {
- reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC (v%1 build >= %2) -- http://www.quassel-irc.org")
- .arg(Global::quasselVersion).arg(Global::quasselBuild));
+ reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org")
+ .arg(Quassel::buildInfo().plainVersionString)
+ .arg(Quassel::buildInfo().buildDate));
emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP VERSION request by %1").arg(prefix));
} else {
// display Version answer