diff --git a/kblog/blogger1.cpp b/kblog/blogger1.cpp index 59c1196d8..7b4491f0f 100644 --- a/kblog/blogger1.cpp +++ b/kblog/blogger1.cpp @@ -1,523 +1,524 @@ /* This file is part of the kblog library. Copyright (c) 2004 Reinhold Kainhofer Copyright (c) 2006-2007 Christian Weilbach Copyright (c) 2007-2008 Mike Arthur 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 "blogger1.h" #include "blogger1_p.h" #include "blogpost.h" #include #include #include #include #include #include using namespace KBlog; Blogger1::Blogger1( const KUrl &server, QObject *parent ) : Blog( server, *new Blogger1Private, parent ) { kDebug() << "Blogger1()"; setUrl( server ); } Blogger1::Blogger1( const KUrl &server, Blogger1Private &dd, QObject *parent ) : Blog( server, dd, parent ) { kDebug() << "Blogger1()"; setUrl( server ); } Blogger1::~Blogger1() { kDebug() << "~Blogger1()"; } QString Blogger1::interfaceName() const { return QLatin1String( "Blogger 1.0" ); } void Blogger1::setUrl( const KUrl &server ) { Q_D( Blogger1 ); Blog::setUrl( server ); delete d->mXmlRpcClient; d->mXmlRpcClient = new KXmlRpc::Client( server ); d->mXmlRpcClient->setUserAgent( userAgent() ); } void Blogger1::fetchUserInfo() { Q_D( Blogger1 ); kDebug() << "Fetch user's info..."; QList args( d->blogger1Args() ); d->mXmlRpcClient->call( "blogger.getUserInfo", args, this, SLOT(slotFetchUserInfo(const QList&,const QVariant&)), this, SLOT(slotError(int,const QString&,const QVariant&)) ); } void Blogger1::listBlogs() { Q_D( Blogger1 ); kDebug() << "Fetch List of Blogs..."; QList args( d->blogger1Args() ); d->mXmlRpcClient->call( "blogger.getUsersBlogs", args, this, SLOT(slotListBlogs(const QList&,const QVariant&)), this, SLOT(slotError(int,const QString&,const QVariant&)) ); } void Blogger1::listRecentPosts( int number ) { Q_D( Blogger1 ); kDebug() << "Fetching List of Posts..."; QList args( d->defaultArgs( blogId() ) ); args << QVariant( number ); d->mXmlRpcClient->call( d->getCallFromFunction( Blogger1Private::GetRecentPosts ), args, this, SLOT(slotListRecentPosts(const QList&,const QVariant&)), this, SLOT(slotError(int,const QString&,const QVariant&)), QVariant( number ) ); } void Blogger1::fetchPost( KBlog::BlogPost *post ) { if ( !post ) { kError() << "Blogger1::modifyPost: post is null pointer"; return; } Q_D( Blogger1 ); kDebug() << "Fetching Post with url" << post->postId(); QList args( d->defaultArgs( post->postId() ) ); unsigned int i= d->mCallCounter++; d->mCallMap[ i ] = post; d->mXmlRpcClient->call( d->getCallFromFunction( Blogger1Private::FetchPost ), args, this, SLOT(slotFetchPost(const QList&,const QVariant&)), this, SLOT(slotError(int, const QString&,const QVariant&)), QVariant( i ) ); } void Blogger1::modifyPost( KBlog::BlogPost *post ) { Q_D( Blogger1 ); if ( !post ) { kError() << "Blogger1::modifyPost: post is null pointer"; return; } kDebug() << "Uploading Post with postId" << post->postId(); unsigned int i= d->mCallCounter++; d->mCallMap[ i ] = post; QList args( d->defaultArgs( post->postId() ) ); d->readArgsFromPost( &args, *post ); d->mXmlRpcClient->call( d->getCallFromFunction( Blogger1Private::ModifyPost ), args, this, SLOT(slotModifyPost(const QList&,const QVariant&)), this, SLOT(slotError(int,const QString&,const QVariant&)), QVariant( i ) ); } void Blogger1::createPost( KBlog::BlogPost *post ) { Q_D( Blogger1 ); if ( !post ) { kError() << "Blogger1::createPost: post is null pointer"; return; } unsigned int i= d->mCallCounter++; d->mCallMap[ i ] = post; kDebug() << "Creating new Post with blogid" << blogId(); QList args( d->defaultArgs( blogId() ) ); d->readArgsFromPost( &args, *post ); d->mXmlRpcClient->call( d->getCallFromFunction( Blogger1Private::CreatePost ), args, this, SLOT(slotCreatePost(const QList&,const QVariant&)), this, SLOT(slotError(int, const QString&,const QVariant&)), QVariant( i ) ); } void Blogger1::removePost( KBlog::BlogPost *post ) { Q_D( Blogger1 ); if ( !post ) { kError() << "Blogger1::removePost: post is null pointer"; return; } unsigned int i = d->mCallCounter++; d->mCallMap[ i ] = post; kDebug() << "Blogger1::removePost: postId=" << post->postId(); QList args( d->blogger1Args( post->postId() ) ); args << QVariant( true ); // Publish must be set to remove post. d->mXmlRpcClient->call( "blogger.deletePost", args, this, SLOT(slotRemovePost(const QList&,const QVariant&)), this, SLOT(slotError(int,const QString&,const QVariant&)), QVariant( i ) ); } Blogger1Private::Blogger1Private() : mXmlRpcClient(0) { mCallCounter = 1; } Blogger1Private::~Blogger1Private() { kDebug() << "~Blogger1Private()"; delete mXmlRpcClient; } QList Blogger1Private::defaultArgs( const QString &id ) { kDebug(); Q_Q ( Blogger1 ); QList args; args << QVariant( QString( "0123456789ABCDEF" ) ); if( !id.isEmpty() ) { args << QVariant( id ); } args << QVariant( q->username() ) << QVariant( q->password() ); return args; } // reimplemenet defaultArgs, since we may not use it virtually everywhere QList Blogger1Private::blogger1Args( const QString &id ) { kDebug(); Q_Q ( Blogger1 ); QList args; args << QVariant( QString( "0123456789ABCDEF" ) ); if( !id.isEmpty() ) { args << QVariant( id ); } args << QVariant( q->username() ) << QVariant( q->password() ); return args; } void Blogger1Private::slotFetchUserInfo( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); Q_UNUSED( id ); kDebug() << "Blog::slotFetchUserInfo"; kDebug() << "TOP:" << result[0].typeName(); QMap userInfo; if ( result[0].type() != QVariant::Map ) { kError() << "Could not fetch user's info out of the result from the server," << "not a map."; emit q->error( Blogger1::ParsingError, i18n( "Could not fetch user's info out of the result " "from the server, not a map." ) ); return; } const QMap resultMap = result[0].toMap(); userInfo["nickname"]=resultMap["nickname"].toString(); userInfo["userid"]=resultMap["userid"].toString(); userInfo["url"]=resultMap["url"].toString(); userInfo["email"]=resultMap["email"].toString(); userInfo["lastname"]=resultMap["lastname"].toString(); userInfo["firstname"]=resultMap["firstname"].toString(); emit q->fetchedUserInfo( userInfo ); } void Blogger1Private::slotListBlogs( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); Q_UNUSED( id ); kDebug() << "Blog::slotListBlogs"; kDebug() << "TOP:" << result[0].typeName(); QList > blogsList; if ( result[0].type() != QVariant::List ) { kError() << "Could not fetch blogs out of the result from the server," << "not a list."; emit q->error( Blogger1::ParsingError, i18n( "Could not fetch blogs out of the result " "from the server, not a list." ) ); return; } const QList posts = result[0].toList(); QList::ConstIterator it = posts.begin(); QList::ConstIterator end = posts.end(); for ( ; it != end; ++it ) { kDebug() << "MIDDLE:" << ( *it ).typeName(); const QMap postInfo = ( *it ).toMap(); QMap blogInfo; blogInfo[ "id" ] = postInfo["blogid"].toString(); blogInfo[ "name" ] = postInfo["blogName"].toString(); kDebug() << "Blog information retrieved: ID =" << blogInfo["id"] << ", Name =" << blogInfo["name"]; blogsList << blogInfo; } emit q->listedBlogs( blogsList ); } void Blogger1Private::slotListRecentPosts( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); int count = id.toInt(); // not sure if needed, actually the API should // not give more posts kDebug() << "Blog::slotListRecentPosts"; kDebug() << "TOP:" << result[0].typeName(); QList fetchedPostList; if ( result[0].type() != QVariant::List ) { kError() << "Could not fetch list of posts out of the" << "result from the server, not a list."; emit q->error( Blogger1::ParsingError, i18n( "Could not fetch list of posts out of the result " "from the server, not a list." ) ); return; } const QList postReceived = result[0].toList(); QList::ConstIterator it = postReceived.begin(); QList::ConstIterator end = postReceived.end(); for ( ; it != end; ++it ) { BlogPost post; kDebug() << "MIDDLE:" << ( *it ).typeName(); const QMap postInfo = ( *it ).toMap(); if ( readPostFromMap( &post, postInfo ) ) { kDebug() << "Post with ID:" << post.postId() << "appended in fetchedPostList"; post.setStatus( BlogPost::Fetched ); fetchedPostList.append( post ); } else { kError() << "readPostFromMap failed!"; emit q->error( Blogger1::ParsingError, i18n( "Could not read post." ) ); } if ( --count == 0 ) { break; } } kDebug() << "Emitting listRecentPostsFinished()"; emit q->listedRecentPosts( fetchedPostList ); } void Blogger1Private::slotFetchPost( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); kDebug() << "Blog::slotFetchPost"; KBlog::BlogPost *post = mCallMap[ id.toInt() ]; mCallMap.remove( id.toInt() ); //array of structs containing ISO.8601 // dateCreated, String userid, String postid, String content; // TODO: Time zone for the dateCreated! kDebug () << "TOP:" << result[0].typeName(); if ( result[0].type() == QVariant::Map && readPostFromMap( post, result[0].toMap() ) ) { kDebug() << "Emitting fetchedPost()"; + post->setStatus( KBlog::BlogPost::Fetched ); emit q->fetchedPost( post ); } else { kError() << "Could not fetch post out of the result from the server."; post->setError( i18n( "Could not fetch post out of the result from the server." ) ); post->setStatus( BlogPost::Error ); emit q->errorPost( Blogger1::ParsingError, i18n( "Could not fetch post out of the result from the server." ), post ); } } void Blogger1Private::slotCreatePost( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); KBlog::BlogPost *post = mCallMap[ id.toInt() ]; mCallMap.remove( id.toInt() ); kDebug() << "Blog::slotCreatePost"; //array of structs containing ISO.8601 // dateCreated, String userid, String postid, String content; // TODO: Time zone for the dateCreated! kDebug () << "TOP:" << result[0].typeName(); if ( result[0].type() != QVariant::String && result[0].type() != QVariant::Int ) { kError() << "Could not read the postId, not a string or an integer."; emit q->errorPost( Blogger1::ParsingError, i18n( "Could not read the postId, not a string or an integer." ), post ); return; } QString serverID; if ( result[0].type() == QVariant::String ) { serverID = result[0].toString(); } if ( result[0].type() == QVariant::Int ) { serverID = QString( "%1" ).arg( result[0].toInt() ); } post->setPostId( serverID ); post->setStatus( KBlog::BlogPost::Created ); kDebug() << "emitting createdPost()" << "for title: \"" << post->title() << "\" server id: " << serverID; emit q->createdPost( post ); } void Blogger1Private::slotModifyPost( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); KBlog::BlogPost *post = mCallMap[ id.toInt() ]; mCallMap.remove( id.toInt() ); kDebug() << "Blog::slotModifyPost"; //array of structs containing ISO.8601 // dateCreated, String userid, String postid, String content; // TODO: Time zone for the dateCreated! kDebug() << "TOP:" << result[0].typeName(); if ( result[0].type() != QVariant::Bool ) { kError() << "Could not read the result, not a boolean."; emit q->errorPost( Blogger1::ParsingError, i18n( "Could not read the result, not a boolean." ), post ); return; } post->setStatus( KBlog::BlogPost::Modified ); kDebug() << "emitting modifiedPost() for title: \"" << post->title() << "\""; emit q->modifiedPost( post ); } void Blogger1Private::slotRemovePost( const QList &result, const QVariant &id ) { Q_Q( Blogger1 ); KBlog::BlogPost *post = mCallMap[ id.toInt() ]; mCallMap.remove( id.toInt() ); kDebug() << "Blog::slotRemovePost"; //array of structs containing ISO.8601 // dateCreated, String userid, String postid, String content; // TODO: Time zone for the dateCreated! kDebug() << "TOP:" << result[0].typeName(); if ( result[0].type() != QVariant::Bool ) { kError() << "Could not read the result, not a boolean."; emit q->errorPost( Blogger1::ParsingError, i18n( "Could not read the result, not a boolean." ), post ); return; } post->setStatus( KBlog::BlogPost::Removed ); kDebug() << "emitting removedPost()"; emit q->removedPost( post ); } void Blogger1Private::slotError( int number, const QString &errorString, const QVariant &id ) { Q_Q( Blogger1 ); Q_UNUSED( number ); BlogPost *post = mCallMap[ id.toInt() ]; emit q->errorPost( Blogger1::XmlRpc, errorString, post ); } bool Blogger1Private::readPostFromMap( BlogPost *post, const QMap &postInfo ) { // FIXME: integrate error handling if ( !post ) { return false; } QStringList mapkeys = postInfo.keys(); kDebug() << endl << "Keys:" << mapkeys.join( ", " ); kDebug() << endl; KDateTime dt( postInfo["dateCreated"].toDateTime(), KDateTime::UTC ); if ( dt.isValid() && !dt.isNull() ) { post->setCreationDateTime( dt ); } dt = KDateTime ( postInfo["lastModified"].toDateTime(), KDateTime::UTC ); if ( dt.isValid() && !dt.isNull() ) { post->setModificationDateTime( dt ); } post->setPostId( postInfo["postid"].toString() ); QString title( postInfo["title"].toString() ); QString description( postInfo["description"].toString() ); QString contents( postInfo["content"].toString() ); QStringList category; // Check for hacked title/category support (e.g. in Wordpress) QRegExp titleMatch = QRegExp( "([^<]*)" ); QRegExp categoryMatch = QRegExp( "([^<]*)" ); contents.remove( titleMatch ); if ( titleMatch.numCaptures() > 0 ) { // Get the title value from the regular expression match title = titleMatch.cap( 1 ); } contents.remove( categoryMatch ); if ( categoryMatch.numCaptures() > 0 ) { // Get the category value from the regular expression match category = categoryMatch.capturedTexts(); } post->setTitle( title ); post->setContent( contents ); post->setCategories( category ); return true; } bool Blogger1Private::readArgsFromPost( QList *args, const BlogPost &post ) { if ( !args ) { return false; } QStringList categories = post.categories(); QString content = "" + post.title() + ""; QStringList::const_iterator it; for ( it = categories.constBegin(); it != categories.constEnd(); ++it ) { content += "" + *it + ""; } content += post.content(); *args << QVariant( content ); *args << QVariant( !post.isPrivate() ); return true; } QString Blogger1Private::getCallFromFunction( FunctionToCall type ) { switch ( type ) { case GetRecentPosts: return "blogger.getRecentPosts"; case CreatePost: return "blogger.newPost"; case ModifyPost: return "blogger.editPost"; case FetchPost: return "blogger.getPost"; default: return QString(); } } #include "blogger1.moc" diff --git a/kblog/gdata.cpp b/kblog/gdata.cpp index aa7adceba..31fb11582 100644 --- a/kblog/gdata.cpp +++ b/kblog/gdata.cpp @@ -1,1079 +1,989 @@ /* 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 #include #include #include #include #include #include #include #include #include #include #define TIMEOUT 600 using namespace KBlog; GData::GData( const KUrl &server, QObject *parent ) : Blog( server, *new GDataPrivate, parent ) { kDebug(); setUrl( server ); } GData::~GData() { kDebug(); } QString GData::interfaceName() const { kDebug(); return QLatin1String( "Google Blogger Data" ); } QString GData::fullName() const { kDebug(); return d_func()->mFullName; } void GData::setFullName( const QString &fullName ) { kDebug(); Q_D( GData ); d->mFullName = fullName; } QString GData::profileId() const { kDebug(); return d_func()->mProfileId; } void GData::setProfileId( const QString &pid ) { kDebug(); Q_D( GData ); d->mProfileId = pid; } void GData::fetchProfileId() { kDebug(); QByteArray data; - KIO::Job *job = KIO::get( url(), KIO::NoReload, KIO::HideProgressInfo ); + KIO::StoredTransferJob *job = KIO::storedGet( url(), KIO::NoReload, KIO::HideProgressInfo ); KUrl blogUrl = url(); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotFetchProfileIdData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFetchProfileId(KJob*)) ); } void GData::listBlogs() { kDebug(); 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( "http://www.blogger.com/feeds/" + profileId() + "/blogs" ); } void GData::listRecentPosts( const QStringList &labels, int number, const KDateTime &upMinTime, const KDateTime &upMaxTime, const KDateTime &pubMinTime, const KDateTime &pubMaxTime ) { kDebug(); Q_D( GData ); QString urlString( "http://www.blogger.com/feeds/" + blogId() + "/posts/default" ); if ( ! labels.empty() ) { urlString += "/-/" + labels.join( "/" ); } kDebug() << "listRecentPosts()"; KUrl url( urlString ); if ( !upMinTime.isNull() ) { url.addQueryItem( "updated-min", upMinTime.toString() ); } if( !upMaxTime.isNull() ) { url.addQueryItem( "updated-max", upMaxTime.toString() ); } if( !pubMinTime.isNull() ) { url.addQueryItem( "published-min", pubMinTime.toString() ); } if( !pubMaxTime.isNull() ) { url.addQueryItem( "published-max", pubMaxTime.toString() ); } 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.url() ); } void GData::listRecentPosts( int number ) { kDebug(); listRecentPosts( QStringList(), number ); } void GData::listComments( KBlog::BlogPost *post ) { kDebug(); 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( "http://www.blogger.com/feeds/" + blogId() + '/' + post->postId() + "/comments/default" ); } void GData::listAllComments() { kDebug(); 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( "http://www.blogger.com/feeds/" + blogId() + "/comments/default" ); } void GData::fetchPost( KBlog::BlogPost *post ) { kDebug(); Q_D( GData ); if ( !post ) { kError() << "post is null pointer"; return; } kDebug(); 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( "http://www.blogger.com/feeds/" + blogId() + "/posts/default" ); } void GData::modifyPost( KBlog::BlogPost *post ) { kDebug(); Q_D( GData ); if ( !post ) { kError() << "post is null pointer"; return; } if ( !d->authenticate() ){ kError() << "Authentication failed."; emit errorPost( Atom, i18n( "Authentication failed." ), post ); return; } QString atomMarkup = ""; atomMarkup += "tag:blogger.com,1999:blog-" + blogId(); atomMarkup += ".post-" + post->postId() + ""; atomMarkup += "" + post->creationDateTime().toString() + ""; atomMarkup += "" + post->modificationDateTime().toString() + ""; atomMarkup += "" + post->title() + ""; if( post->isPrivate() ) { atomMarkup += ""; atomMarkup += "yes"; } atomMarkup += ""; atomMarkup += "
"; atomMarkup += post->content(); atomMarkup += "
"; QList::ConstIterator it = post->tags().constBegin(); QList::ConstIterator end = post->tags().constEnd(); for( ; it != end; ++it ){ atomMarkup += ""; } atomMarkup += ""; if ( !fullName().isEmpty() ) { atomMarkup += "" + fullName() + ""; } atomMarkup += "" + username() + ""; atomMarkup += ""; atomMarkup += "
"; QByteArray postData; QDataStream stream( &postData, QIODevice::WriteOnly ); stream.writeRawData( atomMarkup.toUtf8(), atomMarkup.toUtf8().length() ); - KIO::TransferJob *job = KIO::http_post( + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, KUrl( "http://www.blogger.com/feeds/" + blogId() + "/posts/default/" + post->postId() ), - postData, KIO::HideProgressInfo ); + KIO::HideProgressInfo ); Q_ASSERT( job ); d->mModifyPostMap[ job ] = post; job->addMetaData( "content-type", "Content-Type: application/atom+xml; charset=utf-8" ); job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); job->addMetaData( "customHTTPHeader", "Authorization: GoogleLogin auth=" + d->mAuthenticationString + "\r\nX-HTTP-Method-Override: PUT" ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotModifyPostData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotModifyPost(KJob*)) ); } void GData::createPost( KBlog::BlogPost *post ) { kDebug(); Q_D( GData ); if ( !post ) { kError() << "post is null pointer"; return; } if ( !d->authenticate() ){ kError() << "Authentication failed."; emit errorPost( Atom, i18n( "Authentication failed." ), post ); return; } QString atomMarkup = ""; atomMarkup += "" + post->title() + ""; if ( post->isPrivate() ) { atomMarkup += ""; atomMarkup += "yes"; } atomMarkup += ""; atomMarkup += "
"; atomMarkup += post->content(); // FIXME check for Utf atomMarkup += "
"; QList::ConstIterator it = post->tags().constBegin(); QList::ConstIterator end = post->tags().constEnd(); for( ; it != end; ++it ){ atomMarkup += ""; } atomMarkup += ""; if ( !fullName().isEmpty() ) { atomMarkup += "" + fullName() + ""; } atomMarkup += "" + username() + ""; atomMarkup += ""; atomMarkup += "
"; QByteArray postData; QDataStream stream( &postData, QIODevice::WriteOnly ); stream.writeRawData( atomMarkup.toUtf8(), atomMarkup.toUtf8().length() ); - KIO::TransferJob *job = KIO::http_post( + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, KUrl( "http://www.blogger.com/feeds/" + blogId() + "/posts/default" ), - postData, KIO::HideProgressInfo ); + KIO::HideProgressInfo ); Q_ASSERT ( job ); d->mCreatePostMap[ job ] = post; job->addMetaData( "content-type", "Content-Type: application/atom+xml; charset=utf-8" ); job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); job->addMetaData( "customHTTPHeader", "Authorization: GoogleLogin auth=" + d->mAuthenticationString ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotCreatePostData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotCreatePost(KJob*)) ); } void GData::removePost( KBlog::BlogPost *post ) { kDebug(); Q_D( GData ); if ( !post ) { kError() << "post is null pointer"; return; } if ( !d->authenticate() ){ kError() << "Authentication failed."; emit errorPost( Atom, i18n( "Authentication failed." ), post ); return; } QByteArray postData; - KIO::TransferJob *job = KIO::http_post( + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, KUrl( "http://www.blogger.com/feeds/" + blogId() + "/posts/default/" + post->postId() ), - postData, KIO::HideProgressInfo ); + KIO::HideProgressInfo ); d->mRemovePostMap[ job ] = post; if ( !job ) { kWarning() << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << "/posts/default/" + post->postId(); } job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); job->addMetaData( "customHTTPHeader", "Authorization: GoogleLogin auth=" + d->mAuthenticationString + "\r\nX-HTTP-Method-Override: DELETE" ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotRemovePostData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotRemovePost(KJob*)) ); } void GData::createComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ) { kDebug(); if ( !comment ) { kError() << "comment is null pointer"; return; } if ( !post ) { kError() << "post is null pointer"; return; } Q_D( GData ); if ( !d->authenticate() ){ kError() << "Authentication failed."; emit errorComment( Atom, i18n( "Authentication failed." ), post, comment ); return; } QString atomMarkup = ""; atomMarkup += "" + comment->title() + ""; atomMarkup += "" + comment->content() + ""; atomMarkup += ""; atomMarkup += "" + comment->name() + ""; atomMarkup += "" + comment->email() + ""; atomMarkup += ""; QByteArray postData; kDebug() << postData; QDataStream stream( &postData, QIODevice::WriteOnly ); stream.writeRawData( atomMarkup.toUtf8(), atomMarkup.toUtf8().length() ); - KIO::TransferJob *job = KIO::http_post( + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, KUrl( "http://www.blogger.com/feeds/" + blogId() + "/" + post->postId() + "/comments/default" ), - postData, KIO::HideProgressInfo ); + KIO::HideProgressInfo ); d->mCreateCommentMap[ job ][post] = comment; if ( !job ) { kWarning() << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << "/" << post->postId() << "/comments/default"; } job->addMetaData( "content-type", "Content-Type: application/atom+xml; charset=utf-8" ); job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "customHTTPHeader", "Authorization: GoogleLogin auth=" + d->mAuthenticationString ); job->addMetaData( "UserAgent", userAgent() ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotCreateCommentData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotCreateComment(KJob*)) ); } void GData::removeComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ) { kDebug(); Q_D( GData ); kDebug(); if ( !comment ) { kError() << "comment is null pointer"; return; } if ( !post ) { kError() << "post is null pointer"; return; } if ( !d->authenticate() ){ kError() << "Authentication failed."; emit errorComment( Atom, i18n( "Authentication failed." ), post, comment ); return; } QByteArray postData; - KIO::TransferJob *job = KIO::http_post( + KIO::StoredTransferJob *job = KIO::storedHttpPost(postData, KUrl( "http://www.blogger.com/feeds/" + blogId() + "/" + post->postId() + - "/comments/default/" + comment->commentId() ), - postData, KIO::HideProgressInfo ); + "/comments/default/" + comment->commentId() ), KIO::HideProgressInfo ); d->mRemoveCommentMap[ job ][ post ] = comment; if ( !job ) { kWarning() << "Unable to create KIO job for http://www.blogger.com/feeds/" << blogId() << post->postId() << "/comments/default/" << comment->commentId(); } job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); job->addMetaData( "customHTTPHeader", "Authorization: GoogleLogin auth=" + d->mAuthenticationString + "\r\nX-HTTP-Method-Override: DELETE" ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotRemoveCommentData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotRemoveComment(KJob*)) ); } GDataPrivate::GDataPrivate():mAuthenticationString(), mAuthenticationTime() { kDebug(); } GDataPrivate::~GDataPrivate() { kDebug(); } bool GDataPrivate::authenticate() { kDebug(); Q_Q( GData ); QByteArray data; KUrl authGateway( "https://www.google.com/accounts/ClientLogin" ); authGateway.addQueryItem( "Email", q->username() ); authGateway.addQueryItem( "Passwd", q->password() ); authGateway.addQueryItem( "source", q->userAgent() ); authGateway.addQueryItem( "service", "blogger" ); if ( !mAuthenticationTime.isValid() || QDateTime::currentDateTime().toTime_t() - mAuthenticationTime.toTime_t() > TIMEOUT || mAuthenticationString.isEmpty() ) { KIO::Job *job = KIO::http_post( authGateway, QByteArray(), KIO::HideProgressInfo ); if ( KIO::NetAccess::synchronousRun( job, (QWidget*)0, &data, &authGateway ) ) { QRegExp rx( "Auth=(.+)" ); if ( rx.indexIn( data ) != -1 ) { kDebug() << "RegExp got authentication string:" << rx.cap(1); mAuthenticationString = rx.cap(1); mAuthenticationTime = QDateTime::currentDateTime(); return true; } } return false; } return true; } -void GDataPrivate::slotFetchProfileIdData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ){ - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mFetchProfileIdBuffer[ job ].size(); - mFetchProfileIdBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mFetchProfileIdBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotFetchProfileId( KJob *job ) { kDebug(); if( !job ){ kError() << "job is a null pointer."; return; } Q_Q( GData ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); if ( !job->error() ) { QRegExp pid( "http://www.blogger.com/profile/(\\d+)" ); - if ( pid.indexIn( mFetchProfileIdBuffer[ job ] ) != -1 ) { + if ( pid.indexIn( data ) != -1 ) { q->setProfileId( pid.cap(1) ); kDebug() << "QRegExp bid( 'http://www.blogger.com/profile/(\\d+)' matches" << pid.cap(1); emit q->fetchedProfileId( pid.cap(1) ); } else { kError() << "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 { kError() << "Could not fetch the homepage data."; emit q->error( GData::Other, i18n( "Could not fetch the homepage data." ) ); emit q->fetchedProfileId( QString() ); } - mFetchProfileIdBuffer[ job ].resize( 0 ); - mFetchProfileIdBuffer.remove( job ); } void GDataPrivate::slotListBlogs( Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode status ) { kDebug(); Q_Q( GData ); if( !loader ) { kError() << "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( "blog-(\\d+)" ); QMap blogInfo; if ( rx.indexIn( ( *it )->id() ) != -1 ) { kDebug() << "QRegExp rx( 'blog-(\\d+)' matches" << rx.cap(1); blogInfo["id"] = rx.cap(1); blogInfo["title"] = ( *it )->title(); blogInfo["summary"] = ( *it )->description(); //TODO fix/add more blogsList << blogInfo; } else { kError() << "QRegExp rx( 'blog-(\\d+)' does not match anything in:" << ( *it )->id(); emit q->error( GData::Other, i18n( "Could not regexp the blog id path." ) ); } } kDebug() << "Emitting listedBlogs(); "; emit q->listedBlogs( blogsList ); } void GDataPrivate::slotListComments( Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode status ) { kDebug(); Q_Q( GData ); if( !loader ) { kError() << "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( "post-(\\d+)" ); if ( rx.indexIn( ( *it )->id() ) == -1 ) { kError() << "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) ); } kDebug() << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); comment.setTitle( ( *it )->title() ); comment.setContent( ( *it )->content() ); // FIXME: assuming UTC for now comment.setCreationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->datePublished() ), KDateTime::Spec::UTC() ) ); comment.setModificationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->dateUpdated() ), KDateTime::Spec::UTC() ) ); commentList.append( comment ); } kDebug() << "Emitting listedComments()"; emit q->listedComments( post, commentList ); } void GDataPrivate::slotListAllComments( Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode status ) { kDebug(); Q_Q( GData ); if( !loader ) { kError() << "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( "post-(\\d+)" ); if ( rx.indexIn( ( *it )->id() ) == -1 ) { kError() << "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) ); } kDebug() << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); comment.setTitle( ( *it )->title() ); comment.setContent( ( *it )->content() ); // FIXME: assuming UTC for now comment.setCreationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->datePublished() ), KDateTime::Spec::UTC() ) ); comment.setModificationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->dateUpdated() ), KDateTime::Spec::UTC() ) ); commentList.append( comment ); } kDebug() << "Emitting listedAllComments()"; emit q->listedAllComments( commentList ); } void GDataPrivate::slotListRecentPosts( Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode status ) { kDebug(); Q_Q( GData ); if( !loader ) { kError() << "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( "post-(\\d+)" ); if ( rx.indexIn( ( *it )->id() ) == -1 ) { kError() << "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) ); } kDebug() << "QRegExp rx( 'post-(\\d+)' matches" << rx.cap(1); post.setTitle( ( *it )->title() ); post.setContent( ( *it )->content() ); post.setLink( ( *it )->link() ); // FIXME: assuming UTC for now post.setCreationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->datePublished() ), KDateTime::Spec::UTC() ) ); post.setModificationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->dateUpdated() ), KDateTime::Spec::UTC() ) ); post.setStatus( BlogPost::Fetched ); postList.append( post ); if ( number-- == 0 ) { break; } } kDebug() << "Emitting listedRecentPosts()"; emit q->listedRecentPosts( postList ); } void GDataPrivate::slotFetchPost( Syndication::Loader *loader, Syndication::FeedPtr feed, Syndication::ErrorCode status ) { kDebug(); Q_Q( GData ); if( !loader ) { kError() << "loader is a null pointer."; return; } bool success = false; BlogPost *post = mFetchPostMap[ loader ]; if ( status != Syndication::Success ) { emit q->errorPost( GData::Atom, i18n( "Could not get posts." ), post ); return; } QList items = feed->items(); QList::ConstIterator it = items.constBegin(); QList::ConstIterator end = items.constEnd(); for ( ; it != end; ++it ) { QRegExp rx( "post-(\\d+)" ); if ( rx.indexIn( ( *it )->id() ) != -1 && rx.cap(1) == post->postId() ){ kDebug() << "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( ( *it )->link() ); // FIXME: assuming UTC for now post->setCreationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->datePublished() ), KDateTime::Spec::UTC() ) ); post->setModificationDateTime( KDateTime( QDateTime::fromTime_t( ( *it )->dateUpdated() ), KDateTime::Spec::UTC() ) ); kDebug() << "Emitting fetchedPost( postId=" << post->postId() << ");"; success = true; emit q->fetchedPost( post ); } } if ( !success ) { kError() << "QRegExp rx( 'post-(\\d+)' does not match" << mFetchPostMap[ loader ]->postId() << "."; emit q->errorPost( GData::Other, i18n( "Could not regexp the blog id path." ), post ); } mFetchPostMap.remove( loader ); } -void GDataPrivate::slotCreatePostData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ) { - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mCreatePostBuffer[ job ].size(); - mCreatePostBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mCreatePostBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotCreatePost( KJob *job ) { kDebug(); if( !job ) { kError() << "job is a null pointer."; return; } - const QString data = QString::fromUtf8( mCreatePostBuffer[ job ].data(), - mCreatePostBuffer[ job ].size() ); - mCreatePostBuffer[ job ].resize( 0 ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); Q_Q( GData ); KBlog::BlogPost *post = mCreatePostMap[ job ]; mCreatePostMap.remove( job ); if ( job->error() != 0 ) { kError() << "slotCreatePost error:" << job->errorString(); emit q->errorPost( GData::Atom, job->errorString(), post ); return; } QRegExp rxId( "post-(\\d+)" ); //FIXME check and do better handling, esp the creation date time if ( rxId.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub( "(.+)" ); if ( rxPub.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp( "(.+)" ); if ( rxUp.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); post->setPostId( rxId.cap(1) ); post->setCreationDateTime( KDateTime().fromString( rxPub.cap(1) ) ); post->setModificationDateTime( KDateTime().fromString( rxUp.cap(1) ) ); post->setStatus( BlogPost::Created ); kDebug() << "Emitting createdPost()"; emit q->createdPost( post ); } -void GDataPrivate::slotModifyPostData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ) { - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mModifyPostBuffer[ job ].size(); - mModifyPostBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mModifyPostBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotModifyPost( KJob *job ) { kDebug(); if( !job ) { kError() << "job is a null pointer."; return; } - const QString data = QString::fromUtf8( mModifyPostBuffer[ job ].data(), - mModifyPostBuffer[ job ].size() ); - mModifyPostBuffer[ job ].resize( 0 ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); KBlog::BlogPost *post = mModifyPostMap[ job ]; mModifyPostMap.remove( job ); Q_Q( GData ); if ( job->error() != 0 ) { kError() << "slotModifyPost error:" << job->errorString(); emit q->errorPost( GData::Atom, job->errorString(), post ); return; } QRegExp rxId( "post-(\\d+)" ); //FIXME check and do better handling, esp creation date time if ( rxId.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub( "(.+)" ); if ( rxPub.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp( "(.+)" ); if ( rxUp.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); post->setPostId( rxId.cap(1) ); post->setCreationDateTime( KDateTime().fromString( rxPub.cap(1) ) ); post->setModificationDateTime( KDateTime().fromString( rxUp.cap(1) ) ); post->setStatus( BlogPost::Modified ); emit q->modifiedPost( post ); } -void GDataPrivate::slotRemovePostData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ) { - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mRemovePostBuffer[ job ].size(); - mRemovePostBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mRemovePostBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotRemovePost( KJob *job ) { kDebug(); if( !job ) { kError() << "job is a null pointer."; return; } - const QString data = QString::fromUtf8( mRemovePostBuffer[ job ].data(), - mRemovePostBuffer[ job ].size() ); - mRemovePostBuffer[ job ].resize( 0 ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); KBlog::BlogPost *post = mRemovePostMap[ job ]; mRemovePostMap.remove( job ); Q_Q( GData ); if ( job->error() != 0 ) { kError() << "slotRemovePost error:" << job->errorString(); emit q->errorPost( GData::Atom, job->errorString(), post ); return; } post->setStatus( BlogPost::Removed ); kDebug() << "Emitting removedPost()"; emit q->removedPost( post ); } -void GDataPrivate::slotCreateCommentData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ) { - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mCreateCommentBuffer[ job ].size(); - mCreateCommentBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mCreateCommentBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotCreateComment( KJob *job ) { kDebug(); if( !job ) { kError() << "job is a null pointer."; return; } - const QString data = QString::fromUtf8( mCreateCommentBuffer[ job ].data(), - mCreateCommentBuffer[ job ].size() ); - mCreateCommentBuffer[ job ].resize( 0 ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); kDebug() << "Dump data: " << data; Q_Q( GData ); KBlog::BlogComment *comment = mCreateCommentMap[ job ].values().first(); KBlog::BlogPost *post = mCreateCommentMap[ job ].keys().first(); mCreateCommentMap.remove( job ); if ( job->error() != 0 ) { kError() << "slotCreateComment error:" << job->errorString(); emit q->errorComment( GData::Atom, job->errorString(), post, comment ); return; } // TODO check for result and fit appropriately QRegExp rxId( "post-(\\d+)" ); if ( rxId.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( 'post-(\\d+)' ) matches" << rxId.cap(1); QRegExp rxPub( "(.+)" ); if ( rxPub.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxPub.cap(1); QRegExp rxUp( "(.+)" ); if ( rxUp.indexIn( data ) == -1 ) { kError() << "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; } kDebug() << "QRegExp rx( '(.+)' ) matches" << rxUp.cap(1); comment->setCommentId( rxId.cap(1) ); comment->setCreationDateTime( KDateTime().fromString( rxPub.cap(1) ) ); comment->setModificationDateTime( KDateTime().fromString( rxUp.cap(1) ) ); comment->setStatus( BlogComment::Created ); kDebug() << "Emitting createdComment()"; emit q->createdComment( post, comment ); } -void GDataPrivate::slotRemoveCommentData( KIO::Job *job, const QByteArray &data ) -{ - kDebug(); - if( !job ) { - kError() << "job is a null pointer."; - return; - } - unsigned int oldSize = mRemoveCommentBuffer[ job ].size(); - mRemoveCommentBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mRemoveCommentBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void GDataPrivate::slotRemoveComment( KJob *job ) { kDebug(); if( !job ) { kError() << "job is a null pointer."; return; } - const QString data = QString::fromUtf8( mRemoveCommentBuffer[ job ].data(), - mRemoveCommentBuffer[ job ].size() ); - mRemoveCommentBuffer[ job ].resize( 0 ); + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); Q_Q( GData ); KBlog::BlogComment *comment = mRemoveCommentMap[ job ].values().first(); KBlog::BlogPost *post = mRemoveCommentMap[ job ].keys().first(); mRemoveCommentMap.remove( job ); if ( job->error() != 0 ) { kError() << "slotRemoveComment error:" << job->errorString(); emit q->errorComment( GData::Atom, job->errorString(), post, comment ); return; } comment->setStatus( BlogComment::Created ); kDebug() << "Emitting removedComment()"; emit q->removedComment( post, comment ); } #include "gdata.moc" diff --git a/kblog/gdata.h b/kblog/gdata.h index 2de10253e..c503d0b0e 100644 --- a/kblog/gdata.h +++ b/kblog/gdata.h @@ -1,344 +1,332 @@ /* 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. */ #ifndef KBLOG_GDATA_H #define KBLOG_GDATA_H #include #include #include class KUrl; /** @file This file is part of the for accessing Blog Servers and defines the GData class. @author Reinhold Kainhofer \ \par Maintainer: Christian Weilbach \ */ namespace KBlog { class GDataPrivate; class BlogComment; /** @brief A class that can be used for access to GData blogs. The new blogspot.com accounts ( August 2007 ) exclusively support GData API which is a standard based on Atom API. Compared to Blogger 1.0, which is based on Xml-Rpc and less secure, it adds new functionality like titles and comments. @code Blog* myblog = new GData("http://myblogspot.account.com"); myblog->setProfileId( "2039484587348593945823" ); // can be fetched via fetchProfileId() myblog->setBlogId( "1" ); // can be caught by listBlogs() myblog->setUsername( "your_email@address.com" ); myblog->setPassword( "yOuRFuNnYPasSword" ); KBlog::BlogPost *post = new BlogPost(); post->setTitle( "This is the title." ); post->setContent( "Here is some the content..." ); myblog->createPost( post ); @endcode @author Christian Weilbach \ @author Reinhold Kainhofer \ */ class KBLOG_EXPORT GData : public Blog { Q_OBJECT public: /** Create an object for GData @param server The server url for the xmlrpc gateway. @param parent The parent object, inherited from QObject. */ explicit GData( const KUrl &server, QObject *parent = 0 ); /** Destructor. */ ~GData(); /** Sets the user's name for the blog. Username is only the E-Mail address of the user. This is used in createPost and modifyPost. @param fullName is a QString containing the blog username. @see username() @see createPost( KBlog::BlogPost* ) @see modifiyPost( KBlog::BlogPost* ) */ virtual void setFullName( const QString &fullName ); /** Returns the full name of user of the blog. @see setFullName() */ QString fullName() const; /** Returns the profile id of the blog. This is used for rss paths internally. @return The profile id. @see setProfileId( const QString& ) */ QString profileId() const; /** Get the profile's id of the blog. @param pid This is nummeric id. @see profileId() */ virtual void setProfileId( const QString &pid ); /** Returns the of the inherited object. */ QString interfaceName() const; /** Get information about the profile from the blog. Sets the profileId automatically for the blog it is called from. @see setProfileId( const QString& ) @see void fetchedProfileId( const QString& ) */ void fetchProfileId(); /** List the blogs available for this authentication on the server. @see void listedBlogs( const QList\\>& ) */ virtual void listBlogs(); /** List the comments available for this post on the server. @param post The post, which posts should be listed. @see void listedComments( KBlog::BlogPost*, const QList\& ) */ virtual void listComments( KBlog::BlogPost *post ); /** List the all comments available for this authentication on the server. @see void listedAllComments( const QList\& ) */ virtual void listAllComments(); /** List recent posts on the server. The status of the posts will be Fetched. @param number The number of posts to fetch. The order is newest first. @see void listedPosts( const QList\& ) @see void fetchPost( KBlog::BlogPost* ) @see BlogPost::Status */ void listRecentPosts( int number ); /** List recent posts on the server depending on meta information about the post. @param label The lables of posts to fetch. @param number The number of posts to fetch. The order is newest first. @param upMinTime The oldest upload time of the posts to fetch. @param upMaxTime The newest upload time of the posts to fetch. @param pubMinTime The oldest publication time of the posts to fetch. @param pubMaxTime The newest publication time of the posts to fetch. @see void listedPosts( const QList\& ) @see void fetchPost( KBlog::BlogPost* ) */ virtual void listRecentPosts( const QStringList &label=QStringList(), int number=0, const KDateTime &upMinTime=KDateTime(), const KDateTime &upMaxTime=KDateTime(), const KDateTime &pubMinTime=KDateTime(), const KDateTime &pubMaxTime=KDateTime() ); /** Fetch the Post with a specific id. @param post This is the post with its id set correctly. @see BlogPost::setPostId( const QString& ) @see fetchedPost( KBlog::BlogPost *post ) */ void fetchPost( KBlog::BlogPost *post ); /** Modify a post on server. @param post This is used to send the modified post including the correct id. */ void modifyPost( KBlog::BlogPost *post ); /** Create a new post on server. @param post This is send to the server. @see createdPost( KBlog::BlogPost *post ) */ void createPost( KBlog::BlogPost *post ); /** Remove a post from the server. @param post This is the post with its id set correctly. @see BlogPost::setPostId( const QString& ) @see removedPost( KBlog::BlogPost* ) */ void removePost( KBlog::BlogPost *post ); /** Create a comment on the server. @param post This is the post with its id set correctly. @param comment This is the comment to create. @see BlogPost::setPostId( const QString& ) @see createdComment( KBlog::BlogPost*, KBlog::BlogComment* ) */ virtual void createComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ); /** Remove a comment from the server. @param post This is the post with its id set correctly. @param comment This is the comment to remove. @see BlogPost::setPostId( const QString& ) @see removedComment( KBlog::BlogPost*, KBlog::BlogComment* ) */ virtual void removeComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ); Q_SIGNALS: /** This signal is emitted when a list of blogs has been fetched from the blogging server. @param blogsList The list of blogs. @see listBlogs() */ void listedBlogs( const QList >& blogsList ); /** This signal is emitted when a list of all comments has been fetched from the blogging server. @param commentsList The list of comments. @see listAllComments() */ void listedAllComments( const QList &commentsList ); /** This signal is emitted when a list of comments has been fetched from the blogging server. @param post This is the corresponding post. @param comments The list of comments. @see listComments( KBlog::BlogPost* ) */ void listedComments( KBlog::BlogPost *post, const QList &comments ); /** This signal is emitted when a comment has been created on the blogging server. @param post This is the corresponding post. @param comment This is the created comment. @see createComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ) */ void createdComment( const KBlog::BlogPost *post, const KBlog::BlogComment *comment ); /** This signal is emitted when a comment has been removed from the blogging server. @param post This is the corresponding post. @param comment This is the removed comment. @see removeComment( KBlog::BlogPost *post, KBlog::BlogComment *comment ) */ void removedComment( const KBlog::BlogPost *post, const KBlog::BlogComment *comment ); /** This signal is emitted when the profile id has been fetched. @param profileId This is the fetched id. On error it is QString() @see fetchProfileId() */ void fetchedProfileId( const QString &profileId ); protected: /** Overloaded for private inheritance handling. */ GData( const KUrl &server, GDataPrivate &dd, QObject *parent = 0 ); private: Q_DECLARE_PRIVATE( GData ) Q_PRIVATE_SLOT( d_func(), void slotFetchProfileId( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotFetchProfileIdData( KIO::Job *, const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotListBlogs( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ) ) Q_PRIVATE_SLOT( d_func(), void slotListComments( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ) ) Q_PRIVATE_SLOT( d_func(), void slotListAllComments( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ) ) Q_PRIVATE_SLOT( d_func(), void slotListRecentPosts( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ) ) Q_PRIVATE_SLOT( d_func(), void slotFetchPost( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ) ) Q_PRIVATE_SLOT( d_func(), void slotCreatePost( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotCreatePostData( KIO::Job *, const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotModifyPost( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotModifyPostData( KIO::Job *, const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotRemovePost( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotRemovePostData( KIO::Job *, const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotCreateComment( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotCreateCommentData( KIO::Job *, const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotRemoveComment( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), - void slotRemoveCommentData( KIO::Job *, const QByteArray & ) ) }; } //namespace KBlog #endif diff --git a/kblog/gdata_p.h b/kblog/gdata_p.h index 88fadab5b..4aa465a25 100644 --- a/kblog/gdata_p.h +++ b/kblog/gdata_p.h @@ -1,92 +1,80 @@ /* 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. */ #ifndef KBLOG_GDATA_P_H #define KBLOG_GDATA_P_H #include "gdata.h" #include "blog_p.h" #include class KJob; class QDateTime; class QByteArray; template class QMap; namespace KIO { class Job; } namespace KBlog { class GDataPrivate : public BlogPrivate { public: QString mAuthenticationString; QDateTime mAuthenticationTime; - QMap mCreatePostBuffer; QMap mCreatePostMap; - QMap mCreateCommentBuffer; QMap > mCreateCommentMap; - QMap mRemoveCommentBuffer; QMap > mRemoveCommentMap; - QMap mModifyPostBuffer; QMap mModifyPostMap; - QMap mRemovePostBuffer; QMap mRemovePostMap; - QMap mFetchProfileIdBuffer; QMap mFetchPostMap; QMap mListCommentsMap; QMap mListRecentPostsMap; QString mFullName; QString mProfileId; GDataPrivate(); ~GDataPrivate(); bool authenticate(); - virtual void slotFetchProfileIdData( KIO::Job *, const QByteArray & ); virtual void slotFetchProfileId( KJob * ); virtual void slotListBlogs( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ); virtual void slotListComments( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ); virtual void slotListAllComments( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ); virtual void slotListRecentPosts( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ); virtual void slotFetchPost( Syndication::Loader *, Syndication::FeedPtr, Syndication::ErrorCode ); virtual void slotCreatePost( KJob * ); - virtual void slotCreatePostData( KIO::Job *, const QByteArray & ); virtual void slotModifyPost( KJob * ); - virtual void slotModifyPostData( KIO::Job *, const QByteArray & ); virtual void slotRemovePost( KJob * ); - virtual void slotRemovePostData( KIO::Job *, const QByteArray & ); virtual void slotCreateComment( KJob * ); - virtual void slotCreateCommentData( KIO::Job *, const QByteArray & ); virtual void slotRemoveComment( KJob * ); - virtual void slotRemoveCommentData( KIO::Job *, const QByteArray & ); Q_DECLARE_PUBLIC( GData ) }; } #endif diff --git a/kblog/tests/data.h b/kblog/tests/data.h index 1b47a1824..eacdfd193 100644 --- a/kblog/tests/data.h +++ b/kblog/tests/data.h @@ -1,58 +1,53 @@ /* This file is part of the kblog library. Copyright (c) 2006-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. */ #ifndef KBLOG_TEST_DATA_H_ #define KBLOG_TEST_DATA_H_ #include #include #include #include #include -// KUrl mUrl( "http://soctest.wordpress.com/xmlrpc.php" ); -// QString mUsername( "socapitest" ); -// QString mPassword( "k0nt4ctbl0g" ); -// QString mBlogId( "1" ); - -KUrl mUrl( "http://sandbox2.monkey-corp.com/xmlrpc.php" ); +KUrl mUrl( "http://soctest.wordpress.com/xmlrpc.php" ); QString mUsername( "socapitest" ); QString mPassword( "k0nt4ctbl0g" ); -QString mBlogId( "blog" ); +QString mBlogId( "1" ); QDateTime mCreationDateTime( QDateTime::currentDateTime() ); QDateTime mModificationDateTime( QDateTime::currentDateTime() ); QString mTitle( "TestBlog" ); QString mContent( "TestBlog: posted content." ); QString mModifiedContent( "TestBlog: modifiedcontent." ); bool mPrivate = false; QString mPostId( QString( "113" ) ); QString mCommentTitle( "TestBlog Comment" ); QString mCommentContent( "TestBlog: posted comment." ); QString mCommentEmail( QString( "fancy_mail@not.valid" ) ); bool mCommentAllowed = true; bool mTrackBackAllowed = true; QStringList mTags( "funny" ); QString mSummary = "A simple summary."; #endif diff --git a/kblog/wordpressbuggy.cpp b/kblog/wordpressbuggy.cpp index a7a749415..27c80732b 100644 --- a/kblog/wordpressbuggy.cpp +++ b/kblog/wordpressbuggy.cpp @@ -1,371 +1,351 @@ /* This file is part of the kblog library. Copyright (c) 2006-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 "wordpressbuggy.h" #include "wordpressbuggy_p.h" #include "blogpost.h" #include #include #include #include #include #include using namespace KBlog; WordpressBuggy::WordpressBuggy( const KUrl &server, QObject *parent ) : MovableType( server, *new WordpressBuggyPrivate, parent ) { kDebug() << "WordpressBuggy()"; } WordpressBuggy::WordpressBuggy( const KUrl &server, WordpressBuggyPrivate &dd, QObject *parent ) : MovableType( server, dd, parent ) { kDebug() << "WordpressBuggy()"; } WordpressBuggy::~WordpressBuggy() { kDebug() << "~WordpressBuggy()"; } void WordpressBuggy::createPost( KBlog::BlogPost *post ) { kDebug() << "createPost()"; Q_D( WordpressBuggy ); if ( !post ) { kError() << "WordpressBuggy::createPost: post is a null pointer"; emit error ( Other, i18n( "Post is a null pointer." ) ); return; } kDebug() << "Creating new Post with blogId" << blogId(); QString xmlMarkup = ""; xmlMarkup += ""; xmlMarkup += "metaWeblog.newPost"; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += "description"; xmlMarkup += "content()+"]]>"; xmlMarkup += ""; xmlMarkup += "title"; xmlMarkup += "title()+"]]>"; xmlMarkup += ""; QList catList = post->categories(); if ( !catList.empty() ){ xmlMarkup += "categories"; xmlMarkup += ""; QList::ConstIterator it = catList.constBegin(); QList::ConstIterator end = catList.constEnd(); for ( ; it != end; ++it ){ xmlMarkup += ""; } xmlMarkup += ""; xmlMarkup += ""; } xmlMarkup += "dateCreated"; xmlMarkup += "" + post->creationDateTime().toUtc().dateTime().toString( "yyyyMMddThh:mm:ss" ) + ""; xmlMarkup += ""; xmlMarkup += "mt_allow_comments"; xmlMarkup += QString( "%1" ).arg( (int)post->isCommentAllowed() ); xmlMarkup += ""; xmlMarkup += "mt_allow_pings"; xmlMarkup += QString( "%1" ).arg( (int)post->isTrackBackAllowed() ); xmlMarkup += ""; xmlMarkup += "mt_excerpt"; xmlMarkup += "summary() + "]]>"; xmlMarkup += ""; xmlMarkup += "mt_keywords"; xmlMarkup += "tags().join(",") + "]]>"; xmlMarkup += ""; xmlMarkup += "" + QString( "%1" ).arg( (int)(!post->isPrivate() ) ) + ""; xmlMarkup += ""; QByteArray postData; QDataStream stream( &postData, QIODevice::WriteOnly ); stream.writeRawData( xmlMarkup.toUtf8(), xmlMarkup.toUtf8().length() ); - KIO::TransferJob *job = KIO::http_post( url(), postData, KIO::HideProgressInfo ); + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, url(), KIO::HideProgressInfo ); d->mCreatePostMap[ job ] = post; if ( !job ) { kWarning() << "Failed to create job for: " << url().url(); } job->addMetaData( "customHTTPHeader", "X-hacker: Shame on you Wordpress, " + QString() + "you took another 4 hours of my life to work around the stupid dateTime bug." ); job->addMetaData( "content-type", "Content-Type: text/xml; charset=utf-8" ); job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); - connect( job, SIGNAL(data(KIO::Job *,const QByteArray &)), - this, SLOT(slotCreatePostData(KIO::Job *,const QByteArray &)) ); connect( job, SIGNAL(result(KJob *)), this, SLOT(slotCreatePost(KJob *)) ); } void WordpressBuggy::modifyPost( KBlog::BlogPost *post ) { kDebug() << "modifyPost()"; Q_D( WordpressBuggy ); if ( !post ) { kError() << "WordpressBuggy::modifyPost: post is a null pointer"; emit error ( Other, i18n( "Post is a null pointer." ) ); return; } kDebug() << "Uploading Post with postId" << post->postId(); QString xmlMarkup = ""; xmlMarkup += ""; xmlMarkup += "metaWeblog.editPost"; xmlMarkup += ""; xmlMarkup += "postId()+"]]>"; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += ""; xmlMarkup += "description"; xmlMarkup += "content()+"]]>"; xmlMarkup += ""; xmlMarkup += "title"; xmlMarkup += "title()+"]]>"; xmlMarkup += ""; QList catList = post->categories(); if ( !catList.empty() ){ xmlMarkup += "categories"; xmlMarkup += ""; QList::ConstIterator it = catList.constBegin(); QList::ConstIterator end = catList.constEnd(); for ( ; it != end; ++it ){ xmlMarkup += ""; } xmlMarkup += ""; xmlMarkup += ""; } xmlMarkup += "lastModified"; xmlMarkup += "" + post->modificationDateTime().toUtc().dateTime().toString( "yyyyMMddThh:mm:ss" ) + ""; xmlMarkup += ""; xmlMarkup += "dateCreated"; xmlMarkup += "" + post->creationDateTime().toUtc().dateTime().toString( "yyyyMMddThh:mm:ss" ) + ""; xmlMarkup += ""; xmlMarkup += "mt_allow_comments"; xmlMarkup += QString( "%1" ).arg( (int)post->isCommentAllowed() ); xmlMarkup += ""; xmlMarkup += "mt_allow_pings"; xmlMarkup += QString( "%1" ).arg( (int)post->isTrackBackAllowed() ); xmlMarkup += ""; xmlMarkup += "mt_excerpt"; xmlMarkup += "summary() + "]]>"; xmlMarkup += ""; xmlMarkup += "mt_keywords"; xmlMarkup += "tags().join( "," ) + "]]>"; xmlMarkup += ""; xmlMarkup += "" + QString( "%1" ).arg( (int)( !post->isPrivate() ) ) + ""; xmlMarkup += ""; QByteArray postData; QDataStream stream( &postData, QIODevice::WriteOnly ); stream.writeRawData( xmlMarkup.toUtf8(), xmlMarkup.toUtf8().length() ); - KIO::TransferJob *job = KIO::http_post( url(), postData, KIO::HideProgressInfo ); + KIO::StoredTransferJob *job = KIO::storedHttpPost( postData, url(), KIO::HideProgressInfo ); d->mModifyPostMap[ job ] = post; if ( !job ) { kWarning() << "Failed to create job for: " << url().url(); } job->addMetaData( "customHTTPHeader", "X-hacker: Shame on you Wordpress, " + QString() + "you took another 4 hours of my life to work around the stupid dateTime bug." ); job->addMetaData( "content-type", "Content-Type: text/xml; charset=utf-8" ); job->addMetaData( "ConnectTimeout", "50" ); job->addMetaData( "UserAgent", userAgent() ); - connect( job, SIGNAL(data(KIO::Job*,const QByteArray&)), - this, SLOT(slotModifyPostData(KIO::Job*,const QByteArray&)) ); connect( job, SIGNAL(result(KJob*)), this, SLOT(slotModifyPost(KJob*)) ); } QString WordpressBuggy::interfaceName() const { return QLatin1String( "Movable Type" ); } WordpressBuggyPrivate::WordpressBuggyPrivate() { } WordpressBuggyPrivate::~WordpressBuggyPrivate() { kDebug() << "~WordpressBuggyPrivate()"; } QList WordpressBuggyPrivate::defaultArgs( const QString &id ) { Q_Q( WordpressBuggy ); QList args; if ( !id.isEmpty() ) { args << QVariant( id ); } args << QVariant( q->username() ) << QVariant( q->password() ); return args; } -void WordpressBuggyPrivate::slotCreatePostData( KIO::Job *job, const QByteArray &data ) -{ - kDebug() << "slotCreatePostData()"; - unsigned int oldSize = mCreatePostBuffer[ job ].size(); - mCreatePostBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mCreatePostBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void WordpressBuggyPrivate::slotCreatePost( KJob *job ) { kDebug() << "slotCreatePost()"; - const QString data = QString::fromUtf8( mCreatePostBuffer[ job ].data(), - mCreatePostBuffer[ job ].size() ); - mCreatePostBuffer[ job ].resize( 0 ); + + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); Q_Q( WordpressBuggy ); KBlog::BlogPost *post = mCreatePostMap[ job ]; mCreatePostMap.remove( job ); if ( job->error() != 0 ) { kError() << "slotCreatePost error:" << job->errorString(); emit q->errorPost( WordpressBuggy::Atom, job->errorString(), post ); return; } QRegExp rxError( "faultString" ); if ( rxError.indexIn( data ) != -1 ){ rxError = QRegExp( "(.+)" ); if ( rxError.indexIn( data ) != -1 ) { kDebug() << "RegExp of faultString failed."; } kDebug() << rxError.cap(1); emit q->errorPost( WordpressBuggy::XmlRpc, rxError.cap(1), post ); return; } QRegExp rxId( "(.+)" ); if ( rxId.indexIn( data ) == -1 ){ kError() << "Could not regexp the id out of the result:" << data; emit q->errorPost( WordpressBuggy::XmlRpc, i18n( "Could not regexp the id out of the result." ), post ); return; } kDebug() << "QRegExp rx( \"(.+)\" ) matches" << rxId.cap( 1 ); post->setPostId( rxId.cap( 1 ) ); post->setStatus( BlogPost::Created ); kDebug() << "Emitting createdPost()"; emit q->createdPost( post ); } -void WordpressBuggyPrivate::slotModifyPostData( KIO::Job *job, const QByteArray &data ) -{ - kDebug() << "slotModifyPostData()"; - unsigned int oldSize = mModifyPostBuffer[ job ].size(); - mModifyPostBuffer[ job ].resize( oldSize + data.size() ); - memcpy( mModifyPostBuffer[ job ].data() + oldSize, data.data(), data.size() ); -} - void WordpressBuggyPrivate::slotModifyPost( KJob *job ) { kDebug() << "slotModifyPost()"; - const QString data = QString::fromUtf8( mModifyPostBuffer[ job ].data(), - mModifyPostBuffer[ job ].size() ); - mModifyPostBuffer[ job ].resize( 0 ); + + KIO::StoredTransferJob *stj = qobject_cast(job); + const QString data = QString::fromUtf8( stj->data(), stj->data().size() ); KBlog::BlogPost *post = mModifyPostMap[ job ]; mModifyPostMap.remove( job ); Q_Q( WordpressBuggy ); if ( job->error() != 0 ) { kError() << "slotModifyPost error:" << job->errorString(); emit q->errorPost( WordpressBuggy::Atom, job->errorString(), post ); return; } QRegExp rxError( "faultString" ); if ( rxError.indexIn( data ) != -1 ){ rxError = QRegExp( "(.+)" ); if ( rxError.indexIn( data ) != -1 ) { kDebug() << "RegExp of faultString failed."; } kDebug() << rxError.cap(1); emit q->errorPost( WordpressBuggy::XmlRpc, rxError.cap(1), post ); return; } QRegExp rxId( "(.+)" ); if ( rxId.indexIn( data ) == -1 ) { kError() << "Could not regexp the id out of the result:" << data; emit q->errorPost( WordpressBuggy::XmlRpc, i18n( "Could not regexp the id out of the result." ), post ); return; } kDebug() << "QRegExp rx( \"(.+)\" ) matches" << rxId.cap( 1 ); if ( rxId.cap( 1 ).toInt() == 1 ) { kDebug() << "Post successfully updated."; post->setStatus( BlogPost::Modified ); emit q->modifiedPost( post ); } } #include "wordpressbuggy.moc" diff --git a/kblog/wordpressbuggy.h b/kblog/wordpressbuggy.h index c08a3c9e7..0f9a039ab 100644 --- a/kblog/wordpressbuggy.h +++ b/kblog/wordpressbuggy.h @@ -1,120 +1,118 @@ /* 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. */ #ifndef KBLOG_WORDPRESSBUGGY_H #define KBLOG_WORDPRESSBUGGY_H #include class KUrl; /** @file This file is part of the for accessing Blog Servers and defines the WordpressBuggy class. @author Christian Weilbach \ */ namespace KBlog { class WordpressBuggyPrivate; /** @brief A class that can be used for access to blogs (Wordpress, Drupal <5.6 and most likely many more) which simply use the yyyyMMddThh:mm:ss dateTime.iso8601 format stated on http://www.xmlrpc.com. This is only an example for an ISO-8601 compatible format, but many blogs seem to assume exactly this format. This class is needed because KXmlRpc::Client only has support for the extended format yyyy-MM-ddThh:mm:ss which is also standard conform and makes more sense than the mixture above. This class reimplements createPost and modifyPost from scratch to send the dateTime in a compatible format (yyyyMMddThh:mm:ss). The rest of the code is inherited from MovableType, as it does not use the dateTime format. The name is because this problem was first discovered with Wordpress. @code Blog* myblog = new WordpressBuggy("http://example.com/xmlrpc/gateway.php"); myblog->setUsername( "some_user_id" ); myblog->setPassword( "YoURFunnyPAsSwoRD" ); myblog->setBlogId( "1" ); // can be caught by listBlogs() KBlog::BlogPost *post = new BlogPost(); post->setTitle( "This is the title." ); post->setContent( "Here is some the content..." ); myblog->createPost( post ); @endcode @author Christian Weilbach \ */ class KBLOG_EXPORT WordpressBuggy : public MovableType { Q_OBJECT public: /** Create an object for WordpressBuggy @param server is the url for the xmlrpc gateway. @param parent is the parent object. */ explicit WordpressBuggy( const KUrl &server, QObject *parent = 0 ); /** Destroy the object. */ virtual ~WordpressBuggy(); /** Create a new post on server. @param post is send to the server. */ void createPost( KBlog::BlogPost *post ); /** Modify a post on server. @param post The post to be modified on the server. You need to set its id correctly. @see BlogPost::setPostId( const QString& ) @see modifiedPost( KBlog::BlogPost* ) */ void modifyPost( KBlog::BlogPost *post ); /** Returns the of the inherited object. */ QString interfaceName() const; protected: /** Constructor needed for private inheritance. */ WordpressBuggy( const KUrl &server, WordpressBuggyPrivate &dd, QObject *parent = 0 ); private: Q_DECLARE_PRIVATE( WordpressBuggy ) Q_PRIVATE_SLOT( d_func(), void slotCreatePost( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), void slotCreatePostData( KIO::Job *,const QByteArray & ) ) Q_PRIVATE_SLOT( d_func(), void slotModifyPost( KJob * ) ) - Q_PRIVATE_SLOT( d_func(), void slotModifyPostData( KIO::Job *,const QByteArray & ) ) }; } //namespace KBlog #endif diff --git a/kblog/wordpressbuggy_p.h b/kblog/wordpressbuggy_p.h index af87a75aa..017d44bee 100644 --- a/kblog/wordpressbuggy_p.h +++ b/kblog/wordpressbuggy_p.h @@ -1,61 +1,57 @@ /* This file is part of the kblog library. Copyright (c) 2007 Mike Arthur 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. */ #ifndef WORDPRESSBUGGY_P_H #define WORDPRESSBUGGY_P_H #include "wordpressbuggy.h" #include "movabletype_p.h" #include class KJob; class QByteArray; template class QMap; namespace KIO { class Job; } namespace KBlog { class WordpressBuggyPrivate : public MovableTypePrivate { public: - QMap mCreatePostBuffer; QMap mCreatePostMap; - QMap mModifyPostBuffer; QMap mModifyPostMap; WordpressBuggyPrivate(); virtual ~WordpressBuggyPrivate(); virtual QList defaultArgs( const QString &id = QString() ); virtual void slotCreatePost( KJob * ); - virtual void slotCreatePostData( KIO::Job *, const QByteArray & ); virtual void slotModifyPost( KJob * ); - virtual void slotModifyPostData( KIO::Job *, const QByteArray & ); Q_DECLARE_PUBLIC( WordpressBuggy ) }; } #endif