diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03cef4e..1742abb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,81 +1,82 @@ set(kblog_SRCS blog.cpp blogcomment.cpp blogmedia.cpp blogger1.cpp + feedretriever.cpp gdata.cpp # livejournal.cpp metaweblog.cpp movabletype.cpp wordpressbuggy.cpp blogpost.cpp ) if( KPimGAPI_FOUND ) set(kblog_SRCS ${kblog_SRCS} blogger.cpp) endif() ecm_qt_declare_logging_category(kblog_SRCS HEADER kblog_debug.h IDENTIFIER KBLOG_LOG CATEGORY_NAME org.kde.pim.kblog) configure_file(blog_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/blog_config.h @ONLY) add_library(KF5Blog ${kblog_SRCS}) generate_export_header(KF5Blog BASE_NAME kblog) add_library(KF5::Blog ALIAS KF5Blog) target_include_directories(KF5Blog INTERFACE "$") target_include_directories(KF5Blog PUBLIC "$") target_link_libraries(KF5Blog PUBLIC KF5::Syndication KF5::CalendarCore PRIVATE KF5::XmlRpcClient KF5::CoreAddons KF5::KIOCore KF5::I18n ) set_target_properties(KF5Blog PROPERTIES VERSION ${KBLOG_VERSION_STRING} SOVERSION ${KBLOG_SOVERSION} EXPORT_NAME Blog ) install(TARGETS KF5Blog EXPORT KF5BlogTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) ecm_generate_headers(KBlog_CamelCase_HEADERS HEADER_NAMES Blog BlogComment Blogger1 BlogMedia BlogPost GData MetaWeblog MovableType WordpressBuggy PREFIX KBlog REQUIRED_HEADERS KBlog_HEADERS ) install(FILES ${KBlog_BINARY_DIR}/src/kblog_export.h ${KBlog_HEADERS} ${KBlog_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KBlog/kblog COMPONENT Devel ) install(FILES ${KBlog_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KBlog/KBlog COMPONENT Devel ) ecm_generate_pri_file(BASE_NAME KBlog LIB_NAME KF5Blog DEPS "Syndication CalendarCore" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KBlog) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/feedretriever.cpp b/src/feedretriever.cpp new file mode 100644 index 0000000..9d481c6 --- /dev/null +++ b/src/feedretriever.cpp @@ -0,0 +1,68 @@ +/* + This file is part of Akregator. + + Copyright (C) 2018 Daniel Vrátil + + 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) any later version. + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "feedretriever.h" + +#include + +#include + +using namespace KBlog; + +FeedRetriever::FeedRetriever() + : Syndication::DataRetriever() +{ +} + +void FeedRetriever::retrieveData(const QUrl &url) +{ + auto job = KIO::storedGet(url, KIO::NoReload, KIO::HideProgressInfo); + connect(job, &KJob::result, this, &FeedRetriever::getFinished); + mJob = job; + mJob->start(); +} + +int FeedRetriever::errorCode() const +{ + return mError; +} + +void FeedRetriever::abort() +{ + if (mJob) { + mJob->kill(); + mJob = nullptr; + } +} + +void FeedRetriever::getFinished(KJob *job) +{ + if (job->error()) { + mError = job->error(); + Q_EMIT dataRetrieved({}, false); + return; + } + + Q_EMIT dataRetrieved(static_cast(job)->data(), true); +} diff --git a/src/feedretriever.h b/src/feedretriever.h new file mode 100644 index 0000000..fb28020 --- /dev/null +++ b/src/feedretriever.h @@ -0,0 +1,54 @@ +/* + This file is part of Akregator. + + Copyright (C) 2018 Daniel Vrátil + + 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) any later version. + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef FEEDRETRIEVER_H_ +#define FEEDRETRIEVER_H_ + +#include + +class KJob; + +namespace KBlog { + +class FeedRetriever : public Syndication::DataRetriever +{ + Q_OBJECT +public: + explicit FeedRetriever(); + + void retrieveData(const QUrl &url) override; + void abort() override; + int errorCode() const override; + +private Q_SLOTS: + void getFinished(KJob *job); + +private: + KJob *mJob = nullptr; + int mError = 0; +}; + +} + +#endif diff --git a/src/gdata.cpp b/src/gdata.cpp index 9ca5b84..115e0a0 100644 --- a/src/gdata.cpp +++ b/src/gdata.cpp @@ -1,999 +1,1000 @@ /* This file is part of the kblog library. Copyright (c) 2007 Christian Weilbach This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "gdata.h" #include "gdata_p.h" #include "blogpost.h" #include "blogcomment.h" +#include "feedretriever.h" #include #include #include #include #include "kblog_debug.h" #include #include #include #include #include #define TIMEOUT 600 using namespace KBlog; GData::GData(const QUrl &server, QObject *parent) : Blog(server, *new GDataPrivate, parent) { qCDebug(KBLOG_LOG); setUrl(server); } GData::~GData() { qCDebug(KBLOG_LOG); } QString GData::interfaceName() const { qCDebug(KBLOG_LOG); return QStringLiteral("Google Blogger Data"); } QString GData::fullName() const { qCDebug(KBLOG_LOG); return d_func()->mFullName; } void GData::setFullName(const QString &fullName) { qCDebug(KBLOG_LOG); Q_D(GData); d->mFullName = fullName; } QString GData::profileId() const { qCDebug(KBLOG_LOG); return d_func()->mProfileId; } void GData::setProfileId(const QString &pid) { qCDebug(KBLOG_LOG); Q_D(GData); d->mProfileId = pid; } void GData::fetchProfileId() { qCDebug(KBLOG_LOG); QByteArray data; KIO::StoredTransferJob *job = KIO::storedGet(url(), KIO::NoReload, KIO::HideProgressInfo); QUrl blogUrl = url(); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotFetchProfileId(KJob*))); } void GData::listBlogs() { qCDebug(KBLOG_LOG); Syndication::Loader *loader = Syndication::Loader::create(); connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode)), this, SLOT(slotListBlogs(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode))); - loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/blogs").arg(profileId()))); + loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/blogs").arg(profileId())), new FeedRetriever); } void GData::listRecentPosts(const QStringList &labels, int number, const QDateTime &upMinTime, const QDateTime &upMaxTime, const QDateTime &pubMinTime, const QDateTime &pubMaxTime) { qCDebug(KBLOG_LOG); Q_D(GData); QString urlString(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/posts/default")); if (! labels.empty()) { urlString += QStringLiteral("/-/") + labels.join(QLatin1Char('/')); } qCDebug(KBLOG_LOG) << "listRecentPosts()"; QUrl url(urlString); QUrlQuery q; if (!upMinTime.isNull()) { q.addQueryItem(QStringLiteral("updated-min"), upMinTime.toUTC().toString(QStringLiteral("yyyy-MM-ddTHH:mm:ssZ"))); } if (!upMaxTime.isNull()) { q.addQueryItem(QStringLiteral("updated-max"), upMaxTime.toUTC().toString(QStringLiteral("yyyy-MM-ddTHH:mm:ssZ"))); } if (!pubMinTime.isNull()) { q.addQueryItem(QStringLiteral("published-min"), pubMinTime.toUTC().toString(QStringLiteral("yyyy-MM-ddTHH:mm:ssZ"))); } if (!pubMaxTime.isNull()) { q.addQueryItem(QStringLiteral("published-max"), pubMaxTime.toUTC().toString(QStringLiteral("yyyy-MM-ddTHH:mm:ssZ"))); } url.setQuery(q); Syndication::Loader *loader = Syndication::Loader::create(); if (number > 0) { d->mListRecentPostsMap[ loader ] = number; } connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode)), this, SLOT(slotListRecentPosts(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode))); - loader->loadFrom(url); + loader->loadFrom(url, new FeedRetriever); } void GData::listRecentPosts(int number) { qCDebug(KBLOG_LOG); listRecentPosts(QStringList(), number); } void GData::listComments(KBlog::BlogPost *post) { qCDebug(KBLOG_LOG); Q_D(GData); Syndication::Loader *loader = Syndication::Loader::create(); d->mListCommentsMap[ loader ] = post; connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode)), this, SLOT(slotListComments(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode))); loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QLatin1Char('/') + - post->postId() + QStringLiteral("/comments/default"))); + post->postId() + QStringLiteral("/comments/default")), new FeedRetriever); } void GData::listAllComments() { qCDebug(KBLOG_LOG); Syndication::Loader *loader = Syndication::Loader::create(); connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode)), this, SLOT(slotListAllComments(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode))); - loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/comments/default").arg(blogId()))); + loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/comments/default").arg(blogId())), new FeedRetriever); } void GData::fetchPost(KBlog::BlogPost *post) { qCDebug(KBLOG_LOG); Q_D(GData); if (!post) { qCritical() << "post is null pointer"; return; } qCDebug(KBLOG_LOG); Syndication::Loader *loader = Syndication::Loader::create(); d->mFetchPostMap[ loader ] = post; connect(loader, SIGNAL(loadingComplete(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode)), this, SLOT(slotFetchPost(Syndication::Loader*,Syndication::FeedPtr,Syndication::ErrorCode))); - loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/posts/default").arg(blogId()))); + loader->loadFrom(QUrl(QStringLiteral("http://www.blogger.com/feeds/%1/posts/default").arg(blogId())), new FeedRetriever); } void GData::modifyPost(KBlog::BlogPost *post) { qCDebug(KBLOG_LOG); Q_D(GData); if (!post) { qCritical() << "post is null pointer"; return; } if (!d->authenticate()) { qCritical() << "Authentication failed."; emit errorPost(Atom, i18n("Authentication failed."), post); return; } QString atomMarkup = QStringLiteral(""); atomMarkup += QStringLiteral("tag:blogger.com,1999:blog-") + blogId(); atomMarkup += QStringLiteral(".post-") + post->postId() + QStringLiteral(""); atomMarkup += QStringLiteral("") + post->creationDateTime().toString() + QStringLiteral(""); atomMarkup += QStringLiteral("") + post->modificationDateTime().toString() + QStringLiteral(""); atomMarkup += QStringLiteral("") + post->title() + QStringLiteral(""); if (post->isPrivate()) { atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("yes"); } atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("
"); atomMarkup += post->content(); atomMarkup += QStringLiteral("
"); foreach (const QString &tag, post->tags()) { atomMarkup += QStringLiteral(""); } atomMarkup += QStringLiteral(""); if (!fullName().isEmpty()) { atomMarkup += QStringLiteral("") + fullName() + QStringLiteral(""); } atomMarkup += QStringLiteral("") + username() + QStringLiteral(""); atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("
"); QByteArray postData; QDataStream stream(&postData, QIODevice::WriteOnly); stream.writeRawData(atomMarkup.toUtf8().constData(), atomMarkup.toUtf8().length()); KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/posts/default/") + post->postId()), KIO::HideProgressInfo); Q_ASSERT(job); d->mModifyPostMap[ job ] = post; job->addMetaData(QStringLiteral("content-type"), QStringLiteral("Content-Type: application/atom+xml; charset=utf-8")); job->addMetaData(QStringLiteral("ConnectTimeout"), QStringLiteral("50")); job->addMetaData(QStringLiteral("UserAgent"), userAgent()); job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: GoogleLogin auth=") + d->mAuthenticationString + QStringLiteral("\r\nX-HTTP-Method-Override: PUT")); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotModifyPost(KJob*))); } void GData::createPost(KBlog::BlogPost *post) { qCDebug(KBLOG_LOG); Q_D(GData); if (!post) { qCritical() << "post is null pointer"; return; } if (!d->authenticate()) { qCritical() << "Authentication failed."; emit errorPost(Atom, i18n("Authentication failed."), post); return; } QString atomMarkup = QStringLiteral(""); atomMarkup += QStringLiteral("") + post->title() + QStringLiteral(""); if (post->isPrivate()) { atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("yes"); } atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("
"); atomMarkup += post->content(); // FIXME check for Utf atomMarkup += QStringLiteral("
"); QList::ConstIterator it = post->tags().constBegin(); QList::ConstIterator end = post->tags().constEnd(); for (; it != end; ++it) { atomMarkup += QStringLiteral(""); } atomMarkup += QStringLiteral(""); if (!fullName().isEmpty()) { atomMarkup += QStringLiteral("") + fullName() + QStringLiteral(""); } atomMarkup += QStringLiteral("") + username() + QStringLiteral(""); atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("
"); QByteArray postData; QDataStream stream(&postData, QIODevice::WriteOnly); stream.writeRawData(atomMarkup.toUtf8().constData(), atomMarkup.toUtf8().length()); KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/posts/default")), KIO::HideProgressInfo); Q_ASSERT(job); d->mCreatePostMap[ job ] = post; job->addMetaData(QStringLiteral("content-type"), QStringLiteral("Content-Type: application/atom+xml; charset=utf-8")); job->addMetaData(QStringLiteral("ConnectTimeout"), QStringLiteral("50")); job->addMetaData(QStringLiteral("UserAgent"), userAgent()); job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: GoogleLogin auth=") + d->mAuthenticationString); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotCreatePost(KJob*))); } void GData::removePost(KBlog::BlogPost *post) { qCDebug(KBLOG_LOG); Q_D(GData); if (!post) { qCritical() << "post is null pointer"; return; } if (!d->authenticate()) { qCritical() << "Authentication failed."; emit errorPost(Atom, i18n("Authentication failed."), post); return; } QByteArray postData; KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/posts/default/") + post->postId()), KIO::HideProgressInfo); if (!job) { qCWarning(KBLOG_LOG) << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << QStringLiteral("/posts/default/") + post->postId(); return; } d->mRemovePostMap[ job ] = post; job->addMetaData(QStringLiteral("ConnectTimeout"), QStringLiteral("50")); job->addMetaData(QStringLiteral("UserAgent"), userAgent()); job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: GoogleLogin auth=") + d->mAuthenticationString + QStringLiteral("\r\nX-HTTP-Method-Override: DELETE")); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotRemovePost(KJob*))); } void GData::createComment(KBlog::BlogPost *post, KBlog::BlogComment *comment) { qCDebug(KBLOG_LOG); if (!comment) { qCritical() << "comment is null pointer"; return; } if (!post) { qCritical() << "post is null pointer"; return; } Q_D(GData); if (!d->authenticate()) { qCritical() << "Authentication failed."; emit errorComment(Atom, i18n("Authentication failed."), post, comment); return; } QString atomMarkup = QStringLiteral(""); atomMarkup += QStringLiteral("") + comment->title() + QStringLiteral(""); atomMarkup += QStringLiteral("") + comment->content() + QStringLiteral(""); atomMarkup += QStringLiteral(""); atomMarkup += QStringLiteral("") + comment->name() + QStringLiteral(""); atomMarkup += QStringLiteral("") + comment->email() + QStringLiteral(""); atomMarkup += QStringLiteral(""); QByteArray postData; qCDebug(KBLOG_LOG) << postData; QDataStream stream(&postData, QIODevice::WriteOnly); stream.writeRawData(atomMarkup.toUtf8().constData(), atomMarkup.toUtf8().length()); KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/") + post->postId() + QStringLiteral("/comments/default")), KIO::HideProgressInfo); if (!job) { qCWarning(KBLOG_LOG) << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << "/" << post->postId() << "/comments/default"; return; } d->mCreateCommentMap[ job ][post] = comment; job->addMetaData(QStringLiteral("content-type"), QStringLiteral("Content-Type: application/atom+xml; charset=utf-8")); job->addMetaData(QStringLiteral("ConnectTimeout"), QStringLiteral("50")); job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: GoogleLogin auth=") + d->mAuthenticationString); job->addMetaData(QStringLiteral("UserAgent"), userAgent()); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotCreateComment(KJob*))); } void GData::removeComment(KBlog::BlogPost *post, KBlog::BlogComment *comment) { qCDebug(KBLOG_LOG); Q_D(GData); qCDebug(KBLOG_LOG); if (!comment) { qCritical() << "comment is null pointer"; return; } if (!post) { qCritical() << "post is null pointer"; return; } if (!d->authenticate()) { qCritical() << "Authentication failed."; emit errorComment(Atom, i18n("Authentication failed."), post, comment); return; } QByteArray postData; KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, QUrl(QStringLiteral("http://www.blogger.com/feeds/") + blogId() + QStringLiteral("/") + post->postId() + QStringLiteral("/comments/default/") + comment->commentId()), KIO::HideProgressInfo); d->mRemoveCommentMap[ job ][ post ] = comment; if (!job) { qCWarning(KBLOG_LOG) << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << post->postId() << "/comments/default/" << comment->commentId(); } job->addMetaData(QStringLiteral("ConnectTimeout"), QStringLiteral("50")); job->addMetaData(QStringLiteral("UserAgent"), userAgent()); job->addMetaData(QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: GoogleLogin auth=") + d->mAuthenticationString + QStringLiteral("\r\nX-HTTP-Method-Override: DELETE")); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotRemoveComment(KJob*))); } GDataPrivate::GDataPrivate(): mAuthenticationString(), mAuthenticationTime() { qCDebug(KBLOG_LOG); } GDataPrivate::~GDataPrivate() { qCDebug(KBLOG_LOG); } bool GDataPrivate::authenticate() { qCDebug(KBLOG_LOG); Q_Q(GData); QByteArray data; QUrl authGateway(QStringLiteral("https://www.google.com/accounts/ClientLogin")); QUrlQuery query; query.addQueryItem(QStringLiteral("Email"), q->username()); query.addQueryItem(QStringLiteral("Passwd"), q->password()); query.addQueryItem(QStringLiteral("source"), q->userAgent()); query.addQueryItem(QStringLiteral("service"), QStringLiteral("blogger")); authGateway.setQuery(query); if (!mAuthenticationTime.isValid() || QDateTime::currentDateTime().toTime_t() - mAuthenticationTime.toTime_t() > TIMEOUT || mAuthenticationString.isEmpty()) { KIO::TransferJob *job = KIO::http_post(authGateway, QByteArray(), KIO::HideProgressInfo); QObject::connect(job, &KIO::TransferJob::data, q, [&data](KIO::Job *, const QByteArray &newdata) { data.reserve(data.size() + newdata.size()); memcpy(data.data() + data.size(), newdata.data(), newdata.size()); }); if (job->exec()) { QRegExp rx(QStringLiteral("Auth=(.+)")); if (rx.indexIn(QLatin1String(data)) != -1) { qCDebug(KBLOG_LOG) << "RegExp got authentication string:" << rx.cap(1); mAuthenticationString = rx.cap(1); mAuthenticationTime = QDateTime::currentDateTime(); return true; } } return false; } return true; } void GDataPrivate::slotFetchProfileId(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } Q_Q(GData); KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); if (!job->error()) { QRegExp pid(QStringLiteral("http://www.blogger.com/profile/(\\d+)")); if (pid.indexIn(data) != -1) { q->setProfileId(pid.cap(1)); qCDebug(KBLOG_LOG) << "QRegExp bid( 'http://www.blogger.com/profile/(\\d+)' matches" << pid.cap(1); emit q->fetchedProfileId(pid.cap(1)); } else { qCritical() << "QRegExp bid( 'http://www.blogger.com/profile/(\\d+)' " << " could not regexp the Profile ID"; emit q->error(GData::Other, i18n("Could not regexp the Profile ID.")); emit q->fetchedProfileId(QString()); } } else { qCritical() << "Job Error: " << job->errorString(); emit q->error(GData::Other, job->errorString()); emit q->fetchedProfileId(QString()); } } void GDataPrivate::slotListBlogs(Syndication::Loader *loader, const Syndication::FeedPtr &feed, Syndication::ErrorCode status) { qCDebug(KBLOG_LOG); Q_Q(GData); if (!loader) { qCritical() << "loader is a null pointer."; return; } if (status != Syndication::Success) { emit q->error(GData::Atom, i18n("Could not get blogs.")); return; } QList > blogsList; QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for (; it != end; ++it) { QRegExp rx(QStringLiteral("blog-(\\d+)")); QMap blogInfo; if (rx.indexIn((*it)->id()) != -1) { qCDebug(KBLOG_LOG) << "QRegExp rx( 'blog-(\\d+)' matches" << rx.cap(1); blogInfo[QStringLiteral("id")] = rx.cap(1); blogInfo[QStringLiteral("title")] = (*it)->title(); blogInfo[QStringLiteral("url")] = (*it)->link(); blogInfo[QStringLiteral("summary")] = (*it)->description(); //TODO fix/add more blogsList << blogInfo; } else { qCritical() << "QRegExp rx( 'blog-(\\d+)' does not match anything in:" << (*it)->id(); emit q->error(GData::Other, i18n("Could not regexp the blog id path.")); } } qCDebug(KBLOG_LOG) << "Emitting listedBlogs(); "; emit q->listedBlogs(blogsList); } void GDataPrivate::slotListComments(Syndication::Loader *loader, const Syndication::FeedPtr &feed, Syndication::ErrorCode status) { qCDebug(KBLOG_LOG); Q_Q(GData); if (!loader) { qCritical() << "loader is a null pointer."; return; } BlogPost *post = mListCommentsMap[ loader ]; mListCommentsMap.remove(loader); if (status != Syndication::Success) { emit q->errorPost(GData::Atom, i18n("Could not get comments."), post); return; } QList commentList; QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for (; it != end; ++it) { BlogComment comment; QRegExp rx(QStringLiteral("post-(\\d+)")); if (rx.indexIn((*it)->id()) == -1) { qCritical() << "QRegExp rx( 'post-(\\d+)' does not match" << rx.cap(1); emit q->error(GData::Other, i18n("Could not regexp the comment id path.")); } else { comment.setCommentId(rx.cap(1)); } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); comment.setTitle((*it)->title()); comment.setContent((*it)->content()); // FIXME: assuming UTC for now comment.setCreationDateTime(QDateTime::fromTime_t((*it)->datePublished())); comment.setModificationDateTime(QDateTime::fromTime_t((*it)->dateUpdated())); commentList.append(comment); } qCDebug(KBLOG_LOG) << "Emitting listedComments()"; emit q->listedComments(post, commentList); } void GDataPrivate::slotListAllComments(Syndication::Loader *loader, const Syndication::FeedPtr &feed, Syndication::ErrorCode status) { qCDebug(KBLOG_LOG); Q_Q(GData); if (!loader) { qCritical() << "loader is a null pointer."; return; } if (status != Syndication::Success) { emit q->error(GData::Atom, i18n("Could not get comments.")); return; } QList commentList; QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for (; it != end; ++it) { BlogComment comment; QRegExp rx(QStringLiteral("post-(\\d+)")); if (rx.indexIn((*it)->id()) == -1) { qCritical() << "QRegExp rx( 'post-(\\d+)' does not match" << rx.cap(1); emit q->error(GData::Other, i18n("Could not regexp the comment id path.")); } else { comment.setCommentId(rx.cap(1)); } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); comment.setTitle((*it)->title()); comment.setContent((*it)->content()); // FIXME: assuming UTC for now comment.setCreationDateTime(QDateTime::fromTime_t((*it)->datePublished())); comment.setModificationDateTime(QDateTime::fromTime_t((*it)->dateUpdated())); commentList.append(comment); } qCDebug(KBLOG_LOG) << "Emitting listedAllComments()"; emit q->listedAllComments(commentList); } void GDataPrivate::slotListRecentPosts(Syndication::Loader *loader, const Syndication::FeedPtr &feed, Syndication::ErrorCode status) { qCDebug(KBLOG_LOG); Q_Q(GData); if (!loader) { qCritical() << "loader is a null pointer."; return; } if (status != Syndication::Success) { emit q->error(GData::Atom, i18n("Could not get posts.")); return; } int number = 0; if (mListRecentPostsMap.contains(loader)) { number = mListRecentPostsMap[ loader ]; } mListRecentPostsMap.remove(loader); QList postList; QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for (; it != end; ++it) { BlogPost post; QRegExp rx(QStringLiteral("post-(\\d+)")); if (rx.indexIn((*it)->id()) == -1) { qCritical() << "QRegExp rx( 'post-(\\d+)' does not match" << rx.cap(1); emit q->error(GData::Other, i18n("Could not regexp the post id path.")); } else { post.setPostId(rx.cap(1)); } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); post.setTitle((*it)->title()); post.setContent((*it)->content()); post.setLink(QUrl((*it)->link())); QStringList labels; int catCount = (*it)->categories().count(); QList< Syndication::CategoryPtr > cats = (*it)->categories(); for (int i = 0; i < catCount; ++i) { if (cats[i]->label().isEmpty()) { labels.append(cats[i]->term()); } else { labels.append(cats[i]->label()); } } post.setTags(labels); // FIXME: assuming UTC for now post.setCreationDateTime(QDateTime::fromTime_t((*it)->datePublished())); post.setModificationDateTime(QDateTime::fromTime_t((*it)->dateUpdated())); post.setStatus(BlogPost::Fetched); postList.append(post); if (number-- == 0) { break; } } qCDebug(KBLOG_LOG) << "Emitting listedRecentPosts()"; emit q->listedRecentPosts(postList); } void GDataPrivate::slotFetchPost(Syndication::Loader *loader, const Syndication::FeedPtr &feed, Syndication::ErrorCode status) { qCDebug(KBLOG_LOG); Q_Q(GData); if (!loader) { qCritical() << "loader is a null pointer."; return; } bool success = false; BlogPost *post = mFetchPostMap.take(loader); qCritical() << "Post" << post; post->postId(); if (status != Syndication::Success) { emit q->errorPost(GData::Atom, i18n("Could not get posts."), post); return; } QString postId = post->postId(); QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for (; it != end; ++it) { QRegExp rx(QStringLiteral("post-(\\d+)")); if (rx.indexIn((*it)->id()) != -1 && rx.cap(1) == postId) { qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); post->setPostId(rx.cap(1)); post->setTitle((*it)->title()); post->setContent((*it)->content()); post->setStatus(BlogPost::Fetched); post->setLink(QUrl((*it)->link())); post->setCreationDateTime(QDateTime::fromTime_t((*it)->datePublished()).toLocalTime()); post->setModificationDateTime(QDateTime::fromTime_t((*it)->dateUpdated()).toLocalTime()); qCDebug(KBLOG_LOG) << "Emitting fetchedPost( postId=" << postId << ");"; success = true; emit q->fetchedPost(post); break; } } if (!success) { qCritical() << "QRegExp rx( 'post-(\\d+)' does not match" << mFetchPostMap[ loader ]->postId() << "."; emit q->errorPost(GData::Other, i18n("Could not regexp the blog id path."), post); } } void GDataPrivate::slotCreatePost(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); Q_Q(GData); KBlog::BlogPost *post = mCreatePostMap[ job ]; mCreatePostMap.remove(job); if (job->error() != 0) { qCritical() << "slotCreatePost error:" << job->errorString(); emit q->errorPost(GData::Atom, job->errorString(), post); return; } QRegExp rxId(QStringLiteral("post-(\\d+)")); //FIXME check and do better handling, esp the creation date time if (rxId.indexIn(data) == -1) { qCritical() << "Could not regexp the id out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the id out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub(QStringLiteral("(.+)")); if (rxPub.indexIn(data) == -1) { qCritical() << "Could not regexp the published time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the published time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp(QStringLiteral("(.+)")); if (rxUp.indexIn(data) == -1) { qCritical() << "Could not regexp the update time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the update time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); post->setPostId(rxId.cap(1)); post->setCreationDateTime(QDateTime::fromString(rxPub.cap(1))); post->setModificationDateTime(QDateTime::fromString(rxUp.cap(1))); post->setStatus(BlogPost::Created); qCDebug(KBLOG_LOG) << "Emitting createdPost()"; emit q->createdPost(post); } void GDataPrivate::slotModifyPost(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); KBlog::BlogPost *post = mModifyPostMap[ job ]; mModifyPostMap.remove(job); Q_Q(GData); if (job->error() != 0) { qCritical() << "slotModifyPost error:" << job->errorString(); emit q->errorPost(GData::Atom, job->errorString(), post); return; } QRegExp rxId(QStringLiteral("post-(\\d+)")); //FIXME check and do better handling, esp creation date time if (rxId.indexIn(data) == -1) { qCritical() << "Could not regexp the id out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the id out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub(QStringLiteral("(.+)")); if (rxPub.indexIn(data) == -1) { qCritical() << "Could not regexp the published time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the published time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp(QStringLiteral("(.+)")); if (rxUp.indexIn(data) == -1) { qCritical() << "Could not regexp the update time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the update time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); post->setPostId(rxId.cap(1)); post->setCreationDateTime(QDateTime::fromString(rxPub.cap(1))); post->setModificationDateTime(QDateTime::fromString(rxUp.cap(1))); post->setStatus(BlogPost::Modified); emit q->modifiedPost(post); } void GDataPrivate::slotRemovePost(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); KBlog::BlogPost *post = mRemovePostMap[ job ]; mRemovePostMap.remove(job); Q_Q(GData); if (job->error() != 0) { qCritical() << "slotRemovePost error:" << job->errorString(); emit q->errorPost(GData::Atom, job->errorString(), post); return; } post->setStatus(BlogPost::Removed); qCDebug(KBLOG_LOG) << "Emitting removedPost()"; emit q->removedPost(post); } void GDataPrivate::slotCreateComment(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); qCDebug(KBLOG_LOG) << "Dump data: " << data; Q_Q(GData); KBlog::BlogComment *comment = mCreateCommentMap[ job ].cbegin().value(); KBlog::BlogPost *post = mCreateCommentMap[ job ].cbegin().key(); mCreateCommentMap.remove(job); if (job->error() != 0) { qCritical() << "slotCreateComment error:" << job->errorString(); emit q->errorComment(GData::Atom, job->errorString(), post, comment); return; } // TODO check for result and fit appropriately QRegExp rxId(QStringLiteral("post-(\\d+)")); if (rxId.indexIn(data) == -1) { qCritical() << "Could not regexp the id out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the id out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub(QStringLiteral("(.+)")); if (rxPub.indexIn(data) == -1) { qCritical() << "Could not regexp the published time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the published time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp(QStringLiteral("(.+)")); if (rxUp.indexIn(data) == -1) { qCritical() << "Could not regexp the update time out of the result:" << data; emit q->errorPost(GData::Atom, i18n("Could not regexp the update time out of the result."), post); return; } qCDebug(KBLOG_LOG) << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); comment->setCommentId(rxId.cap(1)); comment->setCreationDateTime(QDateTime::fromString(rxPub.cap(1))); comment->setModificationDateTime(QDateTime::fromString(rxUp.cap(1))); comment->setStatus(BlogComment::Created); qCDebug(KBLOG_LOG) << "Emitting createdComment()"; emit q->createdComment(post, comment); } void GDataPrivate::slotRemoveComment(KJob *job) { qCDebug(KBLOG_LOG); if (!job) { qCritical() << "job is a null pointer."; return; } KIO::StoredTransferJob *stj = qobject_cast(job); const QString data = QString::fromUtf8(stj->data().constData(), stj->data().size()); Q_Q(GData); KBlog::BlogComment *comment = mRemoveCommentMap[ job ].cbegin().value(); KBlog::BlogPost *post = mRemoveCommentMap[ job ].cbegin().key(); mRemoveCommentMap.remove(job); if (job->error() != 0) { qCritical() << "slotRemoveComment error:" << job->errorString(); emit q->errorComment(GData::Atom, job->errorString(), post, comment); return; } comment->setStatus(BlogComment::Created); qCDebug(KBLOG_LOG) << "Emitting removedComment()"; emit q->removedComment(post, comment); } #include "moc_gdata.cpp"