From 723db5bff304ad3fdf5a0609198c65a66bfbaea7 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Wed, 13 Feb 2008 16:32:49 +0000 Subject: [PATCH 1/1] More improvements to encoding handling. There is now a server encoding that is independent from the message sending/receiving encodings, so you can have a channelname encoded in ISO, for example, and still send messages in utf8 to that chan. No UI to configure this yet, the server encoding is hardcoded to Latin1 for now. The rest can be edited in network settings. --- src/common/ircchannel.cpp | 9 +++++---- src/common/ircchannel.h | 2 +- src/common/ircuser.cpp | 5 ++--- src/common/ircuser.h | 2 +- src/common/main.cpp | 2 +- src/common/network.cpp | 27 +++++++++++++++++++++------ src/common/network.h | 7 +++++-- src/core/basichandler.cpp | 16 ++++++++-------- src/core/basichandler.h | 8 ++++---- src/core/ircserverhandler.cpp | 24 +++++++++++++----------- src/core/networkconnection.cpp | 21 +++++++++++++-------- src/core/networkconnection.h | 12 ++++++------ src/core/userinputhandler.cpp | 14 +++++++------- 13 files changed, 87 insertions(+), 62 deletions(-) diff --git a/src/common/ircchannel.cpp b/src/common/ircchannel.cpp index 0587697c..f5710ba2 100644 --- a/src/common/ircchannel.cpp +++ b/src/common/ircchannel.cpp @@ -33,12 +33,13 @@ #include -IrcChannel::IrcChannel(const QString &channelname, Network *network) - : SyncableObject(network), +IrcChannel::IrcChannel(const QString &channelname, Network *network) : SyncableObject(network), _initialized(false), _name(channelname), _topic(QString()), - network(network) + network(network), + _codecForEncoding(0), + _codecForDecoding(0) { setObjectName(QString::number(network->networkId().toInt()) + "/" + channelname); } @@ -124,7 +125,7 @@ QString IrcChannel::decodeString(const QByteArray &text) const { return ::decodeString(text, _codecForDecoding); } -QByteArray IrcChannel::encodeString(const QString string) const { +QByteArray IrcChannel::encodeString(const QString &string) const { if(codecForEncoding()) { return _codecForEncoding->fromUnicode(string); } diff --git a/src/common/ircchannel.h b/src/common/ircchannel.h index d9708145..2bf5f64b 100644 --- a/src/common/ircchannel.h +++ b/src/common/ircchannel.h @@ -61,7 +61,7 @@ public: void setCodecForDecoding(QTextCodec *codec); QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString string) const; + QByteArray encodeString(const QString &string) const; public slots: void setTopic(const QString &topic); diff --git a/src/common/ircuser.cpp b/src/common/ircuser.cpp index 223a02f5..c3c2d0cd 100644 --- a/src/common/ircuser.cpp +++ b/src/common/ircuser.cpp @@ -28,8 +28,7 @@ #include #include -IrcUser::IrcUser(const QString &hostmask, Network *network) - : SyncableObject(network), +IrcUser::IrcUser(const QString &hostmask, Network *network) : SyncableObject(network), _initialized(false), _nick(nickFromMask(hostmask)), _user(userFromMask(hostmask)), @@ -145,7 +144,7 @@ QString IrcUser::decodeString(const QByteArray &text) const { return ::decodeString(text, codecForDecoding()); } -QByteArray IrcUser::encodeString(const QString string) const { +QByteArray IrcUser::encodeString(const QString &string) const { if(codecForEncoding()) { return codecForEncoding()->fromUnicode(string); } diff --git a/src/common/ircuser.h b/src/common/ircuser.h index da963231..077cc6d4 100644 --- a/src/common/ircuser.h +++ b/src/common/ircuser.h @@ -80,7 +80,7 @@ public: void setCodecForDecoding(QTextCodec *codec); QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString string) const; + QByteArray encodeString(const QString &string) const; public slots: void setUser(const QString &user); diff --git a/src/common/main.cpp b/src/common/main.cpp index 378d8fe8..0209647a 100644 --- a/src/common/main.cpp +++ b/src/common/main.cpp @@ -93,7 +93,7 @@ int main(int argc, char **argv) { quasselTranslator.load(QString(":i18n/quassel_%1").arg(locale.name())); app.installTranslator(&quasselTranslator); - Network::setDefaultCodecForServer("UTF-8"); + Network::setDefaultCodecForServer("ISO-8859-15"); Network::setDefaultCodecForEncoding("UTF-8"); Network::setDefaultCodecForDecoding("ISO-8859-15"); diff --git a/src/common/network.cpp b/src/common/network.cpp index 99b647a2..05efa9c2 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -36,6 +36,7 @@ QTextCodec *Network::_defaultCodecForDecoding = 0; // Public: // ==================== Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(parent), + _proxy(0), _networkId(networkid), _identity(0), _myNick(QString()), @@ -45,7 +46,6 @@ Network::Network(const NetworkId &networkid, QObject *parent) : SyncableObject(p _connectionState(Disconnected), _prefixes(QString()), _prefixModes(QString()), - _proxy(0), _useRandomServer(false), _useAutoIdentify(false), _useAutoReconnect(false), @@ -296,7 +296,7 @@ IrcUser *Network::newIrcUser(const QString &hostmask) { } IrcUser *Network::newIrcUser(const QByteArray &hostmask) { - return newIrcUser(decodeString(hostmask)); + return newIrcUser(decodeServerString(hostmask)); } void Network::removeIrcUser(IrcUser *ircuser) { @@ -337,7 +337,7 @@ IrcUser *Network::ircUser(QString nickname) const { } IrcUser *Network::ircUser(const QByteArray &nickname) const { - return ircUser(decodeString(nickname)); + return ircUser(decodeServerString(nickname)); } QList Network::ircUsers() const { @@ -370,7 +370,7 @@ IrcChannel *Network::newIrcChannel(const QString &channelname) { } IrcChannel *Network::newIrcChannel(const QByteArray &channelname) { - return newIrcChannel(decodeString(channelname)); + return newIrcChannel(decodeServerString(channelname)); } IrcChannel *Network::ircChannel(QString channelname) const { @@ -382,7 +382,7 @@ IrcChannel *Network::ircChannel(QString channelname) const { } IrcChannel *Network::ircChannel(const QByteArray &channelname) const { - return ircChannel(decodeString(channelname)); + return ircChannel(decodeServerString(channelname)); } @@ -469,7 +469,7 @@ QString Network::decodeString(const QByteArray &text) const { else return ::decodeString(text, _defaultCodecForDecoding); } -QByteArray Network::encodeString(const QString string) const { +QByteArray Network::encodeString(const QString &string) const { if(_codecForEncoding) { return _codecForEncoding->fromUnicode(string); } @@ -479,6 +479,21 @@ QByteArray Network::encodeString(const QString string) const { return string.toAscii(); } +QString Network::decodeServerString(const QByteArray &text) const { + if(_codecForServer) return ::decodeString(text, _codecForServer); + else return ::decodeString(text, _defaultCodecForServer); +} + +QByteArray Network::encodeServerString(const QString &string) const { + if(_codecForServer) { + return _codecForServer->fromUnicode(string); + } + if(_defaultCodecForServer) { + return _defaultCodecForServer->fromUnicode(string); + } + return string.toAscii(); +} + // ==================== // Public Slots: // ==================== diff --git a/src/common/network.h b/src/common/network.h index 6c2ff403..a64fb088 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -141,7 +141,9 @@ public: void setCodecForDecoding(QTextCodec *codec); QString decodeString(const QByteArray &text) const; - QByteArray encodeString(const QString string) const; + QByteArray encodeString(const QString &string) const; + QString decodeServerString(const QByteArray &text) const; + QByteArray encodeServerString(const QString &string) const; static QByteArray defaultCodecForServer(); static QByteArray defaultCodecForEncoding(); @@ -262,6 +264,8 @@ signals: void disconnectRequested(NetworkId id = 0) const; private: + QPointer _proxy; + NetworkId _networkId; IdentityId _identity; @@ -292,7 +296,6 @@ private: bool _unlimitedReconnectRetries; bool _rejoinChannels; - QPointer _proxy; void determinePrefixes(); QTextCodec *_codecForServer; diff --git a/src/core/basichandler.cpp b/src/core/basichandler.cpp index 38205784..8288e10d 100644 --- a/src/core/basichandler.cpp +++ b/src/core/basichandler.cpp @@ -102,13 +102,13 @@ QStringList BasicHandler::serverDecode(const QList &stringlist) { return list; } -QString BasicHandler::bufferDecode(const QString &bufferName, const QByteArray &string) { - return networkConnection()->bufferDecode(bufferName, string); +QString BasicHandler::channelDecode(const QString &bufferName, const QByteArray &string) { + return networkConnection()->channelDecode(bufferName, string); } -QStringList BasicHandler::bufferDecode(const QString &bufferName, const QList &stringlist) { +QStringList BasicHandler::channelDecode(const QString &bufferName, const QList &stringlist) { QStringList list; - foreach(QByteArray s, stringlist) list << networkConnection()->bufferDecode(bufferName, s); + foreach(QByteArray s, stringlist) list << networkConnection()->channelDecode(bufferName, s); return list; } @@ -134,13 +134,13 @@ QList BasicHandler::serverEncode(const QStringList &stringlist) { return list; } -QByteArray BasicHandler::bufferEncode(const QString &bufferName, const QString &string) { - return networkConnection()->bufferEncode(bufferName, string); +QByteArray BasicHandler::channelEncode(const QString &bufferName, const QString &string) { + return networkConnection()->channelEncode(bufferName, string); } -QList BasicHandler::bufferEncode(const QString &bufferName, const QStringList &stringlist) { +QList BasicHandler::channelEncode(const QString &bufferName, const QStringList &stringlist) { QList list; - foreach(QString s, stringlist) list << networkConnection()->bufferEncode(bufferName, s); + foreach(QString s, stringlist) list << networkConnection()->channelEncode(bufferName, s); return list; } diff --git a/src/core/basichandler.h b/src/core/basichandler.h index a520087d..7af38942 100644 --- a/src/core/basichandler.h +++ b/src/core/basichandler.h @@ -42,15 +42,15 @@ public: QString serverDecode(const QByteArray &string); QStringList serverDecode(const QList &stringlist); - QString bufferDecode(const QString &bufferName, const QByteArray &string); - QStringList bufferDecode(const QString &bufferName, const QList &stringlist); + QString channelDecode(const QString &bufferName, const QByteArray &string); + QStringList channelDecode(const QString &bufferName, const QList &stringlist); QString userDecode(const QString &userNick, const QByteArray &string); QStringList userDecode(const QString &userNick, const QList &stringlist); QByteArray serverEncode(const QString &string); QList serverEncode(const QStringList &stringlist); - QByteArray bufferEncode(const QString &bufferName, const QString &string); - QList bufferEncode(const QString &bufferName, const QStringList &stringlist); + QByteArray channelEncode(const QString &bufferName, const QString &string); + QList channelEncode(const QString &bufferName, const QStringList &stringlist); QByteArray userEncode(const QString &userNick, const QString &string); QList userEncode(const QString &userNick, const QStringList &stringlist); diff --git a/src/core/ircserverhandler.cpp b/src/core/ircserverhandler.cpp index 4b848bd0..43c3126b 100644 --- a/src/core/ircserverhandler.cpp +++ b/src/core/ircserverhandler.cpp @@ -176,7 +176,7 @@ void IrcServerHandler::handleJoin(QString prefix, QList params) { void IrcServerHandler::handleKick(QString prefix, QList params) { network()->updateNickFromMask(prefix); - IrcUser *victim = network()->ircUser(serverDecode(params[1])); + IrcUser *victim = network()->ircUser(params[1]); QString channel = serverDecode(params[0]); Q_ASSERT(victim); @@ -184,7 +184,7 @@ void IrcServerHandler::handleKick(QString prefix, QList params) { QString msg; if(params.count() > 2) // someone got a reason! - msg = QString("%1 %2").arg(victim->nick()).arg(bufferDecode(channel, params[2])); + msg = QString("%1 %2").arg(victim->nick()).arg(channelDecode(channel, params[2])); else msg = victim->nick(); @@ -197,7 +197,7 @@ void IrcServerHandler::handleMode(QString prefix, QList params) { return; } - if(network()->isChannelName(params[0])) { + if(network()->isChannelName(serverDecode(params[0]))) { // Channel Modes emit displayMsg(Message::Mode, BufferInfo::ChannelBuffer, serverDecode(params[0]), serverDecode(params).join(" "), prefix); @@ -273,7 +273,7 @@ void IrcServerHandler::handleNotice(QString prefix, QList params) { ? nickFromMask(prefix) : prefix; - networkConnection()->ctcpHandler()->parse(Message::Notice, sender, target, userDecode(prefix, params[1])); + networkConnection()->ctcpHandler()->parse(Message::Notice, sender, target, userDecode(sender, params[1])); } void IrcServerHandler::handlePart(QString prefix, QList params) { @@ -329,7 +329,7 @@ void IrcServerHandler::handleQuit(QString prefix, QList params) { void IrcServerHandler::handleTopic(QString prefix, QList params) { IrcUser *ircuser = network()->updateNickFromMask(prefix); QString channel = serverDecode(params[0]); - QString topic = bufferDecode(channel, params[1]); + QString topic = channelDecode(channel, params[1]); Q_ASSERT(ircuser); network()->ircChannel(channel)->setTopic(topic); @@ -384,7 +384,7 @@ WHOWAS-Message: void IrcServerHandler::handle301(QString prefix, QList params) { Q_UNUSED(prefix); QString nickName = serverDecode(params[0]); - QString awayMessage = serverDecode(params.last()); + QString awayMessage = userDecode(nickName, params.last()); IrcUser *ircuser = network()->ircUser(nickName); if(ircuser) { @@ -463,8 +463,9 @@ void IrcServerHandler::handle315(QString prefix, QList params) { (real life: " :seconds idle, signon time) */ //TODO: parse real life message void IrcServerHandler::handle317(QString prefix, QList params) { - Q_UNUSED(prefix) - IrcUser *ircuser = network()->ircUser(serverDecode(params[0])); + Q_UNUSED(prefix); + QString nick = serverDecode(params[0]); + IrcUser *ircuser = network()->ircUser(nick); if(ircuser) { QDateTime now = QDateTime::currentDateTime(); int idleSecs = serverDecode(params[1]).toInt(); @@ -472,7 +473,7 @@ void IrcServerHandler::handle317(QString prefix, QList params) { ircuser->setIdleTime(now.addSecs(idleSecs)); emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("[Whois] %1 is idling for %2 seconds").arg(ircuser->nick()).arg(ircuser->idleTime().secsTo(now))); } else { - emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("[Whois] idle message: %1").arg(serverDecode(params).join(" "))); + emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("[Whois] idle message: %1").arg(userDecode(nick, params).join(" "))); } } @@ -501,7 +502,7 @@ void IrcServerHandler::handle331(QString prefix, QList params) { void IrcServerHandler::handle332(QString prefix, QList params) { Q_UNUSED(prefix); QString channel = serverDecode(params[0]); - QString topic = bufferDecode(channel, params[1]); + QString topic = channelDecode(channel, params[1]); network()->ircChannel(channel)->setTopic(topic); emit displayMsg(Message::Server, BufferInfo::ChannelBuffer, channel, tr("Topic for %1 is \"%2\"").arg(channel, topic)); } @@ -510,7 +511,8 @@ void IrcServerHandler::handle332(QString prefix, QList params) { void IrcServerHandler::handle333(QString prefix, QList params) { Q_UNUSED(prefix); QString channel = serverDecode(params[0]); - emit displayMsg(Message::Server, BufferInfo::ChannelBuffer, channel, tr("Topic set by %1 on %2") .arg(bufferDecode(channel, params[1]), QDateTime::fromTime_t(bufferDecode(channel, params[2]).toUInt()).toString())); + emit displayMsg(Message::Server, BufferInfo::ChannelBuffer, channel, + tr("Topic set by %1 on %2") .arg(serverDecode(params[1]), QDateTime::fromTime_t(channelDecode(channel, params[2]).toUInt()).toString())); } /* RPL_WHOREPLY: " diff --git a/src/core/networkconnection.cpp b/src/core/networkconnection.cpp index ed1a72b3..381e99d2 100644 --- a/src/core/networkconnection.cpp +++ b/src/core/networkconnection.cpp @@ -27,6 +27,7 @@ #include "core.h" #include "coresession.h" +#include "ircchannel.h" #include "ircuser.h" #include "network.h" #include "identity.h" @@ -109,12 +110,14 @@ CtcpHandler *NetworkConnection::ctcpHandler() const { } QString NetworkConnection::serverDecode(const QByteArray &string) const { - return network()->decodeString(string); + return network()->decodeServerString(string); } -QString NetworkConnection::bufferDecode(const QString &bufferName, const QByteArray &string) const { - Q_UNUSED(bufferName); - // TODO: Implement buffer-specific encodings +QString NetworkConnection::channelDecode(const QString &bufferName, const QByteArray &string) const { + if(!bufferName.isEmpty()) { + IrcChannel *channel = network()->ircChannel(bufferName); + if(channel) return channel->decodeString(string); + } return network()->decodeString(string); } @@ -125,12 +128,14 @@ QString NetworkConnection::userDecode(const QString &userNick, const QByteArray } QByteArray NetworkConnection::serverEncode(const QString &string) const { - return network()->encodeString(string); + return network()->encodeServerString(string); } -QByteArray NetworkConnection::bufferEncode(const QString &bufferName, const QString &string) const { - Q_UNUSED(bufferName); - // TODO: Implement buffer-specific encodings +QByteArray NetworkConnection::channelEncode(const QString &bufferName, const QString &string) const { + if(!bufferName.isEmpty()) { + IrcChannel *channel = network()->ircChannel(bufferName); + if(channel) return channel->encodeString(string); + } return network()->encodeString(string); } diff --git a/src/core/networkconnection.h b/src/core/networkconnection.h index a7aa1fd3..745afc77 100644 --- a/src/core/networkconnection.h +++ b/src/core/networkconnection.h @@ -65,19 +65,19 @@ public: //! 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 channel-specific encoding if one is set (and use the standard encoding else). + QString channelDecode(const QString &channelName, const QByteArray &string) const; - //! Decode a string using a IrcUser specific encoding, if one exists (using the server encoding else). + //! Decode a string using an IrcUser-specific encoding, if one exists (using the standaed 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 channel-specific encoding, if set, and use the standard encoding else. + QByteArray channelEncode(const QString &channelName, const QString &string) const; - //! Encode a string using the user-specific encoding, if set, and use the server encoding else. + //! Encode a string using the user-specific encoding, if set, and use the standard encoding else. QByteArray userEncode(const QString &userNick, const QString &string) const; public slots: diff --git a/src/core/userinputhandler.cpp b/src/core/userinputhandler.cpp index a431f3de..956e3524 100644 --- a/src/core/userinputhandler.cpp +++ b/src/core/userinputhandler.cpp @@ -63,7 +63,7 @@ void UserInputHandler::handleBan(const BufferInfo &bufferInfo, const QString &ms //TODO: find suitable default hostmask if msg gives only nickname // Example: MODE &oulu +b *!*@* - QByteArray banMsg = serverEncode(bufferInfo.bufferName()) + " +b " + bufferEncode(bufferInfo.bufferName(), msg); + QByteArray banMsg = serverEncode(bufferInfo.bufferName()) + " +b " + channelEncode(bufferInfo.bufferName(), msg); emit putCmd("MODE", banMsg); } @@ -126,7 +126,7 @@ void UserInputHandler::handleKick(const BufferInfo &bufferInfo, const QString &m QString reason = msg.section(' ', 1, -1, QString::SectionSkipEmpty).trimmed(); if(reason.isEmpty()) reason = networkConnection()->identity()->kickReason(); QList params; - params << serverEncode(bufferInfo.bufferName()) << serverEncode(nick) << bufferEncode(bufferInfo.bufferName(), reason); + params << serverEncode(bufferInfo.bufferName()) << serverEncode(nick) << channelEncode(bufferInfo.bufferName(), reason); emit putCmd("KICK", params); } @@ -138,13 +138,13 @@ void UserInputHandler::handleList(const BufferInfo &bufferInfo, const QString &m void UserInputHandler::handleMe(const BufferInfo &bufferInfo, const QString &msg) { if(bufferInfo.bufferName().isEmpty()) return; // server buffer - networkConnection()->ctcpHandler()->query(bufferInfo.bufferName(), "ACTION", bufferEncode(bufferInfo.bufferName(), msg)); + networkConnection()->ctcpHandler()->query(bufferInfo.bufferName(), "ACTION", channelEncode(bufferInfo.bufferName(), msg)); emit displayMsg(Message::Action, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick()); } void UserInputHandler::handleMode(const BufferInfo &bufferInfo, const QString &msg) { Q_UNUSED(bufferInfo) - // TODO handle correct encoding for buffer modes (bufferEncode()) + // TODO handle correct encoding for buffer modes (channelEncode()) emit putCmd("MODE", serverEncode(msg.split(' ', QString::SkipEmptyParts))); } @@ -177,7 +177,7 @@ void UserInputHandler::handleOp(const BufferInfo &bufferInfo, const QString &msg void UserInputHandler::handlePart(const BufferInfo &bufferInfo, const QString &msg) { QList params; - params << serverEncode(bufferInfo.bufferName()) << bufferEncode(bufferInfo.bufferName(), msg); + params << serverEncode(bufferInfo.bufferName()) << channelEncode(bufferInfo.bufferName(), msg); emit putCmd("PART", params); } @@ -206,7 +206,7 @@ void UserInputHandler::handleQuote(const BufferInfo &bufferInfo, const QString & void UserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString &msg) { if(bufferInfo.bufferName().isEmpty()) return; // server buffer QList params; - params << serverEncode(bufferInfo.bufferName()) << bufferEncode(bufferInfo.bufferName(), msg); + params << serverEncode(bufferInfo.bufferName()) << channelEncode(bufferInfo.bufferName(), msg); emit putCmd("PRIVMSG", params); emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self); } @@ -214,7 +214,7 @@ void UserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString &ms void UserInputHandler::handleTopic(const BufferInfo &bufferInfo, const QString &msg) { if(bufferInfo.bufferName().isEmpty()) return; QList params; - params << serverEncode(bufferInfo.bufferName()) << bufferEncode(bufferInfo.bufferName(), msg); + params << serverEncode(bufferInfo.bufferName()) << channelEncode(bufferInfo.bufferName(), msg); emit putCmd("TOPIC", params); } -- 2.20.1