Added a function decodeString() to util.{h|cpp} that takes a QByteArray with raw...
authorManuel Nickschas <sputnick@quassel-irc.org>
Fri, 6 Jul 2007 16:48:34 +0000 (16:48 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Fri, 6 Jul 2007 16:48:34 +0000 (16:48 +0000)
it using a specified text codec. Except the input data is utf8, in which case this function detects
utf8 and takes appropriate measures to get a correctly decoded QString regardless of the specified coded.

I'd like to use this function for decoding incoming server messages, but we need to change things quite
a bit in the Server to do this correctly. See my comment in server.cpp.

src/CMakeLists.txt
src/common/util.cpp
src/common/util.h
src/core/server.cpp
src/core/server.h
src/qtgui/mainwin.cpp

index 65a664b..7e0244f 100644 (file)
@@ -24,9 +24,9 @@ IF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_QTGUI)
   MESSAGE(FATAL_ERROR "\nYou have not selected which parts of Quassel I should build. Aborting.\nRun 'cmake <path> -DBUILD=<part>', where <part> contains one or more of 'core', 'gui' or 'monolithic', or 'all' to build everything.\n")
 ENDIF(NOT BUILD_MONO AND NOT BUILD_CORE AND NOT BUILD_QTGUI)
 
-IF(BUILD_CORE OR BUILD_QTGUI)
-  MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n")
-ENDIF(BUILD_CORE OR BUILD_QTGUI)
+#IF(BUILD_CORE OR BUILD_QTGUI)
+#  MESSAGE(FATAL_ERROR "\nBuilding of standalone core or GUI not supported at this time. Please check back later.\n")
+#ENDIF(BUILD_CORE OR BUILD_QTGUI)
 
 SET(CMAKE_BUILD_TYPE Debug)
 
index 2238cbe..675a735 100644 (file)
@@ -19,6 +19,8 @@
  ***************************************************************************/
 
 #include "util.h"
+#include <QDebug>
+#include <QTextCodec>
 
 QString nickFromMask(QString mask) {
   return mask.section('!', 0, 0);
@@ -40,6 +42,38 @@ bool isChannelName(QString str) {
   return QString("#&!+").contains(str[0]);
 }
 
+QString decodeString(QByteArray input, QString encoding) {
+  // 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
+  bool isUtf8 = true;
+  int cnt = 0;
+  for(int i = 0; i < input.size(); i++) {
+    if(cnt) {
+      if((input[i] & 0xc0) != 0x80) { isUtf8 = false; break; }  // Following byte does not start with 10
+      cnt--;
+      continue;
+    }
+    if(!(input[i] & 0x80)) continue; // 7 bit is ok
+    if((input[i] & 0xf8) == 0xf0) { cnt = 3; continue; }
+    if((input[i] & 0xf0) == 0xe0) { cnt = 2; continue; }
+    if((input[i] & 0xe0) == 0xc0) { cnt = 1; continue; }
+    isUtf8 = false; break;  // 8 bit char, but not utf8!
+  }
+  if(isUtf8 && cnt == 0) {
+    QString s = QString::fromUtf8(input);
+    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);
+  }
+  return codec->toUnicode(input);
+}
+
 void writeDataToDevice(QIODevice *dev, const QVariant &item) {
   QByteArray block;
   QDataStream out(&block, QIODevice::WriteOnly);
index 1a6d889..067bd76 100644 (file)
@@ -29,6 +29,15 @@ QString nickFromMask(QString mask);
 QString userFromMask(QString mask);
 QString hostFromMask(QString mask);
 
+//! 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
+ *  \return The decoded string.
+ */
+QString decodeString(QByteArray input, QString encoding = "ISO-8859-15");
+
 bool isChannelName(QString str);
 
 /**
index 39fcfb3..92fe804 100644 (file)
@@ -82,9 +82,9 @@ void Server::disconnectFromIrc(QString net) {
 
 void Server::socketHasData() {
   while(socket.canReadLine()) {
-    QString s = socket.readLine().trimmed();
+    QByteArray s = socket.readLine().trimmed();
     //qDebug() << "Read" << s;
-    emit recvRawServerMsg(s);
+    //emit recvRawServerMsg(s); // signal not needed, and we should make sure we consider encodings where we need them
     //Message *msg = Message::createFromServerString(this, s);
     handleServerMsg(s);
   }
@@ -158,13 +158,24 @@ void Server::putCmd(QString cmd, QStringList params, QString prefix) {
   socket.write(m.toAscii());
 }
 
-/** Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
-void Server::handleServerMsg(QString msg) {
+/*! Handle a raw message string sent by the server. We try to find a suitable handler, otherwise we call a default handler. */
+void Server::handleServerMsg(QByteArray rawmsg) {
   try {
-    if(msg.isEmpty()) {
+    if(rawmsg.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...
     QString prefix = "";
     QString cmd;
index 34a4514..0f9a1d7 100644 (file)
@@ -159,7 +159,7 @@ class Server : public QThread {
     QHash<QString, QString> topics; // stores topics for each buffer
     VarMap serverSupports;  // stores results from RPL_ISUPPORT
 
-    void handleServerMsg(QString rawMsg);
+    void handleServerMsg(QByteArray rawMsg);
     void handleUserInput(QString buffer, QString usrMsg);
 
     // CTCP Stuff
index fedf028..6b89e20 100644 (file)
@@ -31,8 +31,8 @@
 
 MainWin::MainWin(QtGui *_gui, QWidget *parent) : QMainWindow(parent), gui(_gui) {
   ui.setupUi(this);
-  setWindowTitle("Quassel IRC");
-  //setWindowTitle("Κυασελ Εγαρζη");
+  //setWindowTitle("Quassel IRC");
+  setWindowTitle(QString::fromUtf8("Κυασελ Εγαρζη"));
   setWindowIcon(QIcon(":/qirc-icon.png"));
   setWindowIconText("Quassel IRC");