Fixed and integrated SqliteStorage as new storage backend. This retires the old Backl...
authorManuel Nickschas <sputnick@quassel-irc.org>
Sun, 3 Jun 2007 14:21:01 +0000 (14:21 +0000)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 3 Jun 2007 14:21:01 +0000 (14:21 +0000)
SqliteStorage still needs some love though, and it does not yet have transactions.

Now that we have transitioned to Storage, we can tackle multi-user support in Core.

CMakeLists.txt
core/core.cpp
core/core.h
core/server.cpp
core/sqlitestorage.cpp

index 3634639..5a365e5 100644 (file)
@@ -42,7 +42,7 @@ INCLUDE_DIRECTORIES(${SDIRS} plugins)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
 # We need Qt4 support.
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
 # We need Qt4 support.
-SET(QT_MIN_VERSION "4.3.0")
+SET(QT_MIN_VERSION "4.3.0")  # 4.3 is required for SSL, crypto and some other stuff
 FIND_PACKAGE(Qt4 REQUIRED)
 
 # Set needed libraries
 FIND_PACKAGE(Qt4 REQUIRED)
 
 # Set needed libraries
index f9de45f..821ec2a 100644 (file)
@@ -23,6 +23,7 @@
 #include "global.h"
 #include "util.h"
 #include "coreproxy.h"
 #include "global.h"
 #include "util.h"
 #include "coreproxy.h"
+#include "sqlitestorage.h"
 
 #include <QtSql>
 #include <QSettings>
 
 #include <QtSql>
 #include <QSettings>
 Core::Core() {
   if(core) qFatal("Trying to instantiate more than one Core object!");
 
 Core::Core() {
   if(core) qFatal("Trying to instantiate more than one Core object!");
 
+  if(!SqliteStorage::isAvailable()) {
+    qFatal("Sqlite is currently required! Please make sure your Qt library has sqlite support enabled.");
+  }
+  //SqliteStorage::init();
+  storage = new SqliteStorage();
+  user = storage->validateUser("Default", "password");
+  if(!user) user = storage->addUser("Default", "password");
+  Q_ASSERT(user);
+
   connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
   connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
   connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGUI(BufferId, QString)));
   connect(coreProxy, SIGNAL(requestServerStates()), this, SIGNAL(serverStateRequested()));
   connect(coreProxy, SIGNAL(gsRequestConnect(QStringList)), this, SLOT(connectToIrc(QStringList)));
   connect(coreProxy, SIGNAL(gsUserInput(BufferId, QString)), this, SLOT(msgFromGUI(BufferId, QString)));
-  connect(coreProxy, SIGNAL(gsImportBacklog()), &backlog, SLOT(importOldBacklog()));
+  connect(coreProxy, SIGNAL(gsImportBacklog()), storage, SLOT(importOldBacklog()));
   connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
   connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
   connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
   connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
   connect(coreProxy, SIGNAL(gsRequestBacklog(BufferId, QVariant, QVariant)), this, SLOT(sendBacklog(BufferId, QVariant, QVariant)));
   connect(this, SIGNAL(displayMsg(Message)), coreProxy, SLOT(csDisplayMsg(Message)));
   connect(this, SIGNAL(displayStatusMsg(QString, QString)), coreProxy, SLOT(csDisplayStatusMsg(QString, QString)));
   connect(this, SIGNAL(backlogData(BufferId, QList<QVariant>, bool)), coreProxy, SLOT(csBacklogData(BufferId, QList<QVariant>, bool)));
-  connect(&backlog, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
+  connect(storage, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
   connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
   // Read global settings from config file
   QSettings s;
   connect(this, SIGNAL(bufferIdUpdated(BufferId)), coreProxy, SLOT(csUpdateBufferId(BufferId)));
   // Read global settings from config file
   QSettings s;
@@ -47,7 +57,7 @@ Core::Core() {
   foreach(key, s.childKeys()) {
     global->updateData(key, s.value(key));
   }
   foreach(key, s.childKeys()) {
     global->updateData(key, s.value(key));
   }
-  backlog.init("Default"); // FIXME
+
   global->updateData("CoreReady", true);
   // Now that we are in sync, we can connect signals to automatically store further updates.
   // I don't think we care if global data changed locally or if it was updated by a client. 
   global->updateData("CoreReady", true);
   // Now that we are in sync, we can connect signals to automatically store further updates.
   // I don't think we care if global data changed locally or if it was updated by a client. 
@@ -60,6 +70,7 @@ Core::~Core() {
   //foreach(Server *s, servers) {
   //  delete s;
   //}
   //foreach(Server *s, servers) {
   //  delete s;
   //}
+  delete storage;
 }
 
 void Core::globalDataUpdated(QString key) {
 }
 
 void Core::globalDataUpdated(QString key) {
@@ -119,22 +130,15 @@ void Core::recvMessageFromServer(Message::Type type, QString target, QString tex
   Q_ASSERT(s);
   BufferId buf;
   if((flags & Message::PrivMsg) && !(flags & Message::Self)) {
   Q_ASSERT(s);
   BufferId buf;
   if((flags & Message::PrivMsg) && !(flags & Message::Self)) {
-    buf = backlog.getBufferId(s->getNetwork(), nickFromMask(sender));
+    buf = storage->getBufferId(user, s->getNetwork(), nickFromMask(sender));
   } else {
   } else {
-    buf = backlog.getBufferId(s->getNetwork(), target);
+    buf = storage->getBufferId(user, s->getNetwork(), target);
   }
   Message msg(buf, type, text, sender, flags);
   }
   Message msg(buf, type, text, sender, flags);
-  msg.msgId = backlog.logMessage(msg);
+  msg.msgId = storage->logMessage(msg); //qDebug() << msg.msgId;
+  Q_ASSERT(msg.msgId);
   emit displayMsg(msg);
 }
   emit displayMsg(msg);
 }
-/*
-void Core::recvMessageFromServer(Message msg) {
-  Server *s = qobject_cast<Server*>(sender());
-  Q_ASSERT(s);
-  logMessage(s->getNetwork(), msg);
-  emit displayMsg(s->getNetwork(), msg);
-}
-*/
 
 void Core::recvStatusMsgFromServer(QString msg) {
   Server *s = qobject_cast<Server*>(sender());
 
 void Core::recvStatusMsgFromServer(QString msg) {
   Server *s = qobject_cast<Server*>(sender());
@@ -143,7 +147,7 @@ void Core::recvStatusMsgFromServer(QString msg) {
 }
 
 QList<BufferId> Core::getBuffers() {
 }
 
 QList<BufferId> Core::getBuffers() {
-  return backlog.requestBuffers();
+  return storage->requestBuffers(user);
 }
 
 void Core::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
 }
 
 void Core::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
@@ -153,7 +157,7 @@ void Core::sendBacklog(BufferId id, QVariant v1, QVariant v2) {
 
 
   } else {
 
 
   } else {
-    msglist = backlog.requestMsgs(id, v1.toInt(), v2.toInt());
+    msglist = storage->requestMsgs(id, v1.toInt(), v2.toInt());
   }
 
   // Send messages out in smaller packages - we don't want to make the signal data too large!
   }
 
   // Send messages out in smaller packages - we don't want to make the signal data too large!
index 459c684..a90a8f6 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "server.h"
 #include "backlog.h"
 
 #include "server.h"
 #include "backlog.h"
+#include "storage.h"
 #include "global.h"
 
 class Core : public QObject {
 #include "global.h"
 
 class Core : public QObject {
@@ -37,7 +38,6 @@ class Core : public QObject {
 
     Core();
     ~Core();
 
     Core();
     ~Core();
-    QHash<QString, QList<Message> > getBackLog() { return QHash<QString, QList<Message> >()/*backLog*/; }; // FIXME
     QList<BufferId> getBuffers();
 
   public slots:
     QList<BufferId> getBuffers();
 
   public slots:
@@ -59,32 +59,15 @@ class Core : public QObject {
     void bufferIdUpdated(BufferId);
 
   private slots:
     void bufferIdUpdated(BufferId);
 
   private slots:
-    //void serverStatesRequested();
     void globalDataUpdated(QString);
     void recvStatusMsgFromServer(QString msg);
     void globalDataUpdated(QString);
     void recvStatusMsgFromServer(QString msg);
-    //void recvMessageFromServer(Message msg);
     void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
     void serverDisconnected(QString net);
 
   private:
     void recvMessageFromServer(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
     void serverDisconnected(QString net);
 
   private:
-    Backlog backlog;
-    QDir backLogDir;
-    bool backLogEnabled;
+    Storage *storage;
     QHash<QString, Server *> servers;
     QHash<QString, Server *> servers;
-    //QHash<QString, QList<Message> > backLog;
-    //QHash<QString, int> netIdx;
-    //QHash<QString, QFile *> logFiles;
-    //QHash<QString, QDataStream *> logStreams;
-    //QHash<QString, QDate> logFileDates;
-    //QHash<QString, QDir> logFileDirs;
-
-    //QSqlDatabase logDb;
-
-    //uint getNetIdx(QString net);
-    //void initBackLog();
-    //void initBackLogOld();
-    //void logMessage(QString, Message);
-    //void logMessageOld(QString, Message);
+    UserId user;
 
 };
 
 
 };
 
index f527226..f7d7916 100644 (file)
@@ -870,7 +870,7 @@ void Server::handleCtcpAction(CtcpType ctcptype, QString prefix, QString target,
 void Server::handleCtcpPing(CtcpType ctcptype, QString prefix, QString target, QString param) {
   if(ctcptype == CtcpQuery) {
     ctcpReply(nickFromMask(prefix), "PING", param);
 void Server::handleCtcpPing(CtcpType ctcptype, QString prefix, QString target, QString param) {
   if(ctcptype == CtcpQuery) {
     ctcpReply(nickFromMask(prefix), "PING", param);
-    emit displayMsg(Message::Plain, "", tr("Received CTCP PING request by %1").arg(prefix));
+    emit displayMsg(Message::Server, "", tr("Received CTCP PING request by %1").arg(prefix));
   } else {
     // display ping answer
   }
   } else {
     // display ping answer
   }
@@ -880,7 +880,7 @@ void Server::handleCtcpVersion(CtcpType ctcptype, QString prefix, QString target
   if(ctcptype == CtcpQuery) {
     // FIXME use real Info about quassel :)
     ctcpReply(nickFromMask(prefix), "VERSION", QString("Quassel:pre Release:*nix"));
   if(ctcptype == CtcpQuery) {
     // FIXME use real Info about quassel :)
     ctcpReply(nickFromMask(prefix), "VERSION", QString("Quassel:pre Release:*nix"));
-    emit displayMsg(Message::Plain, "", tr("Received CTCP VERSION request by %1").arg(prefix));
+    emit displayMsg(Message::Server, "", tr("Received CTCP VERSION request by %1").arg(prefix));
   } else {
     // TODO display Version answer
   }
   } else {
     // TODO display Version answer
   }
index ba07cbe..9b6f88d 100644 (file)
@@ -23,7 +23,7 @@
 
 SqliteStorage::SqliteStorage() {
   // TODO I don't think that this path is failsafe for windows users :) 
 
 SqliteStorage::SqliteStorage() {
   // TODO I don't think that this path is failsafe for windows users :) 
-  QString backlogFile = Global::quasselDir + "/quassel-backlog-newstyle.sqlite";
+  QString backlogFile = Global::quasselDir + "/quassel-storage.sqlite";
   logDb = QSqlDatabase::addDatabase("QSQLITE");
   logDb.setDatabaseName(backlogFile);
   bool ok = logDb.open();
   logDb = QSqlDatabase::addDatabase("QSQLITE");
   logDb.setDatabaseName(backlogFile);
   bool ok = logDb.open();
@@ -34,82 +34,86 @@ SqliteStorage::SqliteStorage() {
     Q_ASSERT(ok);
     return;
   }
     Q_ASSERT(ok);
     return;
   }
-  
+
+  /*
+  NO, we should not start a transaction to check if transactions are supported :-)
   if(!logDb.transaction()) {
     qWarning(tr("Database driver does not support transactions. This might lead to a corrupt database!").toAscii());
   }
   if(!logDb.transaction()) {
     qWarning(tr("Database driver does not support transactions. This might lead to a corrupt database!").toAscii());
   }
-  
+  */
+
   // check if the db schema is up to date
   QSqlQuery query = logDb.exec("SELECT MAX(version) FROM coreinfo");
   if(query.first()) {
   // check if the db schema is up to date
   QSqlQuery query = logDb.exec("SELECT MAX(version) FROM coreinfo");
   if(query.first()) {
-    // TOTO VersionCheck
+    // TODO VersionCheck
     //checkVersion(query.value(0));
     qDebug() << "Sqlite is ready. Quassel Schema Version:" << query.value(0).toUInt();
   } else {
     initDb();
   }
     //checkVersion(query.value(0));
     qDebug() << "Sqlite is ready. Quassel Schema Version:" << query.value(0).toUInt();
   } else {
     initDb();
   }
-  
+
   // we will need those pretty often... so let's speed things up:
   // we will need those pretty often... so let's speed things up:
-  createBufferQuery = new QSqlQuery();
+  createBufferQuery = new QSqlQuery(logDb);
   createBufferQuery->prepare("INSERT INTO buffer (userid, networkid, buffername) VALUES (:userid, (SELECT networkid FROM network WHERE networkname = :networkname), :buffername)");
   createBufferQuery->prepare("INSERT INTO buffer (userid, networkid, buffername) VALUES (:userid, (SELECT networkid FROM network WHERE networkname = :networkname), :buffername)");
-  
-  createNetworkQuery = new QSqlQuery();
+
+  createNetworkQuery = new QSqlQuery(logDb);
   createNetworkQuery->prepare("INSERT INTO network (userid, networkname) VALUES (:userid, :networkname)");
   createNetworkQuery->prepare("INSERT INTO network (userid, networkname) VALUES (:userid, :networkname)");
-  
-  getBufferIdQuery = new QSqlQuery();
+
+  getBufferIdQuery = new QSqlQuery(logDb);
   getBufferIdQuery->prepare("SELECT bufferid FROM buffer "
                             "JOIN network ON buffer.networkid = network.networkid "
   getBufferIdQuery->prepare("SELECT bufferid FROM buffer "
                             "JOIN network ON buffer.networkid = network.networkid "
-                            "WHERE network.networkname = :networkname AND buffer.userid = :userid AND buffer.buffername = :buffername");
+                            "WHERE network.networkname = :networkname AND buffer.userid = :userid AND buffer.buffername = :buffername "
+                            "LIMIT 1");
 
 
-  
-  logMessageQuery = new QSqlQuery();
+
+  logMessageQuery = new QSqlQuery(logDb);
   logMessageQuery->prepare("INSERT INTO backlog (time, bufferid, type, flags, senderid, message) "
                            "VALUES (:time, :bufferid, :type, :flags, (SELECT senderid FROM sender WHERE sender = :sender), :message)");
   logMessageQuery->prepare("INSERT INTO backlog (time, bufferid, type, flags, senderid, message) "
                            "VALUES (:time, :bufferid, :type, :flags, (SELECT senderid FROM sender WHERE sender = :sender), :message)");
-  
-  addSenderQuery = new QSqlQuery();
+
+  addSenderQuery = new QSqlQuery(logDb);
   addSenderQuery->prepare("INSERT INTO sender (sender) VALUES (:sender)");
 
   addSenderQuery->prepare("INSERT INTO sender (sender) VALUES (:sender)");
 
-  getLastMessageIdQuery = new QSqlQuery();
+  getLastMessageIdQuery = new QSqlQuery(logDb);
   getLastMessageIdQuery->prepare("SELECT messageid FROM backlog "
                                  "WHERE time = :time AND bufferid = :bufferid AND type = :type AND senderid = (SELECT senderid FROM sender WHERE sender = :sender)");
 
   getLastMessageIdQuery->prepare("SELECT messageid FROM backlog "
                                  "WHERE time = :time AND bufferid = :bufferid AND type = :type AND senderid = (SELECT senderid FROM sender WHERE sender = :sender)");
 
-  requestMsgsOffsetQuery = new QSqlQuery();
+  requestMsgsOffsetQuery = new QSqlQuery(logDb);
   requestMsgsOffsetQuery->prepare("SELECT count(*) FROM backlog WHERE bufferid = :bufferid AND messageid < :messageid");
   requestMsgsOffsetQuery->prepare("SELECT count(*) FROM backlog WHERE bufferid = :bufferid AND messageid < :messageid");
-  
-  requestMsgsQuery = new QSqlQuery();
+
+  requestMsgsQuery = new QSqlQuery(logDb);
   requestMsgsQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                             "FROM backlog "
                             "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                             "JOIN sender ON backlog.senderid = sender.senderid "
                             "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
   requestMsgsQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                             "FROM backlog "
                             "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                             "JOIN sender ON backlog.senderid = sender.senderid "
                             "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
-                            "WHERE buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid) "
+                            "WHERE buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid2) "
                             "ORDER BY messageid DESC "
                             "LIMIT :limit OFFSET :offset");
                             "ORDER BY messageid DESC "
                             "LIMIT :limit OFFSET :offset");
-  
-  requestMsgsSinceOffsetQuery = new QSqlQuery();
+
+  requestMsgsSinceOffsetQuery = new QSqlQuery(logDb);
   requestMsgsSinceOffsetQuery->prepare("SELECT count(*) FROM backlog WHERE bufferid = :bufferid AND time >= :since");
   requestMsgsSinceOffsetQuery->prepare("SELECT count(*) FROM backlog WHERE bufferid = :bufferid AND time >= :since");
-  
-  requestMsgsSinceQuery = new QSqlQuery();
+
+  requestMsgsSinceQuery = new QSqlQuery(logDb);
   requestMsgsSinceQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                                  "FROM backlog "
                                  "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                                  "JOIN sender ON backlog.senderid = sender.senderid "
                                  "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
   requestMsgsSinceQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                                  "FROM backlog "
                                  "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                                  "JOIN sender ON backlog.senderid = sender.senderid "
                                  "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
-                                 "WHERE (buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid)) AND "
+                                 "WHERE (buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid2)) AND "
                                  "backlog.time >= :since "
                                  "ORDER BY messageid DESC "
                                  "LIMIT -1 OFFSET :offset");
                                  "backlog.time >= :since "
                                  "ORDER BY messageid DESC "
                                  "LIMIT -1 OFFSET :offset");
-  
-  requestMsgRangeQuery = new QSqlQuery();
+
+  requestMsgRangeQuery = new QSqlQuery(logDb);
   requestMsgRangeQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                                 "FROM backlog "
                                 "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                                 "JOIN sender ON backlog.senderid = sender.senderid "
                                 "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
   requestMsgRangeQuery->prepare("SELECT messageid, time,  type, flags, sender, message, displayname "
                                 "FROM backlog "
                                 "JOIN buffer ON backlog.bufferid = buffer.bufferid "
                                 "JOIN sender ON backlog.senderid = sender.senderid "
                                 "LEFT JOIN buffergroup ON buffer.groupid = buffergroup.groupid "
-                                "WHERE (buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid)) AND "
+                                "WHERE (buffer.bufferid = :bufferid OR buffer.groupid = (SELECT groupid FROM buffer WHERE bufferid = :bufferid2)) AND "
                                 "backlog.messageid >= :firstmsg AND backlog.messageid <= :lastmsg "
                                 "ORDER BY messageid DESC ");
                                 "backlog.messageid >= :firstmsg AND backlog.messageid <= :lastmsg "
                                 "ORDER BY messageid DESC ");
-  
+
 }
 
 SqliteStorage::~SqliteStorage() {
 }
 
 SqliteStorage::~SqliteStorage() {
@@ -125,10 +129,12 @@ SqliteStorage::~SqliteStorage() {
   delete createBufferQuery;
   delete getBufferIdQuery;
   logDb.close();
   delete createBufferQuery;
   delete getBufferIdQuery;
   logDb.close();
+  //qDebug() << logDb.lastError().text();
 }
 
 
 void SqliteStorage::initDb() {
 }
 
 
 void SqliteStorage::initDb() {
+  //logDb.transaction();
   logDb.exec("CREATE TABLE quasseluser ("
              "userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
              "username TEXT UNIQUE NOT NULL,"
   logDb.exec("CREATE TABLE quasseluser ("
              "userid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
              "username TEXT UNIQUE NOT NULL,"
@@ -187,29 +193,31 @@ void SqliteStorage::initDb() {
 }
 
 bool SqliteStorage::isAvailable() {
 }
 
 bool SqliteStorage::isAvailable() {
-  // oh yes we're available... at least I do hope so :)
+  if(!QSqlDatabase::isDriverAvailable("QSQLITE")) return false;
   return true;
 }
 
 QString SqliteStorage::displayName() {
   return true;
 }
 
 QString SqliteStorage::displayName() {
-  // I think the class name is a got start here
+  // I think the class name is a good start here
   return QString("SqliteStorage");
 }
 
 UserId SqliteStorage::addUser(QString user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
   return QString("SqliteStorage");
 }
 
 UserId SqliteStorage::addUser(QString user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
-  
+
+  //logDb.transaction();
   QSqlQuery query(logDb);
   query.prepare("INSERT INTO quasseluser (username, password) VALUES (:username, :password)");
   query.bindValue(":username", user);
   query.bindValue(":password", cryptopass);
   query.exec();
   if(query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error...
   QSqlQuery query(logDb);
   query.prepare("INSERT INTO quasseluser (username, password) VALUES (:username, :password)");
   query.bindValue(":username", user);
   query.bindValue(":password", cryptopass);
   query.exec();
   if(query.lastError().isValid() && query.lastError().number() == 19) { // user already exists - sadly 19 seems to be the general constraint violation error...
+    logDb.rollback();
     return 0;
   } 
   logDb.commit();
     return 0;
   } 
   logDb.commit();
-  
+
   query.prepare("SELECT userid FROM quasseluser WHERE username = :username");
   query.bindValue(":username", user);
   query.exec();
   query.prepare("SELECT userid FROM quasseluser WHERE username = :username");
   query.bindValue(":username", user);
   query.exec();
@@ -220,7 +228,8 @@ UserId SqliteStorage::addUser(QString user, QString password) {
 void SqliteStorage::updateUser(UserId user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
 void SqliteStorage::updateUser(UserId user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
-  
+
+  //logDb.transaction();
   QSqlQuery query(logDb);
   query.prepare("UPDATE quasseluser SET password = :password WHERE userid = :userid");
   query.bindValue(":userid", user);
   QSqlQuery query(logDb);
   query.prepare("UPDATE quasseluser SET password = :password WHERE userid = :userid");
   query.bindValue(":userid", user);
@@ -232,7 +241,7 @@ void SqliteStorage::updateUser(UserId user, QString password) {
 UserId SqliteStorage::validateUser(QString user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
 UserId SqliteStorage::validateUser(QString user, QString password) {
   QByteArray cryptopass = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha1);
   cryptopass = cryptopass.toHex();
-  
+
   QSqlQuery query(logDb);
   query.prepare("SELECT userid FROM quasseluser WHERE username = :username AND password = :password");
   query.bindValue(":username", user);
   QSqlQuery query(logDb);
   query.prepare("SELECT userid FROM quasseluser WHERE username = :username AND password = :password");
   query.bindValue(":username", user);
@@ -244,11 +253,12 @@ UserId SqliteStorage::validateUser(QString user, QString password) {
   } else {
     return 0;
   }
   } else {
     return 0;
   }
-  
 }
 
 void SqliteStorage::delUser(UserId user) {
 }
 
 void SqliteStorage::delUser(UserId user) {
+  //logDb.transaction();
   QSqlQuery query(logDb);
   QSqlQuery query(logDb);
+  // FIXME: backlog has no userid, it's in bufferid
   query.prepare("DELETE FROM backlog WHERE userid = :userid");
   query.bindValue(":userid", user);
   query.exec();
   query.prepare("DELETE FROM backlog WHERE userid = :userid");
   query.bindValue(":userid", user);
   query.exec();
@@ -269,60 +279,89 @@ void SqliteStorage::delUser(UserId user) {
 }
 
 void SqliteStorage::createBuffer(UserId user, QString network, QString buffer) {
 }
 
 void SqliteStorage::createBuffer(UserId user, QString network, QString buffer) {
-  qDebug() << "creating buffer:" << user << network << buffer;
+  //qDebug() << "creating buffer:" << user << network << buffer;
+  //logDb.transaction();
   createBufferQuery->bindValue(":userid", user);
   createBufferQuery->bindValue(":networkname", network);
   createBufferQuery->bindValue(":buffername", buffer);
   createBufferQuery->exec();
   createBufferQuery->bindValue(":userid", user);
   createBufferQuery->bindValue(":networkname", network);
   createBufferQuery->bindValue(":buffername", buffer);
   createBufferQuery->exec();
-  
+
   if(createBufferQuery->lastError().isValid()) {
     if(createBufferQuery->lastError().number() == 19) { // Null Constraint violation
       createNetworkQuery->bindValue(":userid", user);
       createNetworkQuery->bindValue(":networkname", network);
       createNetworkQuery->exec();
       createBufferQuery->exec();
   if(createBufferQuery->lastError().isValid()) {
     if(createBufferQuery->lastError().number() == 19) { // Null Constraint violation
       createNetworkQuery->bindValue(":userid", user);
       createNetworkQuery->bindValue(":networkname", network);
       createNetworkQuery->exec();
       createBufferQuery->exec();
+      //qDebug() << "net" << createNetworkQuery->lastError().text();
+      //qDebug() << "buf" << createBufferQuery->lastError().text();
       Q_ASSERT(!createNetworkQuery->lastError().isValid());
       Q_ASSERT(!createBufferQuery->lastError().isValid());
     } else {
       // do panic!
       qDebug() << "failed to create Buffer: ErrNo:" << createBufferQuery->lastError().number() << "ErrMsg:" << createBufferQuery->lastError().text();
       Q_ASSERT(!createNetworkQuery->lastError().isValid());
       Q_ASSERT(!createBufferQuery->lastError().isValid());
     } else {
       // do panic!
       qDebug() << "failed to create Buffer: ErrNo:" << createBufferQuery->lastError().number() << "ErrMsg:" << createBufferQuery->lastError().text();
+      Q_ASSERT(false);
     }
   }
   logDb.commit();
 }
 
 BufferId SqliteStorage::getBufferId(UserId user, QString network, QString buffer) {
     }
   }
   logDb.commit();
 }
 
 BufferId SqliteStorage::getBufferId(UserId user, QString network, QString buffer) {
+  if(buffer == "") buffer = "$$$";  // FIXME
+
+  QSqlQuery *getBufferIdQuery = new QSqlQuery(logDb);
+  getBufferIdQuery->prepare("SELECT bufferid FROM buffer "
+      "JOIN network ON buffer.networkid = network.networkid "
+      "WHERE network.networkname = :networkname AND buffer.userid = :userid AND buffer.buffername = :buffername "
+      "LIMIT 1");
+
   getBufferIdQuery->bindValue(":networkname", network);
   getBufferIdQuery->bindValue(":userid", user);
   getBufferIdQuery->bindValue(":buffername", buffer);
   getBufferIdQuery->exec();
 
   getBufferIdQuery->bindValue(":networkname", network);
   getBufferIdQuery->bindValue(":userid", user);
   getBufferIdQuery->bindValue(":buffername", buffer);
   getBufferIdQuery->exec();
 
+  bool flg = false;
   if(!getBufferIdQuery->first()) {
     createBuffer(user, network, buffer);
     getBufferIdQuery->exec();
   if(!getBufferIdQuery->first()) {
     createBuffer(user, network, buffer);
     getBufferIdQuery->exec();
-    Q_ASSERT(getBufferIdQuery->first());
+    flg = getBufferIdQuery->first();
+    Q_ASSERT(flg);
   }
   }
-  
-  return BufferId(getBufferIdQuery->value(0).toUInt(), network, buffer);
+  if(buffer == "$$$") buffer = "";
+  BufferId result = BufferId(getBufferIdQuery->value(0).toUInt(), network, buffer);
+  //getBufferIdQuery->clear(); // this is active for some reason, which wrecks havoc with later transactions
+  getBufferIdQuery->last();
+  //qDebug() << "active" << getBufferIdQuery->isActive();
+  if(flg) emit bufferIdUpdated(result);
+  delete getBufferIdQuery;
+  return result;
 }
 
 QList<BufferId> SqliteStorage::requestBuffers(UserId user, QDateTime since) {
   QList<BufferId> bufferlist;
   QSqlQuery query(logDb);
 }
 
 QList<BufferId> SqliteStorage::requestBuffers(UserId user, QDateTime since) {
   QList<BufferId> bufferlist;
   QSqlQuery query(logDb);
-  query.prepare("SELECT bufferid, networkname, buffername FROM buffer "
+  // FIXME: fix query (and make it run in sane time)
+  query.prepare("SELECT buffer.bufferid, networkname, buffername FROM buffer "
+                //"JOIN buffer ON buffer.bufferid = backlog.bufferid "
                 "JOIN network ON buffer.networkid = network.networkid "
                 "JOIN network ON buffer.networkid = network.networkid "
-                "JOIN backlog ON buffer.bufferid = backlog.bufferid "
-                "WHERE buffer.userid = :userid AND time >= :time");
-  query.bindValue(":userid", user);
-  query.bindValue(":time", since.toTime_t());
+                //"JOIN backlog ON buffer.bufferid = backlog.bufferid "
+                "WHERE buffer.userid = 1");// AND time >= 0");
+  //query.bindValue(":userid", user);
+  //if(since.isValid()) query.bindValue(":time", since.toTime_t());
+  //else query.bindValue(":time",0);
+  //qDebug() << query.boundValues();
   query.exec();
   query.exec();
+  //qDebug() << query.lastError().text();
   while(query.next()) {
   while(query.next()) {
-    bufferlist << BufferId(query.value(0).toUInt(), query.value(1).toString(), query.value(2).toString());
+    QString buf = query.value(2).toString();
+    if(buf == "$$$") buf = "";
+    bufferlist << BufferId(query.value(0).toUInt(), query.value(1).toString(), buf);
   }
   return bufferlist;
 }
 
 MsgId SqliteStorage::logMessage(Message msg) {
   }
   return bufferlist;
 }
 
 MsgId SqliteStorage::logMessage(Message msg) {
+  if(msg.sender == "") msg.sender = "$$$";  // FIXME handle empty sender strings in a sane way
+  //logDb.transaction();
   logMessageQuery->bindValue(":time", msg.timeStamp.toTime_t());
   logMessageQuery->bindValue(":bufferid", msg.buffer.uid());
   logMessageQuery->bindValue(":type", msg.type);
   logMessageQuery->bindValue(":time", msg.timeStamp.toTime_t());
   logMessageQuery->bindValue(":bufferid", msg.buffer.uid());
   logMessageQuery->bindValue(":type", msg.type);
@@ -330,8 +369,7 @@ MsgId SqliteStorage::logMessage(Message msg) {
   logMessageQuery->bindValue(":sender", msg.sender);
   logMessageQuery->bindValue(":message", msg.text);
   logMessageQuery->exec();
   logMessageQuery->bindValue(":sender", msg.sender);
   logMessageQuery->bindValue(":message", msg.text);
   logMessageQuery->exec();
-
-  // constraint violation - must be NOT NULL constraint - probably the sender is missing... 
+  // constraint violation - must be NOT NULL constraint - probably the sender is missing...
   if(logMessageQuery->lastError().isValid()) {
     if(logMessageQuery->lastError().number() == 19) { 
       addSenderQuery->bindValue(":sender", msg.sender);
   if(logMessageQuery->lastError().isValid()) {
     if(logMessageQuery->lastError().number() == 19) { 
       addSenderQuery->bindValue(":sender", msg.sender);
@@ -343,16 +381,18 @@ MsgId SqliteStorage::logMessage(Message msg) {
   }
 
   logDb.commit();
   }
 
   logDb.commit();
-  
+
   getLastMessageIdQuery->bindValue(":time", msg.timeStamp.toTime_t());
   getLastMessageIdQuery->bindValue(":bufferid", msg.buffer.uid());
   getLastMessageIdQuery->bindValue(":type", msg.type);
   getLastMessageIdQuery->bindValue(":sender", msg.sender);
   getLastMessageIdQuery->exec();
   getLastMessageIdQuery->bindValue(":time", msg.timeStamp.toTime_t());
   getLastMessageIdQuery->bindValue(":bufferid", msg.buffer.uid());
   getLastMessageIdQuery->bindValue(":type", msg.type);
   getLastMessageIdQuery->bindValue(":sender", msg.sender);
   getLastMessageIdQuery->exec();
-  
+
   if(getLastMessageIdQuery->first()) {
     return getLastMessageIdQuery->value(0).toUInt();
   } else { // somethin went wrong... :(
   if(getLastMessageIdQuery->first()) {
     return getLastMessageIdQuery->value(0).toUInt();
   } else { // somethin went wrong... :(
+    qDebug() << getLastMessageIdQuery->lastQuery();
+    Q_ASSERT(false);
     return 0;
   }
 }
     return 0;
   }
 }
@@ -365,13 +405,13 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, int lastmsgs, int off
   requestMsgsOffsetQuery->exec();
   requestMsgsOffsetQuery->first();
   offset = requestMsgsOffsetQuery->value(0).toUInt();
   requestMsgsOffsetQuery->exec();
   requestMsgsOffsetQuery->first();
   offset = requestMsgsOffsetQuery->value(0).toUInt();
-  
+
   // now let's select the messages
   requestMsgsQuery->bindValue(":bufferid", buffer.uid());
   // now let's select the messages
   requestMsgsQuery->bindValue(":bufferid", buffer.uid());
+  requestMsgsQuery->bindValue(":bufferid2", buffer.uid());  // Qt can't handle the same placeholder used twice
   requestMsgsQuery->bindValue(":limit", lastmsgs);
   requestMsgsQuery->bindValue(":offset", offset);
   requestMsgsQuery->exec();
   requestMsgsQuery->bindValue(":limit", lastmsgs);
   requestMsgsQuery->bindValue(":offset", offset);
   requestMsgsQuery->exec();
-  
   while(requestMsgsQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgsQuery->value(1).toInt()),
                 buffer,
   while(requestMsgsQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgsQuery->value(1).toInt()),
                 buffer,
@@ -380,9 +420,10 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, int lastmsgs, int off
                 requestMsgsQuery->value(4).toString(),
                 requestMsgsQuery->value(3).toUInt());
     msg.msgId = requestMsgsQuery->value(0).toUInt();
                 requestMsgsQuery->value(4).toString(),
                 requestMsgsQuery->value(3).toUInt());
     msg.msgId = requestMsgsQuery->value(0).toUInt();
+    if(msg.sender == "$$$") msg.sender = "";  // FIXME
     messagelist << msg;
   }
     messagelist << msg;
   }
-  
+
   return messagelist;
 }
 
   return messagelist;
 }
 
@@ -395,13 +436,14 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, QDateTime since, int
   requestMsgsSinceOffsetQuery->exec();
   requestMsgsSinceOffsetQuery->first();
   offset = requestMsgsSinceOffsetQuery->value(0).toUInt();  
   requestMsgsSinceOffsetQuery->exec();
   requestMsgsSinceOffsetQuery->first();
   offset = requestMsgsSinceOffsetQuery->value(0).toUInt();  
-  
+
   // now let's select the messages
   requestMsgsSinceQuery->bindValue(":bufferid", buffer.uid());
   // now let's select the messages
   requestMsgsSinceQuery->bindValue(":bufferid", buffer.uid());
+  requestMsgsSinceQuery->bindValue(":bufferid2", buffer.uid());
   requestMsgsSinceQuery->bindValue(":since", since.toTime_t());
   requestMsgsSinceQuery->bindValue(":offset", offset);
   requestMsgsSinceQuery->exec();
   requestMsgsSinceQuery->bindValue(":since", since.toTime_t());
   requestMsgsSinceQuery->bindValue(":offset", offset);
   requestMsgsSinceQuery->exec();
-  
+
   while(requestMsgsSinceQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgsSinceQuery->value(1).toInt()),
                 buffer,
   while(requestMsgsSinceQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgsSinceQuery->value(1).toInt()),
                 buffer,
@@ -410,10 +452,11 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, QDateTime since, int
                 requestMsgsSinceQuery->value(4).toString(),
                 requestMsgsSinceQuery->value(3).toUInt());
     msg.msgId = requestMsgsSinceQuery->value(0).toUInt();
                 requestMsgsSinceQuery->value(4).toString(),
                 requestMsgsSinceQuery->value(3).toUInt());
     msg.msgId = requestMsgsSinceQuery->value(0).toUInt();
+    if(msg.sender == "$$$") msg.sender = "";  // FIXME
     messagelist << msg;
   }
     messagelist << msg;
   }
-  
-    
+
+
   return messagelist;
 }
 
   return messagelist;
 }
 
@@ -421,9 +464,10 @@ QList<Message> SqliteStorage::requestMsgs(BufferId buffer, QDateTime since, int
 QList<Message> SqliteStorage::requestMsgRange(BufferId buffer, int first, int last) {
   QList<Message> messagelist;
   requestMsgRangeQuery->bindValue(":bufferid", buffer.uid());
 QList<Message> SqliteStorage::requestMsgRange(BufferId buffer, int first, int last) {
   QList<Message> messagelist;
   requestMsgRangeQuery->bindValue(":bufferid", buffer.uid());
+  requestMsgRangeQuery->bindValue(":bufferid2", buffer.uid());
   requestMsgRangeQuery->bindValue(":firstmsg", first);
   requestMsgRangeQuery->bindValue(":lastmsg", last);
   requestMsgRangeQuery->bindValue(":firstmsg", first);
   requestMsgRangeQuery->bindValue(":lastmsg", last);
-  
+
   while(requestMsgRangeQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgRangeQuery->value(1).toInt()),
                 buffer,
   while(requestMsgRangeQuery->next()) {
     Message msg(QDateTime::fromTime_t(requestMsgRangeQuery->value(1).toInt()),
                 buffer,
@@ -432,9 +476,10 @@ QList<Message> SqliteStorage::requestMsgRange(BufferId buffer, int first, int la
                 requestMsgRangeQuery->value(4).toString(),
                 requestMsgRangeQuery->value(3).toUInt());
     msg.msgId = requestMsgRangeQuery->value(0).toUInt();
                 requestMsgRangeQuery->value(4).toString(),
                 requestMsgRangeQuery->value(3).toUInt());
     msg.msgId = requestMsgRangeQuery->value(0).toUInt();
+    if(msg.sender == "$$$") msg.sender = "";  // FIXME
     messagelist << msg;
   }
     messagelist << msg;
   }
-  
+
   return messagelist;
 }
 
   return messagelist;
 }
 
@@ -448,6 +493,7 @@ void SqliteStorage::importOldBacklog() {
   } else {
     user = query.value(0).toUInt();
   }
   } else {
     user = query.value(0).toUInt();
   }
+  // FIXME: backlog does not have userid, we have to select bufferids first
   query.prepare("DELETE FROM backlog WHERE userid = :userid");
   query.bindValue(":userid", user);
   query.exec();
   query.prepare("DELETE FROM backlog WHERE userid = :userid");
   query.bindValue(":userid", user);
   query.exec();