Actually, most of the basic infrastructure is in place; but we can't configure it yet,
i.e. ISO-8859-15 it is for now, and encodings are not respected when we send stuff yet.
It instantly gives you a working utf8 detection on receiving though, so those crappy umlauts
should be a thing of the past now.
The infrastructure allows for setting individual encodings for networks, channels and even
IRC users (for queries), so putting a decent UI on that thing should make Quassel really useful
in international environments that are too backward to use utf8 yet :)
BTW, hacking on Christmas Eve proves to be really productive...
src/qtui/serverlist.h
src/qtui/settingsdlg.cpp
src/qtui/settingsdlg.h
-src/qtui/settingspage.h
src/qtui/settingspages.cpp
src/qtui/settingspages.h
src/qtui/topicwidget.cpp
}
void Client::setCoreConfiguration(const QVariantMap &settings) {
- writeDataToDevice(socket, settings);
+ SignalProxy::writeDataToDevice(socket, settings);
}
void Client::coreSocketConnected() {
clientInit["GuiProtocol"] = GUI_PROTOCOL;
clientInit["User"] = coreConnectionInfo["User"].toString();
clientInit["Password"] = coreConnectionInfo["Password"].toString();
- writeDataToDevice(socket, clientInit);
+ SignalProxy::writeDataToDevice(socket, clientInit);
}
void Client::coreSocketDisconnected() {
void Client::coreHasData() {
QVariant item;
- if(readDataFromDevice(socket, blockSize, item)) {
+ if(SignalProxy::readDataFromDevice(socket, blockSize, item)) {
emit recvPartialItem(1,1);
QVariantMap msg = item.toMap();
if (!msg["StartWizard"].toBool()) {
if(isChannelName(_bufferName))
return _bufferName;
else
- return nickFromMask(_bufferName);
+ return nickFromMask(_bufferName); // FIXME get rid of global functions and use the NetworkInfo stuff instead!
}
QDebug operator<<(QDebug dbg, const BufferInfo &b) {
//#include "nicktreemodel.h"
#include "signalproxy.h"
#include "ircuser.h"
+#include "util.h"
#include <QMapIterator>
#include <QHashIterator>
+#include <QTextCodec>
#include <QDebug>
return userModes(networkInfo->ircUser(nick));
}
+QTextCodec *IrcChannel::codecForEncoding() const {
+ return _codecForEncoding;
+}
+
+void IrcChannel::setCodecForEncoding(const QString &name) {
+ setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void IrcChannel::setCodecForEncoding(QTextCodec *codec) {
+ _codecForEncoding = codec;
+}
+
+QTextCodec *IrcChannel::codecForDecoding() const {
+ return _codecForDecoding;
+}
+
+void IrcChannel::setCodecForDecoding(const QString &name) {
+ setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void IrcChannel::setCodecForDecoding(QTextCodec *codec) {
+ _codecForDecoding = codec;
+}
+
+QString IrcChannel::decodeString(const QByteArray &text) const {
+ if(!codecForDecoding()) return networkInfo->decodeString(text);
+ return ::decodeString(text, _codecForDecoding);
+}
+
+QByteArray IrcChannel::encodeString(const QString string) const {
+ if(codecForEncoding()) {
+ return _codecForEncoding->fromUnicode(string);
+ }
+ return networkInfo->encodeString(string);
+}
+
// ====================
// PUBLIC SLOTS:
// ====================
QString userModes(IrcUser *ircuser) const;
QString userModes(const QString &nick) const;
+ QTextCodec *codecForEncoding() const;
+ QTextCodec *codecForDecoding() const;
+ void setCodecForEncoding(const QString &codecName);
+ void setCodecForEncoding(QTextCodec *codec);
+ void setCodecForDecoding(const QString &codecName);
+ void setCodecForDecoding(QTextCodec *codec);
+
+ QString decodeString(const QByteArray &text) const;
+ QByteArray encodeString(const QString string) const;
+
public slots:
void setTopic(const QString &topic);
QHash<IrcUser *, QString> _userModes;
NetworkInfo *networkInfo;
+
+ QTextCodec *_codecForEncoding;
+ QTextCodec *_codecForDecoding;
};
#endif
#include "signalproxy.h"
#include "ircchannel.h"
+#include <QTextCodec>
#include <QDebug>
IrcUser::IrcUser(const QString &hostmask, NetworkInfo *networkinfo)
_nick(nickFromMask(hostmask)),
_user(userFromMask(hostmask)),
_host(hostFromMask(hostmask)),
- networkInfo(networkinfo)
+ networkInfo(networkinfo),
+ _codecForEncoding(0),
+ _codecForDecoding(0)
{
updateObjectName();
}
return chanList;
}
+QTextCodec *IrcUser::codecForEncoding() const {
+ return _codecForEncoding;
+}
+
+void IrcUser::setCodecForEncoding(const QString &name) {
+ setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void IrcUser::setCodecForEncoding(QTextCodec *codec) {
+ _codecForEncoding = codec;
+}
+
+QTextCodec *IrcUser::codecForDecoding() const {
+ return _codecForDecoding;
+}
+
+void IrcUser::setCodecForDecoding(const QString &name) {
+ setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void IrcUser::setCodecForDecoding(QTextCodec *codec) {
+ _codecForDecoding = codec;
+}
+
+QString IrcUser::decodeString(const QByteArray &text) const {
+ if(!codecForDecoding()) return networkInfo->decodeString(text);
+ return ::decodeString(text, codecForDecoding());
+}
+
+QByteArray IrcUser::encodeString(const QString string) const {
+ if(codecForEncoding()) {
+ return codecForEncoding()->fromUnicode(string);
+ }
+ return networkInfo->encodeString(string);
+}
+
// ====================
// PUBLIC SLOTS:
// ====================
Q_PROPERTY(QStringList channels READ channels STORED false)
// Q_PROPERTY(QStringList usermodes READ usermodes WRITE setUsermodes)
-
public:
IrcUser(const QString &hostmask, NetworkInfo *networkInfo);
virtual ~IrcUser();
QStringList channels() const;
+ // user-specific encodings
+ QTextCodec *codecForEncoding() const;
+ QTextCodec *codecForDecoding() const;
+ void setCodecForEncoding(const QString &codecName);
+ void setCodecForEncoding(QTextCodec *codec);
+ void setCodecForDecoding(const QString &codecName);
+ void setCodecForDecoding(QTextCodec *codec);
+
+ QString decodeString(const QByteArray &text) const;
+ QByteArray encodeString(const QString string) const;
+
public slots:
void setUser(const QString &user);
void setHost(const QString &host);
void updateHostmask(const QString &mask);
void setUserModes(const QString &modes);
-
+
void joinChannel(IrcChannel *channel);
void joinChannel(const QString &channelname);
void partChannel(IrcChannel *channel);
void hostSet(QString host);
void nickSet(QString newnick);
void hostmaskUpdated(QString mask);
-
+
void userModesSet(QString modes);
-
+
void channelJoined(QString channel);
void channelParted(QString channel);
void userModeRemoved(QString mode);
void renameObject(QString oldname, QString newname);
-
+
// void setUsermodes(const QSet<QString> &usermodes);
// QSet<QString> usermodes() const;
private slots:
void updateObjectName();
void channelDestroyed();
-
+
private:
inline bool operator==(const IrcUser &ircuser2) {
return (_nick.toLower() == ircuser2.nick().toLower());
// QSet<QString> _channels;
QSet<IrcChannel *> _channels;
QString _userModes;
-
+
NetworkInfo *networkInfo;
+
+ QTextCodec *_codecForEncoding;
+ QTextCodec *_codecForDecoding;
};
#endif
#include "ircchannel.h"
#include <QDebug>
+#include <QTextCodec>
#include "util.h"
_currentServer(QString()),
_prefixes(QString()),
_prefixModes(QString()),
- _proxy(NULL)
+ _proxy(0),
+ _codecForEncoding(0),
+ _codecForDecoding(0)
{
setObjectName(QString::number(networkid));
}
return _ircChannels.values();
}
+QTextCodec *NetworkInfo::codecForEncoding() const {
+ return _codecForEncoding;
+}
+
+void NetworkInfo::setCodecForEncoding(const QString &name) {
+ setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void NetworkInfo::setCodecForEncoding(QTextCodec *codec) {
+ _codecForEncoding = codec;
+}
+
+QTextCodec *NetworkInfo::codecForDecoding() const {
+ return _codecForDecoding;
+}
+
+void NetworkInfo::setCodecForDecoding(const QString &name) {
+ setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
+}
+
+void NetworkInfo::setCodecForDecoding(QTextCodec *codec) {
+ _codecForDecoding = codec;
+}
+
+QString NetworkInfo::decodeString(const QByteArray &text) const {
+ return ::decodeString(text, _codecForDecoding);
+}
+
+QByteArray NetworkInfo::encodeString(const QString string) const {
+ if(_codecForEncoding) {
+ return _codecForEncoding->fromUnicode(string);
+ }
+ return string.toAscii();
+}
+
// ====================
// Public Slots:
// ====================
SignalProxy *proxy() const;
void setProxy(SignalProxy *proxy);
-
+
bool isMyNick(const QString &nick) const;
bool isMyNick(IrcUser *ircuser) const;
QString prefixToMode(const QCharRef &prefix);
QString modeToPrefix(const QString &mode);
QString modeToPrefix(const QCharRef &mode);
-
+
QString networkName() const;
QString currentServer() const;
QString myNick() const;
bool supports(const QString ¶m) const;
QString support(const QString ¶m) const;
-
+
IrcUser *newIrcUser(const QString &hostmask);
IrcUser *ircUser(QString nickname) const;
QList<IrcUser *> ircUsers() const;
-
+
IrcChannel *newIrcChannel(const QString &channelname);
IrcChannel *ircChannel(QString channelname);
QList<IrcChannel *> ircChannels() const;
+ QTextCodec *codecForEncoding() const;
+ QTextCodec *codecForDecoding() const;
+ void setCodecForEncoding(const QString &codecName);
+ void setCodecForEncoding(QTextCodec *codec);
+ void setCodecForDecoding(const QString &codecName);
+ void setCodecForDecoding(QTextCodec *codec);
+
+ QString decodeString(const QByteArray &text) const;
+ QByteArray encodeString(const QString string) const;
+
public slots:
void setNetworkName(const QString &networkName);
void setCurrentServer(const QString ¤tServer);
QPointer<SignalProxy> _proxy;
void determinePrefixes();
+ QTextCodec *_codecForEncoding;
+ QTextCodec *_codecForDecoding;
+
};
#endif
void detachObject(QObject *obj);
void detachSignals(QObject *sender);
void detachSlots(QObject *receiver);
-
+
+ //! Writes a QVariant to a device.
+ /** The data item is prefixed with the resulting blocksize,
+ * so the corresponding function readDataFromDevice() can check if enough data is available
+ * at the device to reread the item.
+ */
static void writeDataToDevice(QIODevice *dev, const QVariant &item);
+
+ //! Reads a data item from a device that has been written by writeDataToDevice().
+ /** If not enough data bytes are available, the function returns false and the QVariant reference
+ * remains untouched.
+ */
static bool readDataFromDevice(QIODevice *dev, quint32 &blockSize, QVariant &item);
static QString methodBaseName(const QMetaMethod &method);
/***************************************************************************
- * Copyright (C) 2005/06 by the Quassel IRC Team *
+ * Copyright (C) 2005-07 by the Quassel IRC Team *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
return QString("#&!+").contains(str[0]);
}
-QString decodeString(QByteArray input, QString encoding) {
+QString decodeString(const QByteArray &input, QTextCodec *codec) {
// First, we check if it's utf8. It is very improbable to encounter a string that looks like
// valid utf8, but in fact is not. This means that if the input string passes as valid utf8, it
// is safe to assume that it is.
- Q_ASSERT(sizeof(const char) == sizeof(quint8)); // just to make sure
+ // Q_ASSERT(sizeof(const char) == sizeof(quint8)); // In God we trust...
bool isUtf8 = true;
int cnt = 0;
for(int i = 0; i < input.size(); i++) {
//qDebug() << "Detected utf8:" << s;
return s;
}
- QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii());
- if(!codec) {
- qWarning() << QString("Invalid encoding: %1").arg(encoding);
- return QString::fromAscii(input);
- }
+ //QTextCodec *codec = QTextCodec::codecForName(encoding.toAscii());
+ if(!codec) return QString::fromAscii(input);
return codec->toUnicode(input);
}
+/* not needed anymore
void writeDataToDevice(QIODevice *dev, const QVariant &item) {
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
in >> item;
return true;
}
-
+*/
uint editingDistance(const QString &s1, const QString &s2) {
uint n = s1.size()+1;
#include <QString>
#include <QMetaMethod>
+
+// TODO Use versions from NetworkInfo instead
QString nickFromMask(QString mask);
QString userFromMask(QString mask);
QString hostFromMask(QString mask);
+bool isChannelName(QString str);
+
//! Take a string and decode it using the specified text codec, recognizing utf8.
/** This function takes a string and first checks if it is encoded in utf8, in which case it is
* decoded appropriately. Otherwise, the specified text codec is used to transform the string.
* \param input The input string containing encoded data
- * \param encoding The text encoding we assume if it's not utf8
+ * \param encoding The text codec we use if the input is not utf8
* \return The decoded string.
*/
-QString decodeString(QByteArray input, QString encoding = "ISO-8859-15");
-
-bool isChannelName(QString str);
-
-/**
- * Writes a QVariant to a device. The data item is prefixed with the resulting blocksize,
- * so the corresponding function readDataFromDevice() can check if enough data is available
- * at the device to reread the item.
- */
-void writeDataToDevice(QIODevice *, const QVariant &);
-
-/** Reads a data item from a device that has previously been written by writeDataToDevice().
- * If not enough data bytes are available, the function returns false and the QVariant reference
- * remains untouched.
- */
-bool readDataFromDevice(QIODevice *, quint32 &, QVariant &);
+QString decodeString(const QByteArray &input, QTextCodec *codec = 0);
+// NOTE: We have static copies of these in SignalProxy...
+//void writeDataToDevice(QIODevice *, const QVariant &);
+//bool readDataFromDevice(QIODevice *, quint32 &, QVariant &);
uint editingDistance(const QString &s1, const QString &s2);
#include "core.h"
#include "coresession.h"
#include "coresettings.h"
+#include "signalproxy.h"
#include "sqlitestorage.h"
-#include "util.h"
#include <QMetaObject>
#include <QMetaMethod>
Q_ASSERT(socket && blockSizes.contains(socket));
quint32 bsize = blockSizes.value(socket);
QVariant item;
- if(readDataFromDevice(socket, bsize, item)) {
+ if(SignalProxy::readDataFromDevice(socket, bsize, item)) {
// we need to auth the client
try {
QVariantMap msg = item.toMap();
disconnect(socket, 0, this, 0);
sessions[uid]->addClient(socket);
qDebug() << "Client initialized successfully.";
- writeDataToDevice(socket, reply);
+ SignalProxy::writeDataToDevice(socket, reply);
}
void Core::processCoreSetup(QTcpSocket *socket, QVariantMap &msg) {
QVariantMap reply;
reply["StartWizard"] = true;
reply["StorageProviders"] = availableStorageProviders();
- writeDataToDevice(socket, reply);
+ SignalProxy::writeDataToDevice(socket, reply);
} else {
// write coresettings
CoreSettings s;
QVariantMap reply;
reply["StartWizard"] = true;
reply["StorageProviders"] = availableStorageProviders();
- writeDataToDevice(socket, reply);
+ SignalProxy::writeDataToDevice(socket, reply);
}
}
enum CtcpType {CtcpQuery, CtcpReply};
- QStringList parse(CtcpType, QString, QString, QString);
+ QStringList parse(CtcpType, QString prefix, QString target, QString message);
QString dequote(QString);
QString XdelimDequote(QString);
QString pack(QString ctcpTag, QString message);
void query(QString bufname, QString ctcpTag, QString message);
void reply(QString bufname, QString ctcpTag, QString message);
-
+
public slots:
void handleAction(CtcpType, QString prefix, QString target, QString param);
void handlePing(CtcpType, QString prefix, QString target, QString param);
private:
QString XDELIM;
QHash<QString, QString> ctcpMDequoteHash;
- QHash<QString, QString> ctcpXDelimDequoteHash;
+ QHash<QString, QString> ctcpXDelimDequoteHash;
};
#include <QDebug>
IrcServerHandler::IrcServerHandler(Server *parent)
- : BasicHandler(parent) {
+ : BasicHandler(parent), server(parent) {
}
IrcServerHandler::~IrcServerHandler() {
+
+}
+
+QString IrcServerHandler::serverDecode(const QByteArray &string) {
+ return server->serverDecode(string);
+}
+
+QStringList IrcServerHandler::serverDecode(const QList<QByteArray> &stringlist) {
+ QStringList list;
+ foreach(QByteArray s, stringlist) list << server->serverDecode(s);
+ return list;
+}
+
+QString IrcServerHandler::bufferDecode(const QString &bufferName, const QByteArray &string) {
+ return server->bufferDecode(bufferName, string);
+}
+
+QStringList IrcServerHandler::bufferDecode(const QString &bufferName, const QList<QByteArray> &stringlist) {
+ QStringList list;
+ foreach(QByteArray s, stringlist) list << server->bufferDecode(bufferName, s);
+ return list;
+}
+
+QString IrcServerHandler::userDecode(const QString &userNick, const QByteArray &string) {
+ return server->userDecode(userNick, string);
+}
+
+QStringList IrcServerHandler::userDecode(const QString &userNick, const QList<QByteArray> &stringlist) {
+ QStringList list;
+ foreach(QByteArray s, stringlist) list << server->userDecode(userNick, s);
+ return list;
}
/*! Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
-void IrcServerHandler::handleServerMsg(QByteArray rawmsg) {
+void IrcServerHandler::handleServerMsg(QByteArray msg) {
try {
- if(rawmsg.isEmpty()) {
+ if(msg.isEmpty()) {
qWarning() << "Received empty string from server!";
return;
}
- // TODO Implement encoding conversion
- /* At this point, we have a raw message as a byte array. This needs to be converted to a QString somewhere.
- * Problem is, that at this point we don't know which encoding to use for the various parts of the message.
- * This is something the command handler needs to take care of (e.g. PRIVMSG needs to first parse for CTCP,
- * and then convert the raw strings into the correct encoding.
- * We _can_ safely assume Server encoding for prefix and cmd, but not for the params. Therefore, we need to
- * change from a QStringList to a QList<QByteArray> in all the handlers, and have the handlers call decodeString
- * where needed...
- */
- QString msg = QString::fromLatin1(rawmsg);
-
- // OK, first we split the raw message into its various parts...
+
+ // Now we split the raw message into its various parts...
QString prefix = "";
+ QByteArray trailing;
QString cmd;
- QStringList params;
-
- // a colon as the first chars indicates the existance of a prefix
- if(msg[0] == ':') {
- msg.remove(0,1);
- prefix = msg.section(' ', 0, 0);
- msg = msg.section(' ', 1);
- }
- // next string without a whitespace is the command
- cmd = msg.section(' ', 0, 0).toUpper();
- msg = msg.mid(cmd.length());
-
- // get the parameters
- QString trailing = "";
- if(msg.contains(" :")) {
- trailing = msg.section(" :", 1);
- msg = msg.section(" :", 0, 0);
+ // First, check for a trailing parameter introduced by " :", since this might screw up splitting the msg
+ // NOTE: This assumes that this is true in raw encoding, but well, hopefully there are no servers running in japanese on protocol level...
+ int idx = msg.indexOf(" :");
+ if(idx >= 0) {
+ if(msg.length() > idx + 2) trailing = msg.mid(idx + 2);
+ msg = msg.left(idx);
}
- if(!msg.isEmpty()) {
- params << msg.split(' ', QString::SkipEmptyParts);
+ // OK, now it is safe to split...
+ QList<QByteArray> params = msg.split(' ');
+ if(!trailing.isEmpty()) params << trailing;
+ if(params.count() < 1) {
+ qWarning() << "Received invalid string from server!";
+ return;
}
- if(!trailing.isEmpty()) {
- params << trailing;
+
+ QString foo = serverDecode(params.takeFirst());
+
+ // a colon as the first chars indicates the existence of a prefix
+ if(foo[0] == ':') {
+ foo.remove(0, 1);
+ prefix = foo;
+ if(params.count() < 1) {
+ qWarning() << "Received invalid string from server!";
+ return;
+ }
+ foo = serverDecode(params.takeFirst());
}
+ // next string without a whitespace is the command
+ cmd = foo.trimmed().toUpper();
+
// numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this!
uint num = cmd.toUInt();
if(num > 0) {
- Q_ASSERT(params.count() > 0); // Violation to RFC
+ if(params.count() == 0) {
+ qWarning() << "Message received from server violates RFC and is ignored!";
+ return;
+ }
params.removeFirst();
}
// Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-)
- handle(cmd, Q_ARG(QString, prefix), Q_ARG(QStringList, params));
+ handle(cmd, Q_ARG(QString, prefix), Q_ARG(QList<QByteArray>, params));
//handle(cmd, Q_ARG(QString, prefix));
} catch(Exception e) {
emit displayMsg(Message::Error, "", e.msg());
}
-void IrcServerHandler::defaultHandler(QString cmd, QString prefix, QStringList params) {
+void IrcServerHandler::defaultHandler(QString cmd, QString prefix, QList<QByteArray> rawparams) {
+ // we assume that all this happens in server encoding
+ QStringList params;
+ foreach(QByteArray r, rawparams) params << serverDecode(r);
uint num = cmd.toUInt();
if(num) {
// A lot of server messages don't really need their own handler because they don't do much.
//******************************/
// IRC SERVER HANDLER
//******************************/
-void IrcServerHandler::handleJoin(QString prefix, QStringList params) {
+void IrcServerHandler::handleJoin(QString prefix, QList<QByteArray> params) {
Q_ASSERT(params.count() == 1);
- QString channel = params[0];
+ QString channel = serverDecode(params[0]);
IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
emit displayMsg(Message::Join, channel, channel, prefix);
//qDebug() << "IrcServerHandler::handleJoin()" << prefix << params;
ircuser->joinChannel(channel);
}
-void IrcServerHandler::handleKick(QString prefix, QStringList params) {
+void IrcServerHandler::handleKick(QString prefix, QList<QByteArray> params) {
networkInfo()->updateNickFromMask(prefix);
- IrcUser *victim = networkInfo()->ircUser(params[1]);
- QString channel = params[0];
+ IrcUser *victim = networkInfo()->ircUser(serverDecode(params[1]));
+ QString channel = serverDecode(params[0]);
Q_ASSERT(victim);
victim->partChannel(channel);
QString msg;
if(params.count() > 2) // someone got a reason!
- msg = QString("%1 %2").arg(victim->nick()).arg(params[2]);
+ msg = QString("%1 %2").arg(victim->nick()).arg(bufferDecode(channel, params[2]));
else
msg = victim->nick();
-
- emit displayMsg(Message::Kick, params[0], msg, prefix);
+
+ emit displayMsg(Message::Kick, channel, msg, prefix);
}
-void IrcServerHandler::handleMode(QString prefix, QStringList params) {
+void IrcServerHandler::handleMode(QString prefix, QList<QByteArray> params) {
Q_UNUSED(prefix)
Q_UNUSED(params)
// }
}
-void IrcServerHandler::handleNick(QString prefix, QStringList params) {
+void IrcServerHandler::handleNick(QString prefix, QList<QByteArray> params) {
IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
Q_ASSERT(ircuser);
- QString newnick = params[0];
+ QString newnick = serverDecode(params[0]);
QString oldnick = ircuser->nick();
foreach(QString channel, ircuser->channels()) {
ircuser->setNick(newnick);
}
-void IrcServerHandler::handleNotice(QString prefix, QStringList params) {
+void IrcServerHandler::handleNotice(QString prefix, QList<QByteArray> params) {
if(networkInfo()->currentServer().isEmpty() || networkInfo()->currentServer() == prefix)
- emit displayMsg(Message::Server, "", params[1], prefix);
+ emit displayMsg(Message::Server, "", serverDecode(params[1]), prefix);
else
- emit displayMsg(Message::Notice, "", params[1], prefix);
+ emit displayMsg(Message::Notice, "", userDecode(prefix, params[1]), prefix);
}
-void IrcServerHandler::handlePart(QString prefix, QStringList params) {
+void IrcServerHandler::handlePart(QString prefix, QList<QByteArray> params) {
IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
- QString channel = params[0];
+ QString channel = serverDecode(params[0]);
Q_ASSERT(ircuser);
-
+
ircuser->partChannel(channel);
-
+
QString msg;
if(params.count() > 1)
- msg = params[1];
-
- emit displayMsg(Message::Part, params[0], msg, prefix);
+ msg = userDecode(ircuser->nick(), params[1]);
+
+ emit displayMsg(Message::Part, channel, msg, prefix);
}
-void IrcServerHandler::handlePing(QString prefix, QStringList params) {
- Q_UNUSED(prefix)
- emit putCmd("PONG", params);
+void IrcServerHandler::handlePing(QString prefix, QList<QByteArray> params) {
+ Q_UNUSED(prefix);
+ emit putCmd("PONG", serverDecode(params));
}
-void IrcServerHandler::handlePrivmsg(QString prefix, QStringList params) {
- networkInfo()->updateNickFromMask(prefix);
- if(params.count()<2)
- params << QString("");
-
- // it's possible to pack multiple privmsgs into one param using ctcp
- QStringList messages = server->ctcpHandler()->parse(CtcpHandler::CtcpQuery, prefix, params[0], params[1]);
-
+void IrcServerHandler::handlePrivmsg(QString prefix, QList<QByteArray> params) {
+ IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
+ Q_ASSERT(ircuser);
+ if(params.count() < 2)
+ params << QByteArray("");
+
+ QString target = serverDecode(params[0]);
+
// are we the target or is it a channel?
- if(networkInfo()->isMyNick(params[0])) {
+ if(networkInfo()->isMyNick(target)) {
+ // it's possible to pack multiple privmsgs into one param using ctcp
+ QStringList messages = server->ctcpHandler()->parse(CtcpHandler::CtcpQuery, prefix, target, userDecode(ircuser->nick(), params[1]));
foreach(QString message, messages) {
if(!message.isEmpty()) {
emit displayMsg(Message::Plain, "", message, prefix, Message::PrivMsg);
}
}
-
} else {
- Q_ASSERT(isChannelName(params[0])); // should be channel!
+ Q_ASSERT(isChannelName(target)); // should be channel!
+ QStringList messages = server->ctcpHandler()->parse(CtcpHandler::CtcpQuery, prefix, target, bufferDecode(target, params[1]));
foreach(QString message, messages) {
if(!message.isEmpty()) {
- emit displayMsg(Message::Plain, params[0], message, prefix);
+ emit displayMsg(Message::Plain, target, message, prefix);
}
}
}
}
-void IrcServerHandler::handleQuit(QString prefix, QStringList params) {
+void IrcServerHandler::handleQuit(QString prefix, QList<QByteArray> params) {
IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
Q_ASSERT(ircuser);
- //qDebug() << "IrcServerHandler:handleQuit" << prefix << params;
QString msg;
if(params.count())
- msg = params[0];
-
+ msg = userDecode(ircuser->nick(), params[0]);
+
foreach(QString channel, ircuser->channels())
emit displayMsg(Message::Quit, channel, msg, prefix);
-
+
networkInfo()->removeIrcUser(nickFromMask(prefix));
}
-void IrcServerHandler::handleTopic(QString prefix, QStringList params) {
+void IrcServerHandler::handleTopic(QString prefix, QList<QByteArray> params) {
IrcUser *ircuser = networkInfo()->updateNickFromMask(prefix);
- QString channel = params[0];
- QString topic = params[1];
+ QString channel = serverDecode(params[0]);
+ QString topic = bufferDecode(channel, params[1]);
Q_ASSERT(ircuser);
networkInfo()->ircChannel(channel)->setTopic(topic);
- emit displayMsg(Message::Server, params[0], tr("%1 has changed topic for %2 to: \"%3\"").arg(ircuser->nick()).arg(channel).arg(topic));
+ emit displayMsg(Message::Server, channel, tr("%1 has changed topic for %2 to: \"%3\"").arg(ircuser->nick()).arg(channel).arg(topic));
}
/* RPL_WELCOME */
-void IrcServerHandler::handle001(QString prefix, QStringList params) {
+void IrcServerHandler::handle001(QString prefix, QList<QByteArray> params) {
// there should be only one param: "Welcome to the Internet Relay Network <nick>!<user>@<host>"
- QString myhostmask = params[0].section(' ', -1, -1);
+ QString param = serverDecode(params[0]);
+ QString myhostmask = param.section(' ', -1, -1);
networkInfo()->setCurrentServer(prefix);
networkInfo()->setMyNick(nickFromMask(myhostmask));
- emit displayMsg(Message::Server, "", params[0], prefix);
-
-
- // TODO: reimplement perform List!
- //// send performlist
- //QStringList performList = networkSettings["Perform"].toString().split( "\n" );
- //int count = performList.count();
- //for(int a = 0; a < count; a++) {
- // if(!performList[a].isEmpty() ) {
- // userInput(network, "", performList[a]);
- // }
- //}
+ emit displayMsg(Message::Server, "", param, prefix);
}
/* RPL_ISUPPORT */
// TODO Complete 005 handling, also use sensible defaults for non-sent stuff
-void IrcServerHandler::handle005(QString prefix, QStringList params) {
+void IrcServerHandler::handle005(QString prefix, QList<QByteArray> params) {
Q_UNUSED(prefix)
- QString rpl_isupport_suffix = params.takeLast();
+ QString rpl_isupport_suffix = serverDecode(params.takeLast());
if(rpl_isupport_suffix.toLower() != QString("are supported by this server")) {
qWarning() << "Received invalid RPL_ISUPPORT! Suffix is:" << rpl_isupport_suffix << "Excpected: are supported by this server";
return;
}
- foreach(QString param, params) {
+ foreach(QString param, serverDecode(params)) {
QString key = param.section("=", 0, 0);
QString value = param.section("=", 1);
networkInfo()->addSupport(key, value);
/* RPL_NOTOPIC */
-void IrcServerHandler::handle331(QString prefix, QStringList params) {
- Q_UNUSED(prefix)
- networkInfo()->ircChannel(params[0])->setTopic(QString());
- emit displayMsg(Message::Server, params[0], tr("No topic is set for %1.").arg(params[0]));
+void IrcServerHandler::handle331(QString prefix, QList<QByteArray> params) {
+ Q_UNUSED(prefix);
+ QString channel = serverDecode(params[0]);
+ networkInfo()->ircChannel(channel)->setTopic(QString());
+ emit displayMsg(Message::Server, channel, tr("No topic is set for %1.").arg(channel));
}
/* RPL_TOPIC */
-void IrcServerHandler::handle332(QString prefix, QStringList params) {
- Q_UNUSED(prefix)
- networkInfo()->ircChannel(params[0])->setTopic(params[1]);
- emit displayMsg(Message::Server, params[0], tr("Topic for %1 is \"%2\"").arg(params[0]).arg(params[1]));
+void IrcServerHandler::handle332(QString prefix, QList<QByteArray> params) {
+ Q_UNUSED(prefix);
+ QString channel = serverDecode(params[0]);
+ QString topic = bufferDecode(channel, params[1]);
+ networkInfo()->ircChannel(channel)->setTopic(topic);
+ emit displayMsg(Message::Server, channel, tr("Topic for %1 is \"%2\"").arg(channel, topic));
}
/* Topic set by... */
-void IrcServerHandler::handle333(QString prefix, QStringList params) {
- Q_UNUSED(prefix)
- emit displayMsg(Message::Server, params[0], tr("Topic set by %1 on %2").arg(params[1]).arg(QDateTime::fromTime_t(params[2].toUInt()).toString()));
+void IrcServerHandler::handle333(QString prefix, QList<QByteArray> params) {
+ Q_UNUSED(prefix);
+ QString channel = serverDecode(params[0]);
+ emit displayMsg(Message::Server, channel, tr("Topic set by %1 on %2")
+ .arg(bufferDecode(channel, params[1]), QDateTime::fromTime_t(bufferDecode(channel, params[2]).toUInt()).toString()));
}
/* RPL_NAMREPLY */
-void IrcServerHandler::handle353(QString prefix, QStringList params) {
+void IrcServerHandler::handle353(QString prefix, QList<QByteArray> params) {
Q_UNUSED(prefix)
params.removeFirst(); // either "=", "*" or "@" indicating a public, private or secret channel
- QString channelname = params.takeFirst();
+ QString channelname = serverDecode(params.takeFirst());
- foreach(QString nick, params.takeFirst().split(' ')) {
+ foreach(QString nick, serverDecode(params.takeFirst()).split(' ')) {
QString mode = QString();
if(networkInfo()->prefixes().contains(nick[0])) {
}
/* ERR_ERRONEUSNICKNAME */
-void IrcServerHandler::handle432(QString prefix, QStringList params) {
+void IrcServerHandler::handle432(QString prefix, QList<QByteArray> params) {
Q_UNUSED(prefix)
Q_UNUSED(params)
emit displayMsg(Message::Error, "", tr("Your desired nickname contains illegal characters!"));
}
/* ERR_NICKNAMEINUSE */
-void IrcServerHandler::handle433(QString prefix, QStringList params) {
+void IrcServerHandler::handle433(QString prefix, QList<QByteArray> params) {
Q_UNUSED(prefix)
- QString errnick = params[0];
+ QString errnick = serverDecode(params[0]);
emit displayMsg(Message::Error, "", tr("Nick %1 is already taken").arg(errnick));
emit displayMsg(Message::Error, "", tr("Please use /nick <othernick> to continue your IRC-Session!"));
// FIXME!
~IrcServerHandler();
void handleServerMsg(QByteArray rawMsg);
-
+
+ QString serverDecode(const QByteArray &string);
+ QStringList serverDecode(const QList<QByteArray> &stringlist);
+ QString bufferDecode(const QString &bufferName, const QByteArray &string);
+ QStringList bufferDecode(const QString &bufferName, const QList<QByteArray> &stringlist);
+ QString userDecode(const QString &userNick, const QByteArray &string);
+ QStringList userDecode(const QString &userNick, const QList<QByteArray> &stringlist);
+
+
public slots:
- void handleJoin(QString, QStringList);
- void handleKick(QString, QStringList);
- void handleMode(QString, QStringList);
- void handleNick(QString, QStringList);
- void handleNotice(QString, QStringList);
- void handlePart(QString, QStringList);
- void handlePing(QString, QStringList);
- void handlePrivmsg(QString, QStringList);
- void handleQuit(QString, QStringList);
- void handleTopic(QString, QStringList);
-
- void handle001(QString, QStringList); // RPL_WELCOME
- void handle005(QString, QStringList); // RPL_ISUPPORT
- void handle331(QString, QStringList); // RPL_NOTOPIC
- void handle332(QString, QStringList); // RPL_TOPIC
- void handle333(QString, QStringList); // Topic set by...
- void handle353(QString, QStringList); // RPL_NAMREPLY
- void handle432(QString, QStringList); // ERR_ERRONEUSNICKNAME
- void handle433(QString, QStringList); // ERR_NICKNAMEINUSE
-
- void defaultHandler(QString cmd, QString prefix, QStringList params);
+ void handleJoin(QString, QList<QByteArray>);
+ void handleKick(QString, QList<QByteArray>);
+ void handleMode(QString, QList<QByteArray>);
+ void handleNick(QString, QList<QByteArray>);
+ void handleNotice(QString, QList<QByteArray>);
+ void handlePart(QString, QList<QByteArray>);
+ void handlePing(QString, QList<QByteArray>);
+ void handlePrivmsg(QString, QList<QByteArray>);
+ void handleQuit(QString, QList<QByteArray>);
+ void handleTopic(QString, QList<QByteArray>);
+
+ void handle001(QString, QList<QByteArray>); // RPL_WELCOME
+ void handle005(QString, QList<QByteArray>); // RPL_ISUPPORT
+ void handle331(QString, QList<QByteArray>); // RPL_NOTOPIC
+ void handle332(QString, QList<QByteArray>); // RPL_TOPIC
+ void handle333(QString, QList<QByteArray>); // Topic set by...
+ void handle353(QString, QList<QByteArray>); // RPL_NAMREPLY
+ void handle432(QString, QList<QByteArray>); // ERR_ERRONEUSNICKNAME
+ void handle433(QString, QList<QByteArray>); // ERR_NICKNAMEINUSE
+
+ void defaultHandler(QString cmd, QString prefix, QList<QByteArray> params);
+
+ private:
+ Server *server;
};
_previousState(state)
{
connect(networkInfo(), SIGNAL(currentServerSet(const QString &)), this, SLOT(sendPerform()));
+ networkInfo()->setCodecForEncoding("ISO-8859-15"); // FIXME
+ networkInfo()->setCodecForDecoding("ISO-8859-15"); // FIXME
networkInfo()->setNetworkName(net);
networkInfo()->setProxy(coreSession()->signalProxy());
}
exec();
}
+QString Server::serverDecode(const QByteArray &string) const {
+ return networkInfo()->decodeString(string);
+}
+
+QString Server::bufferDecode(const QString &bufferName, const QByteArray &string) const {
+ Q_UNUSED(bufferName);
+ // TODO: Implement buffer-specific encodings
+ return networkInfo()->decodeString(string);
+}
+
+QString Server::userDecode(const QString &userNick, const QByteArray &string) const {
+ IrcUser *user = networkInfo()->ircUser(userNick);
+ if(user) return user->decodeString(string);
+ return networkInfo()->decodeString(string);
+}
+
+QByteArray Server::serverEncode(const QString &string) const {
+ return networkInfo()->encodeString(string);
+}
+
+QByteArray Server::bufferEncode(const QString &bufferName, const QString &string) const {
+ Q_UNUSED(bufferName);
+ // TODO: Implement buffer-specific encodings
+ return networkInfo()->encodeString(string);
+}
+
+QByteArray Server::userEncode(const QString &userNick, const QString &string) const {
+ IrcUser *user = networkInfo()->ircUser(userNick);
+ if(user) return user->encodeString(string);
+ return networkInfo()->encodeString(string);
+}
+
+
void Server::connectToIrc(QString net) {
if(net != networkName())
return; // not me!
CtcpHandler *ctcpHandler() const { return _ctcpHandler; }
QVariant state(); ///< Return data necessary to restore the server's state upon core restart
-
+
+ //! Decode a string using the server (network) decoding.
+ QString serverDecode(const QByteArray &string) const;
+
+ //! Decode a string using a buffer-specific encoding if one is set (and use the server encoding else).
+ QString bufferDecode(const QString &bufferName, const QByteArray &string) const;
+
+ //! Decode a string using a IrcUser specific encoding, if one exists (using the server encoding else).
+ QString userDecode(const QString &userNick, const QByteArray &string) const;
+
+ //! Encode a string using the server (network) encoding.
+ QByteArray serverEncode(const QString &string) const;
+
+ //! Encode a string using the buffer-specific encoding, if set, and use the server encoding else.
+ QByteArray bufferEncode(const QString &bufferName, const QString &string) const;
+
+ //! Encode a string using the user-specific encoding, if set, and use the server encoding else.
+ QByteArray userEncode(const QString &userNick, const QString &string) const;
+
public slots:
// void setServerOptions();
void connectToIrc(QString net);