[SCM] ktp-common-internals packaging branch, master, updated. debian/15.12.1-2-1839-gf0635e9
Maximiliano Curia
maxy at moszumanska.debian.org
Mon May 9 09:05:50 UTC 2016
Gitweb-URL: http://git.debian.org/?p=pkg-kde/applications/ktp-common-internals.git;a=commitdiff;h=b6e0f2a
The following commit has been merged in the master branch:
commit b6e0f2aa343abac8fd5be85613ed75757ebc2fae
Author: Dan Vrátil <dvratil at redhat.com>
Date: Fri Nov 9 11:02:30 2012 +0100
Kopete logs importer implementation
KTp::LogsImporter can import AIM, MSN, ICQ, Yahoo, Jabber and
GaduGadu logs from Kopete
REVIEW: 107243
---
KTp/CMakeLists.txt | 3 +
KTp/logs-importer-private.cpp | 368 +++++++++++++++++++++
KTp/logs-importer-private.h | 78 +++++
.../accounts-combo-box.cpp => logs-importer.cpp} | 40 +--
KTp/logs-importer.h | 89 +++++
5 files changed, 555 insertions(+), 23 deletions(-)
diff --git a/KTp/CMakeLists.txt b/KTp/CMakeLists.txt
index ae65dc7..0fd12f0 100644
--- a/KTp/CMakeLists.txt
+++ b/KTp/CMakeLists.txt
@@ -7,6 +7,8 @@ set (ktp_common_internals_private_SRCS
error-dictionary.cpp
global-contact-manager.cpp
global-presence.cpp
+ logs-importer.cpp
+ logs-importer-private.cpp
presence.cpp
service-availability-checker.cpp
telepathy-handler-application.cpp
@@ -22,6 +24,7 @@ set (ktp_common_internals_private_HDRS
error-dictionary.h
global-contact-manager.h
global-presence.h
+ logs-importer.h
presence.h
service-availability-checker.h
telepathy-handler-application.h
diff --git a/KTp/logs-importer-private.cpp b/KTp/logs-importer-private.cpp
new file mode 100644
index 0000000..8be39ec
--- /dev/null
+++ b/KTp/logs-importer-private.cpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2012 Dan Vrátil <dvratil at redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "logs-importer-private.h"
+#include "logs-importer.h"
+
+#include <KLocalizedString>
+#include <KDebug>
+#include <KStandardDirs>
+
+using namespace KTp;
+
+LogsImporter::Private::Private(KTp::LogsImporter* parent)
+ : QThread(parent)
+ , m_day(0)
+ , m_month(0)
+ , m_year(0)
+ , m_isMUCLog(false)
+{
+
+}
+
+LogsImporter::Private::~Private()
+{
+
+}
+
+void LogsImporter::Private::setAccountId(const QString& accountId)
+{
+ m_accountId = accountId;
+}
+
+void LogsImporter::Private::run()
+{
+ QStringList files = findKopeteLogs(m_accountId);
+ if (files.isEmpty()) {
+ Q_EMIT error(i18n("No Kopete logs found"));
+ return;
+ }
+
+ Q_FOREACH (const QString &file, files) {
+ convertKopeteLog(file);
+ }
+}
+
+QString LogsImporter::Private::accountIdToAccountName(const QString &accountId) const
+{
+ int plugin = accountId.indexOf(QLatin1Char('/'));
+ int protocol = accountId.indexOf(QLatin1Char('/'), plugin + 1);
+
+ QString username = accountId.mid(protocol + 1);
+
+ /* ICQ accounts are prefixed with '_X' (X being a number) */
+ if (username.startsWith(QLatin1Char('_'))) {
+ username = username.remove(0, 2);
+ }
+
+ /* Remove trailing "0" */
+ username.chop(1);
+
+ /* Kopete escapes ".", "/", "~", "?" and "*" as "-" */
+ username.replace(QLatin1String("_2e"), QLatin1String("-")); /* . */
+ username.replace(QLatin1String("_2f"), QLatin1String("-")); /* / */
+ username.replace(QLatin1String("_7e"), QLatin1String("-")); /* ~ */
+ username.replace(QLatin1String("_3f"), QLatin1String("-")); /* ? */
+ username.replace(QLatin1String("_2a"), QLatin1String("-")); /* * */
+
+ /* But Kopete has apparently no problem with "@", so unescape it */
+ username.replace(QLatin1String("_40"), QLatin1String("@"));
+
+ return username;
+}
+
+QString LogsImporter::Private::accountIdToProtocol(const QString &accountId) const
+{
+ if (accountId.startsWith(QLatin1String("haze/aim/"))) {
+ return QLatin1String("AIMProtocol");
+ } else if (accountId.startsWith(QLatin1String("haze/msn/"))) {
+ return QLatin1String("WlmProtocol");
+ } else if (accountId.startsWith(QLatin1String("haze/icq/"))) {
+ return QLatin1String("ICQProtocol");
+ } else if (accountId.startsWith(QLatin1String("haze/yahoo/"))) {
+ return QLatin1String("YahooProtocol");
+ } else if (accountId.startsWith(QLatin1String("gabble/jabber/"))) {
+ return QLatin1String("JabberProtocol");
+ } else if (accountId.startsWith(QLatin1String("sunshine/gadugadu/")) ||
+ accountId.startsWith(QLatin1String("haze/gadugadu/"))) {
+ return QLatin1String("GaduProtocol");
+ } else {
+ /* We don't support these Kopete protocols:
+ * Bonjour - unable to reliably map Telepathy account to Kopete
+ * GroupWise - no support in Telepathy
+ * Meanwhile - no support in Telepathy
+ * QQ - no support in Telepathy
+ * SMS - no support in Telepathy
+ * Skype - not supported by KTp
+ * WinPopup - no support in Telepathy
+ */
+ kWarning() << accountId << "is an unsupported protocol";
+ return QString();
+ }
+}
+
+QStringList LogsImporter::Private::findKopeteLogs(const QString &accountId) const
+{
+ QStringList files;
+
+ QString protocol = accountIdToProtocol(accountId);
+ if (protocol.isEmpty()) {
+ kWarning() << "Unsupported protocol";
+ return files;
+ }
+
+ QString kopeteAccountId = accountIdToAccountName(accountId);
+ if (kopeteAccountId.isEmpty()) {
+ kWarning() << "Unable to parse account ID";
+ return files;
+ }
+
+ QDir dir(KStandardDirs::locateLocal("data", QLatin1String("kopete/logs/") +
+ protocol + QDir::separator() + kopeteAccountId));
+
+ if (dir.exists()) {
+ QFileInfoList entries = dir.entryInfoList(QStringList() << QLatin1String("*.xml"), QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
+ Q_FOREACH (const QFileInfo &finfo, entries) {
+ files << finfo.filePath();
+ }
+ }
+
+ return files;
+}
+
+void LogsImporter::Private::initKTpDocument()
+{
+ m_ktpDocument.clear();
+ m_ktpLogElement.clear();
+
+ QDomNode xmlNode = m_ktpDocument.createProcessingInstruction(
+ QLatin1String("xml"), QLatin1String("version='1.0' encoding='utf-8'"));
+ m_ktpDocument.appendChild(xmlNode);
+
+ xmlNode = m_ktpDocument.createProcessingInstruction(
+ QLatin1String("xml-stylesheet"), QLatin1String("type=\"text/xsl\" href=\"log-store-xml.xsl\""));
+ m_ktpDocument.appendChild(xmlNode);
+
+ m_ktpLogElement = m_ktpDocument.createElement(QLatin1String("log"));
+ m_ktpDocument.appendChild(m_ktpLogElement);
+}
+
+void LogsImporter::Private::saveKTpDocument()
+{
+ QString filename = QString(QLatin1String("%1%2%3.log"))
+ .arg(m_year)
+ .arg(m_month, 2, 10, QLatin1Char('0'))
+ .arg(m_day, 2, 10, QLatin1Char('0'));
+
+ KStandardDirs dirs;
+ QString path = dirs.localxdgdatadir() + QDir::separator() + QLatin1String("TpLogger") + QDir::separator() + QLatin1String("logs");
+
+ if (m_isMUCLog) {
+ path += QDir::separator() + QLatin1String("chatrooms");
+ } else {
+ QString accountId = m_accountId;
+ /* Escape '/' in accountId as '_' */
+ if (m_accountId.contains(QLatin1Char('/'))) {
+ accountId.replace(QLatin1Char('/'), QLatin1String("_"));
+ }
+ path += QDir::separator() + accountId;
+ }
+
+ path += QDir::separator() + m_contactId;
+
+ /* Make sure the path exists */
+ QDir dir(path);
+ if (!dir.exists()) {
+ QDir::home().mkpath(QDir::home().relativeFilePath(dir.path()));
+ }
+
+ path += QDir::separator() + filename;
+
+ QFile outFile(path);
+ if (outFile.exists()) {
+ kWarning() << path << "already exists, not importing logs";
+ return;
+ }
+
+ outFile.open(QIODevice::WriteOnly);
+ QTextStream stream(&outFile);
+ m_ktpDocument.save(stream, 0);
+
+ kDebug() << "Stored as" << path;
+}
+
+KDateTime LogsImporter::Private::parseKopeteTime(const QDomElement& kopeteMessage) const
+{
+ QString strtime = kopeteMessage.attribute(QLatin1String("time"));
+ if (strtime.isEmpty()) {
+ return KDateTime();
+ }
+
+ /* Kopete time attribute is in format "D H:M:S" - year and month are stored in
+ * log header, Hour, minute and seconds don't have zero padding */
+ QStringList dateTime = strtime.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ if (dateTime.length() != 2) {
+ return KDateTime();
+ }
+
+ QStringList time = dateTime.at(1).split(QLatin1Char(':'));
+
+ QString str = QString(QLatin1String("%1-%2-%3T%4:%5:%6Z"))
+ .arg(m_year)
+ .arg(m_month, 2, 10, QLatin1Char('0'))
+ .arg(dateTime.at(0).toInt(), 2, 10, QLatin1Char('0'))
+ .arg(time.at(0).toInt(), 2, 10, QLatin1Char('0'))
+ .arg(time.at(1).toInt(), 2, 10, QLatin1Char('0'))
+ .arg(time.at(2).toInt(), 2, 10, QLatin1Char('0'));
+
+ /* Kopete stores date in local timezone but Telepathy in UTC. Note that we
+ * must use time offset at the specific date rather then current offset
+ * (could be different due to for example DST) */
+ KDateTime localTz = KDateTime::fromString(str, KDateTime::ISODate);
+ KDateTime utc = localTz.addSecs(-KDateTime::currentLocalDateTime().timeZone().offset(localTz.toTime_t()));
+
+ return utc;
+}
+
+QDomElement LogsImporter::Private::convertKopeteMessage(const QDomElement& kopeteMessage)
+{
+ KDateTime time = parseKopeteTime(kopeteMessage);
+ if (!time.isValid()) {
+ kWarning() << "Failed to parse message time, skipping message";
+ return QDomElement();
+ }
+
+ /* If this is the very first message we are processing, then initialize
+ * the day counter */
+ if (m_day == 0) {
+ m_day = time.date().day();
+ }
+
+ /* Kopete stores logs by months, while Telepathy by days. When day changes,
+ * save to current KTp log and prepare a new document */
+ if (time.date().day() != m_day) {
+ saveKTpDocument();
+ m_day = time.date().day();
+
+ initKTpDocument();
+ }
+
+ QDomElement ktpMessage = m_ktpDocument.createElement(QLatin1String("message"));
+ ktpMessage.setAttribute(QLatin1String("time"), time.toUtc().toString(QLatin1String("%Y%m%dT%H:%M:%S")));
+
+ QString sender = kopeteMessage.attribute(QLatin1String("from"));
+ if (!m_isMUCLog && sender.startsWith(m_contactId) && sender.length() > m_contactId.length()) {
+ m_isMUCLog = true;
+ }
+
+ /* In MUC, the "from" attribute is in format "room at conf.server/senderId", so strip
+ * the room name */
+ if (m_isMUCLog) {
+ sender = sender.remove(m_contactId);
+ }
+
+ ktpMessage.setAttribute(QLatin1String("id"), sender);
+ ktpMessage.setAttribute(QLatin1String("name"), kopeteMessage.attribute(QLatin1String("nick")));
+
+ if (sender == m_meId) {
+ ktpMessage.setAttribute(QLatin1String("isuser"), QLatin1String("true"));
+ } else {
+ ktpMessage.setAttribute(QLatin1String("isuser"), QLatin1String("false"));
+ }
+
+ /* These are not present in Kopete logs, but that should not matter */
+ ktpMessage.setAttribute(QLatin1String("token"), QString());
+ ktpMessage.setAttribute(QLatin1String("message-token"), QString());
+ ktpMessage.setAttribute(QLatin1String("type"), QLatin1String("normal"));
+
+ /* Copy the message content */
+ QDomText message = m_ktpDocument.createTextNode(kopeteMessage.text());
+ ktpMessage.appendChild(message);
+
+ return ktpMessage;
+}
+
+void LogsImporter::Private::convertKopeteLog(const QString& filepath)
+{
+ kDebug() << "Converting" << filepath;
+
+ /* Init */
+ m_day = 0;
+ m_month = 0;
+ m_year = 0;
+ m_isMUCLog = false;
+ m_meId.clear();
+ m_contactId.clear();
+
+ initKTpDocument();
+
+ QFile f(filepath);
+ f.open(QIODevice::ReadOnly);
+
+ QByteArray ba = f.readAll();
+
+ m_kopeteDocument.setContent(ba);
+ /* Get <history> node */
+ QDomElement history = m_kopeteDocument.documentElement();
+ /* Get all <msg> nodes in <history> node */
+ QDomNodeList kopeteMessages = history.elementsByTagName(QLatin1String("msg"));
+
+ /* Get <head> node and parse it */
+ QDomNodeList heads = history.elementsByTagName(QLatin1String("head"));
+ if (heads.isEmpty()) {
+ Q_EMIT error(i18n("Invalid Kopete log format"));
+ return;
+ }
+
+ QDomNode head = heads.item(0);
+ QDomNodeList headData = head.childNodes();
+ if (headData.length() < 3) {
+ Q_EMIT error(i18n("Invalid Kopete log format"));
+ return;
+ }
+
+ for (int i = 0; i < headData.count(); i++) {
+ QDomElement el = headData.item(i).toElement();
+
+ if (el.tagName() == QLatin1String("date")) {
+ m_year = el.attribute(QLatin1String("year"), QString()).toInt();
+ m_month = el.attribute(QLatin1String("month"), QString()).toInt();
+ } else if (el.tagName() == QLatin1String("contact")) {
+ if (el.attribute(QLatin1String("type")) == QLatin1String("myself")) {
+ m_meId = el.attribute(QLatin1String("contactId"));
+ } else {
+ m_contactId = el.attribute(QLatin1String("contactId"));
+ }
+ }
+ }
+
+ if ((m_year == 0) || (m_month == 0) || m_meId.isEmpty() || m_contactId.isEmpty()) {
+ kWarning() << "Failed to correctly parse header. Possibly invalid log format";
+ return;
+ }
+
+ for (int i = 0; i < kopeteMessages.count(); i++) {
+ QDomElement kopeteMessage = kopeteMessages.item(i).toElement();
+
+ QDomElement ktpMessage = convertKopeteMessage(kopeteMessage);
+
+ m_ktpLogElement.appendChild(ktpMessage);
+ }
+
+ saveKTpDocument();
+}
diff --git a/KTp/logs-importer-private.h b/KTp/logs-importer-private.h
new file mode 100644
index 0000000..06c9c0d
--- /dev/null
+++ b/KTp/logs-importer-private.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 Dan Vrátil <dvratil at redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef KTP_LOGSIMPORTER_PRIVATE_H
+#define KTP_LOGSIMPORTER_PRIVATE_H
+
+#include <QThread>
+#include <QStringList>
+#include <QDomDocument>
+#include <KDateTime>
+
+#include "logs-importer.h"
+
+namespace KTp {
+
+class LogsImporter::Private: public QThread
+{
+ Q_OBJECT
+
+ public:
+ Private(LogsImporter* parent);
+ ~Private();
+
+ void setAccountId(const QString &accountId);
+ QStringList findKopeteLogs(const QString &accountId) const;
+
+ Q_SIGNALS:
+ void error(const QString &error);
+
+ protected:
+ virtual void run();
+
+ private:
+
+ QString accountIdToProtocol(const QString &accountId) const;
+ QString accountIdToAccountName(const QString &accountId) const;
+
+ void initKTpDocument();
+ void saveKTpDocument();
+ KDateTime parseKopeteTime(const QDomElement &kopeteMessage) const;
+ QDomElement convertKopeteMessage(const QDomElement &kopeteMessage);
+ void convertKopeteLog(const QString &filepath);
+
+ QString m_accountId;
+ QString m_meId;
+ QString m_contactId;
+
+ QDomDocument m_ktpDocument;
+ QDomDocument m_kopeteDocument;
+ QDomElement m_ktpLogElement;
+
+ int m_day;
+ int m_month;
+ int m_year;
+
+ bool m_isMUCLog;
+
+ friend class KTp::LogsImporter;
+};
+
+} /* namespace KTp */
+
+#endif // KTP_LOGSIMPORTER_PRIVATE_H
diff --git a/KTp/Widgets/accounts-combo-box.cpp b/KTp/logs-importer.cpp
similarity index 51%
copy from KTp/Widgets/accounts-combo-box.cpp
copy to KTp/logs-importer.cpp
index d427e9b..926d265 100644
--- a/KTp/Widgets/accounts-combo-box.cpp
+++ b/KTp/logs-importer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 David Edmundson <kde at davidedmundson.co.uk>
+ * Copyright (C) 2012 Dan Vrátil <dvratil at redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,39 +16,33 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "logs-importer.h"
+#include "logs-importer-private.h"
-#include "accounts-combo-box.h"
-
-#include <TelepathyQt/AccountManager>
#include <TelepathyQt/Account>
-#include <KTp/Models/accounts-list-model.h>
-
+using namespace KTp;
-class KTp::AccountsComboBox::Private
+LogsImporter::LogsImporter(QObject *parent)
+ : QObject(parent)
+ , d(new LogsImporter::Private(this))
{
-public:
- AccountsListModel *model;
-};
+ connect(d, SIGNAL(finished()), SIGNAL(logsImported()));
+ connect(d, SIGNAL(error(QString)), SIGNAL(error(QString)));
+}
-KTp::AccountsComboBox::AccountsComboBox(QWidget *parent) :
- QComboBox(parent),
- d(new KTp::AccountsComboBox::Private())
+LogsImporter::~LogsImporter()
{
- d->model = new AccountsListModel(this);
- setModel(d->model);
+ delete d;
}
-void KTp::AccountsComboBox::setAccountManager(const Tp::AccountManagerPtr &accountManager)
+bool LogsImporter::hasKopeteLogs(const Tp::AccountPtr& account)
{
- d->model->setAccountManager(accountManager);
+ return !d->findKopeteLogs(account->uniqueIdentifier()).isEmpty();
}
-Tp::AccountPtr KTp::AccountsComboBox::currentAccount()
+void LogsImporter::startLogImport(const Tp::AccountPtr& account)
{
- return itemData(currentIndex(), AccountsListModel::AccountRole).value<Tp::AccountPtr>();
+ d->setAccountId(account->uniqueIdentifier());
+ d->start();
}
-
-
-
-
diff --git a/KTp/logs-importer.h b/KTp/logs-importer.h
new file mode 100644
index 0000000..e6a6918
--- /dev/null
+++ b/KTp/logs-importer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Dan Vrátil <dvratil at redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LOGSIMPORTER_H
+#define LOGSIMPORTER_H
+
+#include <QtCore/QObject>
+#include <TelepathyQt/Types>
+
+#include <KTp/ktp-export.h>
+
+namespace KTp
+{
+
+/**
+ * @short A class to import old logs from Kopete
+ *
+ * This class provides convenient interface for importing logs from Kopete.
+ *
+ * Currently the importer supports AIM, WML, ICQ, Jabber, GaduGadu and Yahoo logs.
+ */
+class KTP_EXPORT LogsImporter : public QObject
+{
+ Q_OBJECT
+
+ public:
+ LogsImporter(QObject *parent = 0);
+
+ virtual ~LogsImporter();
+
+ /**
+ * Checks whether there are any Kopete logs for \p account.
+ *
+ * @param account Telepathy Account against whose Kopete counterpart to check
+ * @return Returns when there is at least one log for given account
+ */
+ bool hasKopeteLogs(const Tp::AccountPtr &account);
+
+ /**
+ * Imports Kopete logs for \p account to Telepathy
+ *
+ * Finds all Kopete logs for Kopete-version of \p account, converts them
+ * to Telepathy Logger format and imports then to Telepathy Logger storage.
+ *
+ * This method returns immediatelly. When all logs are scanned and converted,
+ * logsImported() signal is emitted.
+ *
+ * The import will NOT overwrite existing log files.
+ *
+ * @param account A Telepathy Account
+ */
+ void startLogImport(const Tp::AccountPtr &account);
+
+ Q_SIGNALS:
+ /**
+ * Emitted when logs are successfully imported.
+ */
+ void logsImported();
+
+ /**
+ * Emitted when an error occurs during importing.
+ *
+ * The process can still import some logs, but some might be missing.
+ */
+ void error(const QString &error);
+
+ private:
+ class Private;
+ Private *d;
+};
+
+} /* namespace KTp */
+
+#endif // LOGSIMPORTER_H
--
ktp-common-internals packaging
More information about the pkg-kde-commits
mailing list