• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

KBlog Client Library

blogger1.cpp

00001 /*
00002   This file is part of the kblog library.
00003 
00004   Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005   Copyright (c) 2006-2007 Christian Weilbach <christian_weilbach@web.de>
00006   Copyright (c) 2007-2008 Mike Arthur <mike@mikearthur.co.uk>
00007 
00008   This library is free software; you can redistribute it and/or
00009   modify it under the terms of the GNU Library General Public
00010   License as published by the Free Software Foundation; either
00011   version 2 of the License, or (at your option) any later version.
00012 
00013   This library is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016   Library General Public License for more details.
00017 
00018   You should have received a copy of the GNU Library General Public License
00019   along with this library; see the file COPYING.LIB.  If not, write to
00020   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021   Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "blogger1.h"
00025 #include "blogger1_p.h"
00026 #include "blogpost.h"
00027 
00028 #include <kxmlrpcclient/client.h>
00029 
00030 #include <KDebug>
00031 #include <KDateTime>
00032 #include <KLocale>
00033 
00034 #include <QList>
00035 
00036 #include <QStringList>
00037 
00038 using namespace KBlog;
00039 
00040 Blogger1::Blogger1( const KUrl &server, QObject *parent )
00041   : Blog( server, *new Blogger1Private, parent )
00042 {
00043   kDebug() << "Blogger1()";
00044   setUrl( server );
00045 }
00046 
00047 Blogger1::Blogger1( const KUrl &server, Blogger1Private &dd, QObject *parent )
00048   : Blog( server, dd, parent )
00049 {
00050   kDebug() << "Blogger1()";
00051   setUrl( server );
00052 }
00053 
00054 Blogger1::~Blogger1()
00055 {
00056   kDebug() << "~Blogger1()";
00057 }
00058 
00059 QString Blogger1::interfaceName() const
00060 {
00061   return QLatin1String( "Blogger 1.0" );
00062 }
00063 
00064 void Blogger1::setUrl( const KUrl &server )
00065 {
00066   Q_D( Blogger1 );
00067   Blog::setUrl( server );
00068   delete d->mXmlRpcClient;
00069   d->mXmlRpcClient = new KXmlRpc::Client( server );
00070   d->mXmlRpcClient->setUserAgent( userAgent() );
00071 }
00072 
00073 void Blogger1::fetchUserInfo()
00074 {
00075     Q_D( Blogger1 );
00076     kDebug() << "Fetch user's info...";
00077     QList<QVariant> args( d->blogger1Args() );
00078     d->mXmlRpcClient->call(
00079       "blogger.getUserInfo", args,
00080       this, SLOT(slotFetchUserInfo(const QList<QVariant>&,const QVariant&)),
00081       this, SLOT(slotError(int,const QString&,const QVariant&)) );
00082 }
00083 
00084 void Blogger1::listBlogs()
00085 {
00086     Q_D( Blogger1 );
00087     kDebug() << "Fetch List of Blogs...";
00088     QList<QVariant> args( d->blogger1Args() );
00089     d->mXmlRpcClient->call(
00090       "blogger.getUsersBlogs", args,
00091       this, SLOT(slotListBlogs(const QList<QVariant>&,const QVariant&)),
00092       this, SLOT(slotError(int,const QString&,const QVariant&)) );
00093 }
00094 
00095 void Blogger1::listRecentPosts( int number )
00096 {
00097     Q_D( Blogger1 );
00098     kDebug() << "Fetching List of Posts...";
00099     QList<QVariant> args( d->defaultArgs( blogId() ) );
00100     args << QVariant( number );
00101     d->mXmlRpcClient->call(
00102       d->getCallFromFunction( Blogger1Private::GetRecentPosts ), args,
00103       this, SLOT(slotListRecentPosts(const QList<QVariant>&,const QVariant&)),
00104       this, SLOT(slotError(int,const QString&,const QVariant&)),
00105       QVariant( number ) );
00106 }
00107 
00108 void Blogger1::fetchPost( KBlog::BlogPost *post )
00109 {
00110   if ( !post ) {
00111     kError() << "Blogger1::modifyPost: post is null pointer";
00112     return;
00113   }
00114 
00115   Q_D( Blogger1 );
00116   kDebug() << "Fetching Post with url" << post->postId();
00117   QList<QVariant> args( d->defaultArgs( post->postId() ) );
00118   unsigned int i= d->mCallCounter++;
00119   d->mCallMap[ i ] = post;
00120   d->mXmlRpcClient->call(
00121     d->getCallFromFunction( Blogger1Private::FetchPost ), args,
00122     this, SLOT(slotFetchPost(const QList<QVariant>&,const QVariant&)),
00123     this, SLOT(slotError(int, const QString&,const QVariant&)),
00124     QVariant( i ) );
00125 }
00126 
00127 void Blogger1::modifyPost( KBlog::BlogPost *post )
00128 {
00129   Q_D( Blogger1 );
00130 
00131   if ( !post ) {
00132     kError() << "Blogger1::modifyPost: post is null pointer";
00133     return;
00134   }
00135 
00136   kDebug() << "Uploading Post with postId" << post->postId();
00137   unsigned int i= d->mCallCounter++;
00138   d->mCallMap[ i ] = post;
00139   QList<QVariant> args( d->defaultArgs( post->postId() ) );
00140   d->readArgsFromPost( &args, *post );
00141   d->mXmlRpcClient->call(
00142     d->getCallFromFunction( Blogger1Private::ModifyPost ), args,
00143     this, SLOT(slotModifyPost(const QList<QVariant>&,const QVariant&)),
00144     this, SLOT(slotError(int,const QString&,const QVariant&)),
00145     QVariant( i ) );
00146 }
00147 
00148 void Blogger1::createPost( KBlog::BlogPost *post )
00149 {
00150   Q_D( Blogger1 );
00151 
00152   if ( !post ) {
00153     kError() << "Blogger1::createPost: post is null pointer";
00154     return;
00155   }
00156 
00157   unsigned int i= d->mCallCounter++;
00158   d->mCallMap[ i ] = post;
00159   kDebug() << "Creating new Post with blogid" << blogId();
00160   QList<QVariant> args( d->defaultArgs( blogId() ) );
00161   d->readArgsFromPost( &args, *post );
00162   d->mXmlRpcClient->call(
00163     d->getCallFromFunction( Blogger1Private::CreatePost ), args,
00164     this, SLOT(slotCreatePost(const QList<QVariant>&,const QVariant&)),
00165     this, SLOT(slotError(int, const QString&,const QVariant&)),
00166     QVariant( i ) );
00167 }
00168 
00169 void Blogger1::removePost( KBlog::BlogPost *post )
00170 {
00171   Q_D( Blogger1 );
00172 
00173   if ( !post ) {
00174     kError() << "Blogger1::removePost: post is null pointer";
00175     return;
00176   }
00177 
00178  unsigned int i = d->mCallCounter++;
00179  d->mCallMap[ i ] = post;
00180  kDebug() << "Blogger1::removePost: postId=" << post->postId();
00181  QList<QVariant> args( d->blogger1Args( post->postId() ) );
00182  args << QVariant( true ); // Publish must be set to remove post.
00183  d->mXmlRpcClient->call(
00184    "blogger.deletePost", args,
00185    this, SLOT(slotRemovePost(const QList<QVariant>&,const QVariant&)),
00186    this, SLOT(slotError(int,const QString&,const QVariant&)),
00187    QVariant( i ) );
00188 }
00189 
00190 Blogger1Private::Blogger1Private() :
00191 mXmlRpcClient(0)
00192 {
00193   mCallCounter = 1;
00194 }
00195 
00196 Blogger1Private::~Blogger1Private()
00197 {
00198   kDebug() << "~Blogger1Private()";
00199   delete mXmlRpcClient;
00200 }
00201 
00202 QList<QVariant> Blogger1Private::defaultArgs( const QString &id )
00203 {
00204   kDebug();
00205   Q_Q ( Blogger1 );
00206   QList<QVariant> args;
00207   args << QVariant( QString( "0123456789ABCDEF" ) );
00208   if( !id.isEmpty() ) {
00209     args << QVariant( id );
00210   }
00211   args << QVariant( q->username() )
00212        << QVariant( q->password() );
00213   return args;
00214 }
00215 
00216 // reimplemenet defaultArgs, since we may not use it virtually everywhere
00217 QList<QVariant> Blogger1Private::blogger1Args( const QString &id )
00218 {
00219   kDebug();
00220   Q_Q ( Blogger1 );
00221   QList<QVariant> args;
00222   args << QVariant( QString( "0123456789ABCDEF" ) );
00223   if( !id.isEmpty() ) {
00224     args << QVariant( id );
00225   }
00226   args << QVariant( q->username() )
00227        << QVariant( q->password() );
00228   return args;
00229 }
00230 
00231 void Blogger1Private::slotFetchUserInfo( const QList<QVariant> &result, const QVariant &id )
00232 {
00233   Q_Q( Blogger1 );
00234   Q_UNUSED( id );
00235 
00236   kDebug() << "Blog::slotFetchUserInfo";
00237   kDebug() << "TOP:" << result[0].typeName();
00238   QMap<QString,QString> userInfo;
00239   if ( result[0].type() != QVariant::Map ) {
00240     kError() << "Could not fetch user's info out of the result from the server,"
00241                  << "not a map.";
00242     emit q->error( Blogger1::ParsingError,
00243                         i18n( "Could not fetch user's info out of the result "
00244                               "from the server, not a map." ) );
00245     return;
00246   }
00247   const QMap<QString,QVariant> resultMap = result[0].toMap();
00248   userInfo["nickname"]=resultMap["nickname"].toString();
00249   userInfo["userid"]=resultMap["userid"].toString();
00250   userInfo["url"]=resultMap["url"].toString();
00251   userInfo["email"]=resultMap["email"].toString();
00252   userInfo["lastname"]=resultMap["lastname"].toString();
00253   userInfo["firstname"]=resultMap["firstname"].toString();
00254 
00255   emit q->fetchedUserInfo( userInfo );
00256 }
00257 
00258 void Blogger1Private::slotListBlogs( const QList<QVariant> &result, const QVariant &id )
00259 {
00260   Q_Q( Blogger1 );
00261   Q_UNUSED( id );
00262 
00263   kDebug() << "Blog::slotListBlogs";
00264   kDebug() << "TOP:" << result[0].typeName();
00265   QList<QMap<QString,QString> > blogsList;
00266   if ( result[0].type() != QVariant::List ) {
00267     kError() << "Could not fetch blogs out of the result from the server,"
00268                  << "not a list.";
00269     emit q->error( Blogger1::ParsingError,
00270                         i18n( "Could not fetch blogs out of the result "
00271                               "from the server, not a list." ) );
00272     return;
00273   }
00274   const QList<QVariant> posts = result[0].toList();
00275   QList<QVariant>::ConstIterator it = posts.begin();
00276   QList<QVariant>::ConstIterator end = posts.end();
00277   for ( ; it != end; ++it ) {
00278     kDebug() << "MIDDLE:" << ( *it ).typeName();
00279     const QMap<QString, QVariant> postInfo = ( *it ).toMap();
00280     QMap<QString,QString> blogInfo;
00281     blogInfo[ "id" ] = postInfo["blogid"].toString();
00282     blogInfo[ "name" ] = postInfo["blogName"].toString();
00283     kDebug() << "Blog information retrieved: ID =" << blogInfo["id"]
00284         << ", Name =" << blogInfo["name"];
00285     blogsList << blogInfo;
00286   }
00287   emit q->listedBlogs( blogsList );
00288 }
00289 
00290 void Blogger1Private::slotListRecentPosts( const QList<QVariant> &result, const QVariant &id )
00291 {
00292   Q_Q( Blogger1 );
00293   int count = id.toInt(); // not sure if needed, actually the API should
00294 // not give more posts
00295 
00296   kDebug() << "Blog::slotListRecentPosts";
00297   kDebug() << "TOP:" << result[0].typeName();
00298 
00299   QList <BlogPost> fetchedPostList;
00300 
00301   if ( result[0].type() != QVariant::List ) {
00302     kError() << "Could not fetch list of posts out of the"
00303                  << "result from the server, not a list.";
00304     emit q->error( Blogger1::ParsingError,
00305                    i18n( "Could not fetch list of posts out of the result "
00306                          "from the server, not a list." ) );
00307     return;
00308   }
00309   const QList<QVariant> postReceived = result[0].toList();
00310   QList<QVariant>::ConstIterator it = postReceived.begin();
00311   QList<QVariant>::ConstIterator end = postReceived.end();
00312   for ( ; it != end; ++it ) {
00313     BlogPost post;
00314     kDebug() << "MIDDLE:" << ( *it ).typeName();
00315     const QMap<QString, QVariant> postInfo = ( *it ).toMap();
00316     if ( readPostFromMap( &post, postInfo ) ) {
00317       kDebug() << "Post with ID:"
00318                     << post.postId()
00319                     << "appended in fetchedPostList";
00320       post.setStatus( BlogPost::Fetched );
00321       fetchedPostList.append( post );
00322     } else {
00323       kError() << "readPostFromMap failed!";
00324       emit q->error( Blogger1::ParsingError, i18n( "Could not read post." ) );
00325     }
00326     if ( --count == 0 ) {
00327       break;
00328     }
00329   }
00330   kDebug() << "Emitting listRecentPostsFinished()";
00331   emit q->listedRecentPosts( fetchedPostList );
00332 }
00333 
00334 void Blogger1Private::slotFetchPost( const QList<QVariant> &result, const QVariant &id )
00335 {
00336   Q_Q( Blogger1 );
00337   kDebug() << "Blog::slotFetchPost";
00338 
00339   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00340   mCallMap.remove( id.toInt() );
00341 
00342   //array of structs containing ISO.8601
00343   // dateCreated, String userid, String postid, String content;
00344   // TODO: Time zone for the dateCreated!
00345   kDebug () << "TOP:" << result[0].typeName();
00346   if ( result[0].type() == QVariant::Map && readPostFromMap( post, result[0].toMap() ) ) {
00347     kDebug() << "Emitting fetchedPost()";
00348     emit q->fetchedPost( post );
00349   } else {
00350     kError() << "Could not fetch post out of the result from the server.";
00351     post->setError( i18n( "Could not fetch post out of the result from the server." ) );
00352     post->setStatus( BlogPost::Error );
00353     emit q->errorPost( Blogger1::ParsingError,
00354                        i18n( "Could not fetch post out of the result from the server." ), post );
00355   }
00356 }
00357 
00358 void Blogger1Private::slotCreatePost( const QList<QVariant> &result, const QVariant &id )
00359 {
00360   Q_Q( Blogger1 );
00361   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00362   mCallMap.remove( id.toInt() );
00363 
00364   kDebug() << "Blog::slotCreatePost";
00365   //array of structs containing ISO.8601
00366   // dateCreated, String userid, String postid, String content;
00367   // TODO: Time zone for the dateCreated!
00368   kDebug () << "TOP:" << result[0].typeName();
00369   if ( result[0].type() != QVariant::String && result[0].type() != QVariant::Int ) {
00370     kError() << "Could not read the postId, not a string or an integer.";
00371     emit q->errorPost( Blogger1::ParsingError,
00372                           i18n( "Could not read the postId, not a string or an integer." ),
00373                           post );
00374     return;
00375   }
00376   QString serverID;
00377   if ( result[0].type() == QVariant::String ) {
00378     serverID = result[0].toString();
00379   }
00380   if ( result[0].type() == QVariant::Int ) {
00381     serverID = QString( "%1" ).arg( result[0].toInt() );
00382   }
00383   post->setPostId( serverID );
00384   post->setStatus( KBlog::BlogPost::Created );
00385   kDebug() << "emitting createdPost()"
00386                 << "for title: \"" << post->title()
00387                 << "\" server id: " << serverID;
00388   emit q->createdPost( post );
00389 }
00390 
00391 void Blogger1Private::slotModifyPost( const QList<QVariant> &result, const QVariant &id )
00392 {
00393   Q_Q( Blogger1 );
00394   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00395   mCallMap.remove( id.toInt() );
00396 
00397   kDebug() << "Blog::slotModifyPost";
00398   //array of structs containing ISO.8601
00399   // dateCreated, String userid, String postid, String content;
00400   // TODO: Time zone for the dateCreated!
00401   kDebug() << "TOP:" << result[0].typeName();
00402   if ( result[0].type() != QVariant::Bool ) {
00403     kError() << "Could not read the result, not a boolean.";
00404     emit q->errorPost( Blogger1::ParsingError,
00405                           i18n( "Could not read the result, not a boolean." ),
00406                           post );
00407     return;
00408   }
00409   post->setStatus( KBlog::BlogPost::Modified );
00410   kDebug() << "emitting modifiedPost() for title: \""
00411       << post->title() << "\"";
00412   emit q->modifiedPost( post );
00413 }
00414 
00415 void Blogger1Private::slotRemovePost( const QList<QVariant> &result, const QVariant &id )
00416 {
00417   Q_Q( Blogger1 );
00418   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00419   mCallMap.remove( id.toInt() );
00420 
00421   kDebug() << "Blog::slotRemovePost";
00422   //array of structs containing ISO.8601
00423   // dateCreated, String userid, String postid, String content;
00424   // TODO: Time zone for the dateCreated!
00425   kDebug() << "TOP:" << result[0].typeName();
00426   if ( result[0].type() != QVariant::Bool ) {
00427     kError() << "Could not read the result, not a boolean.";
00428     emit q->errorPost( Blogger1::ParsingError,
00429                           i18n( "Could not read the result, not a boolean." ),
00430                           post );
00431     return;
00432   }
00433   post->setStatus( KBlog::BlogPost::Removed );
00434   kDebug() << "emitting removedPost()";
00435   emit q->removedPost( post );
00436 }
00437 
00438 void Blogger1Private::slotError( int number,
00439                                  const QString &errorString,
00440                                  const QVariant &id )
00441 {
00442   Q_Q( Blogger1 );
00443   Q_UNUSED( number );
00444   BlogPost *post = mCallMap[ id.toInt() ];
00445 
00446   emit q->errorPost( Blogger1::XmlRpc, errorString, post );
00447 }
00448 
00449 bool Blogger1Private::readPostFromMap(
00450     BlogPost *post, const QMap<QString, QVariant> &postInfo )
00451 {
00452   // FIXME: integrate error handling
00453   if ( !post ) {
00454     return false;
00455   }
00456   QStringList mapkeys = postInfo.keys();
00457   kDebug() << endl << "Keys:" << mapkeys.join( ", " );
00458   kDebug() << endl;
00459 
00460   KDateTime dt( postInfo["dateCreated"].toDateTime(), KDateTime::UTC );
00461   if ( dt.isValid() && !dt.isNull() ) {
00462     post->setCreationDateTime( dt );
00463   }
00464   dt = KDateTime ( postInfo["lastModified"].toDateTime(), KDateTime::UTC );
00465   if ( dt.isValid() && !dt.isNull() ) {
00466     post->setModificationDateTime( dt );
00467   }
00468   post->setPostId( postInfo["postid"].toString() );
00469 
00470   QString title( postInfo["title"].toString() );
00471   QString description( postInfo["description"].toString() );
00472   QString contents( postInfo["content"].toString() );
00473   QStringList category;
00474 
00475   // Check for hacked title/category support (e.g. in Wordpress)
00476   QRegExp titleMatch = QRegExp( "<title>([^<]*)</title>" );
00477   QRegExp categoryMatch = QRegExp( "<category>([^<]*)</category>" );
00478   contents.remove( titleMatch );
00479   if ( titleMatch.numCaptures() > 0 ) {
00480     // Get the title value from the regular expression match
00481     title = titleMatch.cap( 1 );
00482   }
00483   contents.remove( categoryMatch );
00484   if ( categoryMatch.numCaptures() > 0 ) {
00485     // Get the category value from the regular expression match
00486     category = categoryMatch.capturedTexts();
00487   }
00488 
00489   post->setTitle( title );
00490   post->setContent( contents );
00491   post->setCategories( category );
00492   return true;
00493 }
00494 
00495 bool Blogger1Private::readArgsFromPost( QList<QVariant> *args, const BlogPost &post )
00496 {
00497   if ( !args ) {
00498     return false;
00499   }
00500   QStringList categories = post.categories();
00501   QString content = "<title>" + post.title() + "</title>";
00502   QStringList::const_iterator it;
00503   for ( it = categories.constBegin(); it != categories.constEnd(); ++it ) {
00504     content += "<category>" + *it + "</category>";
00505   }
00506   content += post.content();
00507   *args << QVariant( content );
00508   *args << QVariant( !post.isPrivate() );
00509   return true;
00510 }
00511 
00512 QString Blogger1Private::getCallFromFunction( FunctionToCall type )
00513 {
00514   switch ( type ) {
00515     case GetRecentPosts: return "blogger.getRecentPosts";
00516     case CreatePost:        return "blogger.newPost";
00517     case ModifyPost:       return "blogger.editPost";
00518     case FetchPost:        return "blogger.getPost";
00519     default: return QString();
00520   }
00521 }
00522 
00523 #include "blogger1.moc"

KBlog Client Library

Skip menu "KBlog Client Library"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal