diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | FindQtOAuth.cmake | 38 | ||||
-rw-r--r-- | src/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/sync/operasynchandler.cpp | 884 | ||||
-rw-r--r-- | src/sync/operasynchandler.h | 142 | ||||
-rw-r--r-- | src/sync/sync_host_type.ui | 7 | ||||
-rw-r--r-- | src/sync/sync_opera_settings.ui | 70 | ||||
-rw-r--r-- | src/sync/syncassistant.cpp | 2 | ||||
-rw-r--r-- | src/sync/syncassistant.h | 1 | ||||
-rw-r--r-- | src/sync/synccheckwidget.cpp | 5 | ||||
-rw-r--r-- | src/sync/synchosttypewidget.cpp | 17 | ||||
-rw-r--r-- | src/sync/syncmanager.cpp | 4 | ||||
-rw-r--r-- | src/sync/syncoperasettingswidget.cpp | 60 | ||||
-rw-r--r-- | src/sync/syncoperasettingswidget.h | 52 |
14 files changed, 1289 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d96ad09..5d24751b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.4) # ================================================================================== +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH}) FIND_PACKAGE(Qt4 4.8.0 COMPONENTS QtCore QtGui QtNetwork QtWebKit REQUIRED) @@ -49,6 +50,10 @@ MACRO_BOOL_TO_01(Nepomuk_FOUND HAVE_NEPOMUK) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-nepomuk.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-nepomuk.h ) +FIND_PACKAGE(QCA2 REQUIRED) + +FIND_PACKAGE(QtOAuth REQUIRED) + # ================================================================================== # Log messages diff --git a/FindQtOAuth.cmake b/FindQtOAuth.cmake new file mode 100644 index 00000000..a9578ea2 --- /dev/null +++ b/FindQtOAuth.cmake @@ -0,0 +1,38 @@ +# - Try to find the QtOAuth library +# Once done this will define +# +# QTOAUTH_FOUND - system has the QtOAuth library +# QTOAUTH_INCLUDE_DIR - the QtOAuth include directory +# QTOAUTH_LIBRARY - Link this to use the QtOAuth +# QTOAUTH_DEFINITIONS - Compiler switches required for using QOAuth +# +# Copyright © 2010, Mehrdad Momeny <mehrdad.momeny@gmail.com> +# Copyright © 2010, Harald Sitter <apachelogger@ubuntu.com> +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (QTOAUTH_INCLUDE_DIR AND QTOAUTH_LIBRARY) + # in cache already + set(QTOAUTH_FOUND TRUE) +else (QTOAUTH_INCLUDE_DIR AND QTOAUTH_LIBRARY) + if (NOT WIN32) + find_package(PkgConfig) + pkg_check_modules(PC_QTOAUTH QUIET qoauth) + set(QTOAUTH_DEFINITIONS ${PC_QTOAUTH_CFLAGS_OTHER}) + endif(NOT WIN32) + + find_library(QTOAUTH_LIBRARY NAMES qoauth + HINTS ${PC_QTOAUTH_LIBDIR} ${PC_QTOAUTH_LIBRARY_DIRS} + ) + + find_path(QTOAUTH_INCLUDE_DIR QtOAuth/interface.h + HINTS ${PC_QTOAUTH_INCLUDEDIR} ${PC_QTOAUTH_INCLUDE_DIRS} + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(QtOAuth DEFAULT_MSG QTOAUTH_LIBRARY QTOAUTH_INCLUDE_DIR) + + mark_as_advanced(QTOAUTH_INCLUDE_DIR QTOAUTH_LIBRARY) +endif (QTOAUTH_INCLUDE_DIR AND QTOAUTH_LIBRARY) + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5aa70dbf..763f02d7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -101,6 +101,7 @@ SET( rekonq_KDEINIT_SRCS #---------------------------------------- sync/ftpsynchandler.cpp sync/googlesynchandler.cpp + sync/operasynchandler.cpp sync/syncassistant.cpp sync/synchandler.cpp sync/syncmanager.cpp @@ -110,6 +111,7 @@ SET( rekonq_KDEINIT_SRCS sync/synchosttypewidget.cpp sync/syncftpsettingswidget.cpp sync/syncgooglesettingswidget.cpp + sync/syncoperasettingswidget.cpp ) IF(HAVE_NEPOMUK) @@ -141,6 +143,7 @@ KDE4_ADD_UI_FILES( rekonq_KDEINIT_SRCS sync/sync_data.ui sync/sync_ftp_settings.ui sync/sync_google_settings.ui + sync/sync_opera_settings.ui sync/sync_host_type.ui ) @@ -165,6 +168,8 @@ INCLUDE_DIRECTORIES ( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDES} ${QT4_INCLUDES} + ${QCA2_INCLUDE_DIR} + ${QTOAUTH_INCLUDE_DIR} ) IF(HAVE_NEPOMUK) @@ -197,6 +202,8 @@ TARGET_LINK_LIBRARIES ( kdeinit_rekonq ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KPARTS_LIBS} + ${QCA2_LIBRARY} + ${QTOAUTH_LIBRARY} ) IF(HAVE_NEPOMUK) diff --git a/src/sync/operasynchandler.cpp b/src/sync/operasynchandler.cpp new file mode 100644 index 00000000..cdddbe38 --- /dev/null +++ b/src/sync/operasynchandler.cpp @@ -0,0 +1,884 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com> +* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "operasynchandler.h" +#include "operasynchandler.moc" + +// Auto Includes +#include "rekonq.h" + +// Local Includes +#include "application.h" +#include "bookmarkmanager.h" + +// KDE Includes +#include <KStandardDirs> +#include <klocalizedstring.h> +#include <kbookmarkmanager.h> + + +#include <QList> +#include <QWebPage> +#include <QWebFrame> +#include <QWebElement> +#include <QUrl> +#include <QWebSettings> +#include <QNetworkAccessManager> +#include <QNetworkReply> +#include <QDomDocument> + + +OperaSyncHandler::OperaSyncHandler(QObject *parent) + : SyncHandler(parent) + , _mode(RECEIVE_CHANGES) +// , _doLogin(false) + , _isSyncing(false) +/* , _reply(0) + , _requestCount(0)*/ +{ + kDebug() << "Creating Opera Bookmarks handler..."; +// _webPage.settings()->setAttribute(QWebSettings::AutoLoadImages, false); +// _webPage.settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, true); +// connect(&_webPage, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); + + webView = new QWebView(); + webView->settings()->setAttribute(QWebSettings::AutoLoadImages, false); + connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool))); + + qoauth = new QOAuth::Interface(); + qoauth->setConsumerKey("test_desktop_key"); + qoauth->setConsumerSecret("p2FlOFGr3XFm5gOwEKKDcg3CvA4pp0BC"); +} + + +void OperaSyncHandler::initialLoadAndCheck() +{ + if (!ReKonfig::syncEnabled()) + { + _firstTimeSynced = false; + return; + } + + // Bookmarks + if (ReKonfig::syncBookmarks()) + { +// _mode = RECEIVE_CHANGES; + _mode = SEND_CHANGES; + startLogin(); + } + + if (ReKonfig::syncHistory()) + { + emit syncStatus(Rekonq::History, false, i18n("Not supported!")); + } + + if (ReKonfig::syncHistory()) + { + emit syncStatus(Rekonq::Passwords, false, i18n("Not supported!")); + } +} + + +bool OperaSyncHandler::syncRelativeEnabled(bool check) +{ + if (!ReKonfig::syncEnabled()) + return false; + + if (!_firstTimeSynced) + return false; + + return check; +} + + +// --------------------------------------------------------------------------------------- + + +void OperaSyncHandler::syncHistory() +{ + kDebug() << "Syncing history not supported!"; + emit syncStatus(Rekonq::History, false, i18n("Syncing history not supported!")); + emit syncHistoryFinished(false); +} + + +void OperaSyncHandler::syncPasswords() +{ + kDebug() << "Syncing passwords not supported!"; + emit syncStatus(Rekonq::Passwords, false, i18n("Syncing passwords not supported!")); + emit syncPasswordsFinished(false); +} + + +void OperaSyncHandler::syncBookmarks() +{ + + if (_isSyncing) + { + kDebug() << "Sync already in progress!"; + return; + } +// _mode = SEND_CHANGES; +// startLogin(); +} + +void OperaSyncHandler::startLogin() +{ + if (ReKonfig::syncUser().isEmpty() || ReKonfig::syncPass().isEmpty()) + { + kDebug() << "No username or password!"; + emit syncStatus(Rekonq::Bookmarks, false, i18n("No username or password!")); + emit syncBookmarksFinished(false); + return; + } + + _isSyncing = true; + + _doLogin = true; + + kDebug() << "Loading login page..."; +// _webPage.mainFrame()->load(QUrl("http://bookmarks.google.com/")); + + + qoauth->setRequestTimeout(20000); + qoauth->ignoreSslErrors(); + QOAuth::ParamMap requestMap; + requestMap.insert("oauth_callback", "oob"); + + requestParam = qoauth->requestToken("https://auth.opera.com/service/oauth/request_token", QOAuth::POST, QOAuth::HMAC_SHA1, requestMap); + qDebug() << qoauth->error(); + qDebug() << requestParam; + + requestToken = requestParam.value("oauth_token"); + requestTokenSecret = requestParam.value("oauth_token_secret"); + + qDebug() << requestToken; + qDebug() << requestTokenSecret; + + + qDebug() << QUrl("https://auth.opera.com/service/oauth/authorize?oauth_token=" + QString(requestToken) + "&oauth_callback=oob"); + + webView->resize(400, 400); + + webView->load(QUrl("https://auth.opera.com/service/oauth/authorize?oauth_token=" + QString(requestToken) + "&oauth_callback=oob" )); + + webView->show(); + + +} + +//Loading a webpage finished, what action to take is decided based on url we have loaded. +void OperaSyncHandler::loadFinished(bool ok) +{ + kDebug() << "Load Finished" << ok; + if (!ok) + { + kDebug() << "Error loading: " << _webPage.mainFrame()->url(); + emit syncStatus(Rekonq::Bookmarks, false, i18n( "Error loading: " + _webPage.mainFrame()->url().toEncoded())); + + _isSyncing = false; + return; + } + + qDebug() << webView->url(); + QString path = webView->url().path(); + + qDebug() << path; + if (path == "/service/oauth/authorize") + { + QWebFrame *mainFrame = webView->page()->mainFrame(); + QString html = mainFrame->toHtml(); + + if (html.contains("login-form")) + { + qDebug() << "Login page"; + QWebElement form = mainFrame->findFirstElement("#login-form"); + if (form.isNull()) + { + qDebug() << "form is null"; + } + + QWebElement username = form.findFirst("#username"); + QWebElement password = form.findFirst("#password"); + QWebElement button = form.findFirst("input[name=\"grant\"]"); + + qDebug() << username.isNull(); + qDebug() << password.isNull(); + qDebug() << button.isNull(); + username.setAttribute("value", ReKonfig::syncUser()); + password.setAttribute("value", ReKonfig::syncPass()); + + qDebug() << button.toPlainText(); + button.evaluateJavaScript("this.click();"); + + } + else if (html.contains("verifier")) + { + QWebElement authkey = mainFrame->findFirstElement("#verifier"); + QByteArray verifier = authkey.toPlainText().toUtf8(); + + qDebug() << verifier; + authParams.insert("oauth_verifier", verifier); + resultParam = qoauth->accessToken("https://auth.opera.com/service/oauth/access_token", QOAuth::POST, requestToken, requestTokenSecret, QOAuth::HMAC_SHA1, authParams); + + qDebug() << qoauth->error(); + qDebug() << resultParam; + + authToken = resultParam.value("oauth_token"); + authTokenSecret = resultParam.value("oauth_token_secret"); + + + requestToken.clear(); + requestTokenSecret.clear(); + requestParam.clear(); + resultParam.clear(); + authParams.clear(); + getBookmarks(); + } + + } +} + + + +void OperaSyncHandler::getBookmarks() +{ + QOAuth::ParamMap requestMap; + //requestMap.insert("oauth_nonce", "123"); + requestMap.insert("api_output", "xml"); + qDebug() << "Auth Token : " << authToken; + qDebug() << "Auth Token Secret : " << authTokenSecret; + + urlParams = qoauth->createParametersString("https://link.api.opera.com/rest/bookmark/descendants", QOAuth::GET, authToken, authTokenSecret, QOAuth::HMAC_SHA1, requestMap, QOAuth::ParseForInlineQuery); + + QNetworkRequest request; + + qDebug() << "URL Params: " << urlParams; + QByteArray urlstr = "https://link.api.opera.com/rest/bookmark/descendants"; + + urlstr.append(urlParams); + kDebug() << urlstr; + KIO::TransferJob *job = KIO::get(KUrl(urlstr), KIO::Reload, KIO::HideProgressInfo); + + connect(job, SIGNAL(result(KJob*)), this, SLOT(resultSlot(KJob*))); + connect(job, SIGNAL(data(KIO::Job*, QByteArray)), this, SLOT(dataSlot(KIO::Job*, QByteArray))); +} + +void OperaSyncHandler::dataSlot(KIO::Job* job, QByteArray data) +{ + kDebug() << data; + xmlData += data; +} + +void OperaSyncHandler::resultSlot(KJob* job) +{ + if (job->error() != 0) + { + xmlData = ""; + kDebug() << "Some error!"; + return; + } + + kDebug() << "No Error!"; + kDebug() << xmlData; + + QDomDocument doc("bookmarks"); + doc.setContent(xmlData); + QDomNodeList responseList = doc.elementsByTagName("response"); + + qDebug() << responseList.size(); + KBookmarkGroup root = rApp->bookmarkManager()->rootGroup(); + + if (_mode == RECEIVE_CHANGES) + { + if (responseList.size() > 0) + { + QDomNode item = responseList.at(0).firstChild(); + + // qDebug() << item.nodeName(); + + while (!item.isNull()) + { + handleResource(item, root); + item = item.nextSibling(); + } + } + } + else + { + if (responseList.size() > 0) + { + QDomNode item = responseList.at(0).firstChild(); + + // qDebug() << item.nodeName(); + + while (!item.isNull()) + { + handleResource(item, root); + item = item.nextSibling(); + } + } + + //handleLocalGroup(root, responseList.at(0).toElement()); + + QDomElement item = responseList.at(0).toElement(); + KBookmark current = root.first(); + + while(!current.isNull()) + { + if (current.isGroup()) + { + QString groupName = current.fullText(); + QDomElement child = findOperaFolder(item, groupName); + + if (child.isNull()) + { + //Add Opera group here + kDebug() << "Add group " << groupName; + KJob *job = addBookmarkFolderOnServer(current.fullText()); + jobToGroupMap.insert(job, root); + } + else + { + kDebug() << "Handling group " << groupName; + QDomElement grandChild = getChildElement(child, "children"); + + QString id = getChildString(child, "id"); + + kDebug() << grandChild.tagName() << id; + + if (grandChild.isNull()) + { + kDebug() << "Grand child is null"; + handleLocalGroup(current.toGroup(), grandChild, id); + } + else{ + //kDebug() << "Grand child " << getTitleFromResourceProperties(grandChild); + handleLocalGroup(current.toGroup(), grandChild, id); + } + } + } + + else + { + KUrl url = current.url(); + + QDomElement child = findOperaBookmark(item, url); + + if (child.isNull()) + { + //Add bookmark on server + kDebug() << "Add bookmark :" << url; + addBookmarkOnServer(current.fullText(), current.url().url()); + } + else + { + kDebug() << "Bookmark exists :" << url; + } + } + + current = root.next(current); + } + } + + xmlData = ""; +} + +void OperaSyncHandler::bookmarkDataSlot(KIO::Job* job, QByteArray data) +{ + kDebug() << data; + //xmlData += data; +} + +void OperaSyncHandler::bookmarkResultSlot(KJob* job) +{ + if (job->error() != 0) + { + kDebug() << "Some error!" << job->error(); + return; + } +} + +void OperaSyncHandler::bookmarkFolderDataSlot(KIO::Job* job, QByteArray data) +{ + kDebug() << data; + + QByteArray &value = jobToResponseMap[job]; + value.append(data); + //xmlData += data; +} + +void OperaSyncHandler::bookmarkFolderResultSlot(KJob* job) +{ + if (job->error() != 0) + { + kDebug() << "Some error!"; + return; + } + + QByteArray value = jobToResponseMap[job]; + KBookmarkGroup root = jobToGroupMap[job]; + + kDebug() << "Final value is " << value; + QDomDocument doc("new bookmark"); + doc.setContent(value); + QDomNodeList responseList = doc.elementsByTagName("response"); + + qDebug() << responseList.size(); + + if (responseList.size() > 0) + { + QDomElement item = responseList.at(0).firstChildElement(); + + QString parentId = getIdFromResource(item); + kDebug() << "Resource id is : " << parentId; + + handleLocalGroup(root, item, parentId); + + } +} + +void OperaSyncHandler::handleBookmark(const QDomElement &item, KBookmarkGroup root) +{ + QString url = getUrlFromResourceProperties(item); + QString title = getTitleFromResourceProperties(item); + QString id = getChildString(item, "id"); + + KBookmark bookmark = findLocalBookmark(root, KUrl(url)); + + if (bookmark.isNull()) + { + if (_mode == RECEIVE_CHANGES) + { + root.addBookmark(title, KUrl(url)); + rApp->bookmarkManager()->manager()->emitChanged(root); + } + else + { + //Delete bookmark from server + kDebug() << "Deleting bookmark from server : " << title; + deleteResourceOnServer(id); + } + } + +} + +void OperaSyncHandler::handleBookmarkFolder(const QDomElement &item, KBookmarkGroup &root) +{ + qDebug() << "Title : " << getTitleFromResourceProperties(item); + + QDomNode child = item.firstChild(); + + while (!child.isNull()) + { + QDomNode resource = child.firstChild(); + + while (!resource.isNull()) + { + handleResource(resource, root); + resource = resource.nextSibling(); + } + child = child.nextSibling(); + } +} + +//Handle resource tag of xml replied from server +void OperaSyncHandler::handleResource(const QDomNode &item, KBookmarkGroup &root) +{ + // qDebug() << item.nodeName(); + QDomElement element = item.toElement(); + + QString itemType = getChildString(item, "item_type"); + if (itemType == "bookmark") + { + handleBookmark(element, root); + } + else if (itemType == "bookmark_folder") + { + QString title = getTitleFromResourceProperties(item.toElement()); + QString id = getChildString(item.toElement(), "id"); + if (title == "Trash") return; + + + KBookmarkGroup childGroup = findLocalGroup(root, title); + kDebug() << childGroup.isNull(); + + if (_mode == RECEIVE_CHANGES) + { + if (childGroup.isNull()) + { + childGroup = root.createNewFolder(title); + rApp->bookmarkManager()->manager()->emitChanged(root); + } + + handleBookmarkFolder(element, childGroup); + } + else + { + if (childGroup.isNull()) + { + //Delete bookmark folder on server + kDebug() << "Deleting bookmark folder from server : " << title; + deleteResourceOnServer(id); + } + else + { + handleBookmarkFolder(element, childGroup); + } + } + } +} + +/* +void OperaSyncHandler::handleLocalBookmark(const KBookmark &root, const QDomElement &item) +{ + KUrl url = root.url(); + + QDomElement child = findOperaBookmark(item, url); + + if (child.isNull()) + { + //Delete bookmark on server + } + +} +*/ + +void OperaSyncHandler::handleLocalGroup(const KBookmarkGroup &root, const QDomElement &item, QString parentId) +{ + KBookmark current = root.first(); + + kDebug() << "Handling " << parentId; + while(!current.isNull()) + { + kDebug() << "Looping"; + if (current.isGroup()) + { + QString groupName = current.fullText(); + QDomElement child = findOperaFolder(item, groupName); + + if (child.isNull()) + { + //Add Opera group here + kDebug() << "Add group " << groupName; + kDebug() << "Parent is " << item.text(); + //QString parentId = getIdFromResource(item); + kDebug() << "Parent id is " << parentId; + KJob *job = addBookmarkFolderOnServer(current.fullText(), parentId); + jobToGroupMap.insert(job, current.toGroup()); + } + else + { + kDebug() << "Handling group " << groupName; + + QDomElement grandChild = getChildElement(child, "children"); + + QString id = getChildString(child, "id"); + + if (grandChild.isNull()) + { + handleLocalGroup(current.toGroup(), grandChild, id); + } + else + { + handleLocalGroup(current.toGroup(), grandChild, id); + } + + + } + } + else + { + KUrl url = current.url(); + + QDomElement child = findOperaBookmark(item, url); + + if (child.isNull()) + { + //Add bookmark on server + kDebug() << "Add bookmark :" << url; + kDebug() << "Parent is : " << item.text(); + //QString parentId = getIdFromResource(item); + kDebug() << "Parent id is " << parentId; + addBookmarkOnServer(current.fullText(), current.url().url(), parentId); + } + else + { + kDebug() << "Bookmark exists :" << url; + } + } + + current = root.next(current); + } +} + +void OperaSyncHandler::addBookmarkOnServer(QString title, QString url, QString parent) +{ + QOAuth::ParamMap requestMap; + requestMap.insert("api_output", "xml"); + requestMap.insert("api_method","create"); + requestMap.insert("item_type","bookmark"); + requestMap.insert("title", QUrl::toPercentEncoding(title.toUtf8())); + requestMap.insert("uri", QUrl::toPercentEncoding(url.toUtf8())); + + QByteArray requestUrl = "https://link.api.opera.com/rest/bookmark/"; + + if (!parent.isNull()) + { + requestUrl.append(parent.toUtf8()); + } + + QByteArray postData = qoauth->createParametersString(requestUrl, QOAuth::POST, authToken, authTokenSecret, QOAuth::HMAC_SHA1, requestMap, QOAuth::ParseForRequestContent); + + kDebug() << "Post data is : " << postData; + + kDebug() << "Request Url is : " << requestUrl; + + KIO::TransferJob *job = KIO::http_post( KUrl(requestUrl), postData, KIO::HideProgressInfo ); + job->addMetaData("Content-Type", "application/x-www-form-urlencoded" ); + + connect(job, SIGNAL(result(KJob*)), this, SLOT(bookmarkResultSlot(KJob*))); + connect(job, SIGNAL(data(KIO::Job*, QByteArray)), this, SLOT(bookmarkDataSlot(KIO::Job*, QByteArray))); + +} + +KJob *OperaSyncHandler::addBookmarkFolderOnServer(QString title, QString parent) +{ + QOAuth::ParamMap requestMap; + requestMap.insert("api_output", "xml"); + requestMap.insert("api_method","create"); + requestMap.insert("item_type","bookmark_folder"); + requestMap.insert("title", QUrl::toPercentEncoding(title.toUtf8())); + + QByteArray requestUrl = "https://link.api.opera.com/rest/bookmark/"; + if (!parent.isNull()) + { + requestUrl.append(parent.toUtf8()); + } + + QByteArray postData = qoauth->createParametersString(requestUrl, QOAuth::POST, authToken, authTokenSecret, QOAuth::HMAC_SHA1, requestMap, QOAuth::ParseForRequestContent); + + kDebug() << "Post data is : " << postData; + + kDebug() << "Request Url is : " << requestUrl; + + KIO::TransferJob *job = KIO::http_post( KUrl(requestUrl), postData, KIO::HideProgressInfo ); + job->addMetaData("Content-Type", "application/x-www-form-urlencoded" ); + jobToResponseMap.insert(job, ""); + + connect(job, SIGNAL(result(KJob*)), this, SLOT(bookmarkFolderResultSlot(KJob*))); + connect(job, SIGNAL(data(KIO::Job*, QByteArray)), this, SLOT(bookmarkFolderDataSlot(KIO::Job*, QByteArray))); + + return job; +} + +void OperaSyncHandler::deleteResourceOnServer(QString id) +{ + QOAuth::ParamMap requestMap; + requestMap.insert("api_method","delete"); + + QByteArray requestUrl = "https://link.api.opera.com/rest/bookmark/"; + + if (id.isEmpty()) + { + qDebug() << "Id is empty!"; + return; + } + + requestUrl.append(id.toUtf8()); + QByteArray postData = qoauth->createParametersString(requestUrl, QOAuth::POST, authToken, authTokenSecret, QOAuth::HMAC_SHA1, requestMap, QOAuth::ParseForRequestContent); + + kDebug() << "Deleting Resource : " << id; + kDebug() << "Post data is : " << postData; + + kDebug() << "Request Url is : " << requestUrl; + + KIO::TransferJob *job = KIO::http_post( KUrl(requestUrl), postData, KIO::HideProgressInfo ); + job->addMetaData("Content-Type", "application/x-www-form-urlencoded" ); + + connect(job, SIGNAL(result(KJob*)), this, SLOT(bookmarkResultSlot(KJob*))); + connect(job, SIGNAL(data(KIO::Job*, QByteArray)), this, SLOT(bookmarkDataSlot(KIO::Job*, QByteArray))); + +} + +//Get url for a bookmark from xml element of Opera bookmarks +QString OperaSyncHandler::getUrlFromResourceProperties(const QDomElement &item) +{ + if (item.tagName() != "resource") return QString(); + QDomNodeList propertiesList = item.elementsByTagName("properties"); + + if (propertiesList.size() > 0) + { + QDomElement properties = propertiesList.at(0).toElement(); + QDomNodeList uriList = properties.elementsByTagName("uri"); + if (uriList.size() > 0) + return uriList.at(0).toElement().text(); + } + + return QString(); +} + +//Get title for a bookmark or folder from xml element of Opera bookmarks +QString OperaSyncHandler::getTitleFromResourceProperties(const QDomElement &item) +{ + if (item.tagName() != "resource") return QString(); + + QDomNodeList propertiesList = item.elementsByTagName("properties"); + + if (propertiesList.size() > 0) + { + QDomElement properties = propertiesList.at(0).toElement(); + QDomNodeList titleList = properties.elementsByTagName("title"); + if (titleList.size() > 0) + return titleList.at(0).toElement().text(); + } + + return QString(); +} + +//Get id for a bookmark or folder from xml element of Opera bookmarks +QString OperaSyncHandler::getIdFromResource(const QDomElement &item) +{ + if (item.tagName() != "resource") return QString(); + + QDomNodeList idList = item.elementsByTagName("id"); + + if (idList.size() > 0) + { + return idList.at(0).toElement().text(); + } + + return QString(); +} + +//Get value of a child element of a dom node +QString OperaSyncHandler::getChildString(const QDomNode &node, const QString &name) +{ + QDomNodeList nodes = node.childNodes(); + + for (int j=0; j<nodes.size(); ++j) + { + QDomElement element = nodes.at(j).toElement(); + + if (nodes.at(j).nodeName() == name) + { + //kDebug() << "Url : " << element.text(); + return element.text(); + } + } + return NULL; +} + +//Get value of a child element of a dom node +QDomElement OperaSyncHandler::getChildElement(const QDomNode &node, const QString &name) +{ + QDomNodeList nodes = node.childNodes(); + + for (int j=0; j<nodes.size(); ++j) + { + QDomElement element = nodes.at(j).toElement(); + + if (nodes.at(j).nodeName() == name) + { + //kDebug() << "Url : " << element.text(); + return element; + } + } + return QDomElement(); +} +//Find a bookmark group in a specifiec bookmark group of client +KBookmarkGroup OperaSyncHandler::findLocalGroup(const KBookmarkGroup &root, const QString &name) +{ + KBookmark child = root.first(); + + while (!child.isNull()) + { + kDebug() << child.fullText(); + if (child.isGroup() && name == child.fullText()) + { + break; + } + child = root.next(child); + } + + return child.toGroup(); +} + +//Find a bookmark in a specifiec bookmark group of client +KBookmark OperaSyncHandler::findLocalBookmark(const KBookmarkGroup &root, const KUrl &url) +{ + KBookmark child = root.first(); + + kDebug() << "finding bookmark " << url << " in : " << root.text(); + + while (!child.isNull()) + { + kDebug() << child.url(); + if (!child.isGroup() && url == child.url()) + { + break; + } + child = root.next(child); + } + + return child; +} + +//Find bookmark folder in xml returned by server +QDomElement OperaSyncHandler::findOperaFolder(const QDomElement &root, const QString &name) +{ + QDomElement current = root.firstChild().toElement(); + + kDebug() << "Finding group " << name; + while (!current.isNull()) + { +// kDebug() << "in " << getTitleFromResourceProperties(current); + if ((getChildString(current, "item_type") == "bookmark_folder") && getTitleFromResourceProperties(current) == name) + break; + current = current.nextSibling().toElement(); + } + + return current; +} + +//Find bookmark in xml returned by server +QDomElement OperaSyncHandler::findOperaBookmark(const QDomElement &root, const KUrl &url) +{ + QDomElement current = root.firstChild().toElement(); + + kDebug() << "Finding bookmark " << url; + while (!current.isNull() ) + { +// kDebug() << "in " << getUrlFromResourceProperties(current); + if ((getChildString(current, "item_type") == "bookmark") && KUrl(getUrlFromResourceProperties(current)) == url) + break; + current = current.nextSibling().toElement(); + } + + return current; +} diff --git a/src/sync/operasynchandler.h b/src/sync/operasynchandler.h new file mode 100644 index 00000000..5131425f --- /dev/null +++ b/src/sync/operasynchandler.h @@ -0,0 +1,142 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com> +* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef OPERA_SYNC_HANDLER_H +#define OPERA_SYNC_HANDLER_H + +#include <QWebPage> + +// Local Includes +#include "synchandler.h" + +// KDE Includes +#include <KUrl> +#include <KBookmarkGroup> +#include <KIO/Job> + +// Qt Includes +#include <QtOAuth/QtOAuth> + +// Forward Declarations +class QNetworkReply; +class BookmarkManager; +class QWebView; + +class OperaSyncHandler : public SyncHandler +{ + Q_OBJECT + +public: + OperaSyncHandler(QObject *parent = 0); + + void syncHistory(); + void syncBookmarks(); + void syncPasswords(); + + void initialLoadAndCheck(); + +private Q_SLOTS: + void loadFinished(bool); +/* void fetchingBookmarksFinished(); + void updateBookmarkFinished(); +*/ + void dataSlot(KIO::Job*, QByteArray); + void resultSlot(KJob*); + + void bookmarkDataSlot(KIO::Job*, QByteArray); + void bookmarkResultSlot(KJob*); + + void bookmarkFolderDataSlot(KIO::Job*, QByteArray); + void bookmarkFolderResultSlot(KJob*); + +Q_SIGNALS: + void syncBookmarksFinished(bool); + void syncHistoryFinished(bool); + void syncPasswordsFinished(bool); + +private: + enum {SEND_CHANGES, RECEIVE_CHANGES} _mode; + enum BookmarkType {BOOKMARK, BOOKMARK_FOLDER}; + + bool syncRelativeEnabled(bool); + void startLogin(); + void getBookmarks(); + void handleBookmark(const QDomElement &item, KBookmarkGroup root); + void handleBookmarkFolder(const QDomElement &item, KBookmarkGroup &root); + void handleResource(const QDomNode &item, KBookmarkGroup &root); + +// void handleLocalBookmark(const KBookmarkGroup &root, const QDomElement &item); + void handleLocalGroup(const KBookmarkGroup &root, const QDomElement &item, QString parentId); + + void addBookmarkOnServer(QString, QString, QString parent = QString()); + KJob *addBookmarkFolderOnServer(QString, QString parent = QString()); + void deleteResourceOnServer(QString id); + + static QString getUrlFromResourceProperties(const QDomElement &item); + static QString getTitleFromResourceProperties(const QDomElement &item); + static QString getIdFromResource(const QDomElement &item); + static QString getChildString(const QDomNode &node, const QString &name); + static QDomElement getChildElement(const QDomNode &node, const QString &name); + + static KBookmarkGroup findLocalGroup(const KBookmarkGroup &root, const QString &name); + static KBookmark findLocalBookmark(const KBookmarkGroup &root, const KUrl &url); + + static QDomElement findOperaFolder(const QDomElement &root, const QString &name); + static QDomElement findOperaBookmark(const QDomElement &root, const KUrl &url); + +/* void checkToAddGB(const KBookmarkGroup &root, const QDomNodeList &); + void checkToDeleteGB(BookmarkManager *, const QDomNodeList &); + QString getChildElement(const QDomNode &node, QString name); + void checkRequestCount();*/ + + + // QUrl _remoteBookmarksUrl; + bool _doLogin; + + QWebPage _webPage; +/* QNetworkReply *_reply; + QSet<KUrl> _bookmarksToAdd; + QSet<QString> _bookmarksToDelete; + unsigned int _requestCount;*/ + + bool _isSyncing; + + QOAuth::Interface *qoauth; + QOAuth::ParamMap requestParam, resultParam, authParams; + QByteArray requestToken, requestTokenSecret; + QByteArray authToken, authTokenSecret; + + QUrl url; +// QSslSocket *socket; + QByteArray urlParams; + QWebView *webView; + QByteArray xmlData; + QMap<KJob*, QByteArray> jobToResponseMap; + QMap<KJob*, KBookmarkGroup> jobToGroupMap; +}; + +#endif // OPERA_SYNC_HANDLER_H diff --git a/src/sync/sync_host_type.ui b/src/sync/sync_host_type.ui index ba96ab83..ed7e1cd9 100644 --- a/src/sync/sync_host_type.ui +++ b/src/sync/sync_host_type.ui @@ -32,6 +32,13 @@ </widget> </item> <item> + <widget class="QRadioButton" name="operaRadioButton"> + <property name="text"> + <string>Opera Bookmarks</string> + </property> + </widget> + </item> + <item> <widget class="QRadioButton" name="nullRadioButton"> <property name="text"> <string>/dev/null</string> diff --git a/src/sync/sync_opera_settings.ui b/src/sync/sync_opera_settings.ui new file mode 100644 index 00000000..5144c552 --- /dev/null +++ b/src/sync/sync_opera_settings.ui @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SyncOperaSettings</class> + <widget class="QWidget" name="SyncOperaSettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="operaGroupBox"> + <property name="title"> + <string>Opera Account Settings</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="KLineEdit" name="kcfg_syncUser"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="KLineEdit" name="kcfg_syncPass"/> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>124</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KLineEdit</class> + <extends>QLineEdit</extends> + <header>klineedit.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/sync/syncassistant.cpp b/src/sync/syncassistant.cpp index 651cad75..078ff375 100644 --- a/src/sync/syncassistant.cpp +++ b/src/sync/syncassistant.cpp @@ -35,6 +35,7 @@ #include "syncftpsettingswidget.h" #include "syncgooglesettingswidget.h" +#include "syncoperasettingswidget.h" SyncAssistant::SyncAssistant(QWidget *parent) @@ -46,5 +47,6 @@ SyncAssistant::SyncAssistant(QWidget *parent) setPage(Page_Type, new SyncHostTypeWidget(this)); setPage(Page_FTP_Settings, new SyncFTPSettingsWidget(this)); setPage(Page_Google_Settings, new SyncGoogleSettingsWidget(this)); + setPage(Page_Opera_Settings, new SyncOperaSettingsWidget(this)); setPage(Page_Check, new SyncCheckWidget(this)); } diff --git a/src/sync/syncassistant.h b/src/sync/syncassistant.h index e09db71a..263c918a 100644 --- a/src/sync/syncassistant.h +++ b/src/sync/syncassistant.h @@ -43,6 +43,7 @@ public: Page_Type, Page_FTP_Settings, Page_Google_Settings, + Page_Opera_Settings, Page_Check }; diff --git a/src/sync/synccheckwidget.cpp b/src/sync/synccheckwidget.cpp index 5fdf5cd7..7d44c580 100644 --- a/src/sync/synccheckwidget.cpp +++ b/src/sync/synccheckwidget.cpp @@ -65,6 +65,11 @@ void SyncCheckWidget::initializePage() syncLabel->setText(i18n("Google")); hostLabel->setText(ReKonfig::syncHost()); } + else if (ReKonfig::syncType() == 2) + { + syncLabel->setText(i18n("Opera")); + hostLabel->setText(ReKonfig::syncHost()); + } else { syncLabel->setText(i18n("No sync")); diff --git a/src/sync/synchosttypewidget.cpp b/src/sync/synchosttypewidget.cpp index d52baf34..73f9a7cb 100644 --- a/src/sync/synchosttypewidget.cpp +++ b/src/sync/synchosttypewidget.cpp @@ -42,8 +42,10 @@ SyncHostTypeWidget::SyncHostTypeWidget(QWidget *parent) if (ReKonfig::syncType() == 0) ftpRadioButton->setChecked(true); - else if (ReKonfig::syncType() == 1) + else if(ReKonfig::syncType() == 1) googleRadioButton->setChecked(true); + else if(ReKonfig::syncType() == 2) + operaRadioButton->setChecked(true); else nullRadioButton->setChecked(true); } @@ -57,14 +59,19 @@ int SyncHostTypeWidget::nextId() const ReKonfig::setSyncType(0); return SyncAssistant::Page_FTP_Settings; } - else if (googleRadioButton->isChecked()) + else if (googleRadioButton->isChecked()) + { + ReKonfig::setSyncType(1); + return SyncAssistant::Page_Google_Settings; + } + else if (operaRadioButton->isChecked()) { - ReKonfig::setSyncType(1); - return SyncAssistant::Page_Google_Settings; + ReKonfig::setSyncType(2); + return SyncAssistant::Page_Opera_Settings; } else { - ReKonfig::setSyncType(2); + ReKonfig::setSyncType(3); return SyncAssistant::Page_Check; } diff --git a/src/sync/syncmanager.cpp b/src/sync/syncmanager.cpp index aeb543d0..a4acb80b 100644 --- a/src/sync/syncmanager.cpp +++ b/src/sync/syncmanager.cpp @@ -39,6 +39,7 @@ #include "syncassistant.h" #include "ftpsynchandler.h" #include "googlesynchandler.h" +#include "operasynchandler.h" // KDE Includes #include <klocalizedstring.h> @@ -83,6 +84,9 @@ void SyncManager::loadSettings() case 1: _syncImplementation = new GoogleSyncHandler(this); break; + case 2: + _syncImplementation = new OperaSyncHandler(this); + break; default: kDebug() << "/dev/null"; return; diff --git a/src/sync/syncoperasettingswidget.cpp b/src/sync/syncoperasettingswidget.cpp new file mode 100644 index 00000000..0b5e3386 --- /dev/null +++ b/src/sync/syncoperasettingswidget.cpp @@ -0,0 +1,60 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com> +* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "syncoperasettingswidget.h" +#include "syncoperasettingswidget.moc" + +// Auto Includes +#include "rekonq.h" + +// Local Includes +#include "syncassistant.h" + + +SyncOperaSettingsWidget::SyncOperaSettingsWidget(QWidget *parent) + : QWizardPage(parent) +{ + setupUi(this); + kcfg_syncUser->setText(ReKonfig::syncUser()); + kcfg_syncPass->setText(ReKonfig::syncPass()); + + kcfg_syncPass->setPasswordMode(true); +} + + +int SyncOperaSettingsWidget::nextId() const +{ + // save + ReKonfig::setSyncHost("http://link.opera.com/"); + ReKonfig::setSyncUser(kcfg_syncUser->text()); + ReKonfig::setSyncPass(kcfg_syncPass->text()); + + ReKonfig::setSyncHistory(false); + ReKonfig::setSyncPasswords(false); + + return SyncAssistant::Page_Check; +} diff --git a/src/sync/syncoperasettingswidget.h b/src/sync/syncoperasettingswidget.h new file mode 100644 index 00000000..5eb608d3 --- /dev/null +++ b/src/sync/syncoperasettingswidget.h @@ -0,0 +1,52 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2011 by Siteshwar Vashisht <siteshwar AT gmail.com> +* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef SYNC_OPERA_SETTINGS_WIDGET_H +#define SYNC_OPERA_SETTINGS_WIDGET_H + + +// Rekonq Includes +#include "rekonq_defines.h" + +// Ui Includes +#include "ui_sync_opera_settings.h" + +// Qt Includes +#include <QWizardPage> + + +class SyncOperaSettingsWidget : public QWizardPage, private Ui::SyncOperaSettings +{ + Q_OBJECT + +public: + SyncOperaSettingsWidget(QWidget *parent = 0); + + int nextId() const; +}; + +#endif // SYNC_OPERA_SETTINGS_WIDGET_H |