• Skip to content
  • Skip to link menu
KDE 4.0 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 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(5323) << "Blogger1()";
00044   setUrl( server );
00045 }
00046 
00047 Blogger1::Blogger1( const KUrl &server, Blogger1Private &dd, QObject *parent )
00048   : Blog( server, dd, parent )
00049 {
00050   kDebug(5323) << "Blogger1()";
00051   setUrl( server );
00052 }
00053 
00054 Blogger1::~Blogger1()
00055 {
00056   kDebug(5323) << "~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(5323) << "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(5323) << "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(5323) << "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(5323) << "Blogger1::modifyPost: post is null pointer";
00112     return;
00113   }
00114 
00115   Q_D( Blogger1 );
00116   kDebug(5323) << "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(5323) << "Blogger1::modifyPost: post is null pointer";
00133     return;
00134   }
00135 
00136   kDebug(5323) << "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(5323) << "Blogger1::createPost: post is null pointer";
00154     return;
00155   }
00156 
00157   unsigned int i= d->mCallCounter++;
00158   d->mCallMap[ i ] = post;
00159   kDebug(5323) << "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(5323) << "Blogger1::removePost: post is null pointer";
00175     return;
00176   }
00177 
00178  unsigned int i = d->mCallCounter++;
00179  d->mCallMap[ i ] = post;
00180  kDebug(5323) << "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(5323) << "~Blogger1Private()";
00199   delete mXmlRpcClient;
00200 }
00201 
00202 QList<QVariant> Blogger1Private::defaultArgs( const QString &id )
00203 {
00204   Q_Q ( Blogger1 );
00205   QList<QVariant> args;
00206   args << QVariant( QString( "0123456789ABCDEF" ) );
00207   if( !id.isEmpty() ) {
00208     args << QVariant( id );
00209   }
00210   args << QVariant( q->username() )
00211        << QVariant( q->password() );
00212   return args;
00213 }
00214 
00215 // reimplemenet defaultArgs, since we may not use it virtually everywhere
00216 QList<QVariant> Blogger1Private::blogger1Args( const QString &id )
00217 {
00218   Q_Q( Blogger1 );
00219   QList<QVariant> args;
00220   args << QVariant( QString( "0123456789ABCDEF" ) );
00221   if( !id.isEmpty() ) {
00222     args << QVariant( id );
00223   }
00224   args << QVariant( q->username() )
00225        << QVariant( q->password() );
00226   return args;
00227 }
00228 
00229 void Blogger1Private::slotFetchUserInfo( const QList<QVariant> &result, const QVariant &id )
00230 {
00231   Q_Q( Blogger1 );
00232   Q_UNUSED( id );
00233 
00234   kDebug(5323) << "Blog::slotFetchUserInfo";
00235   kDebug(5323) << "TOP:" << result[0].typeName();
00236   QMap<QString,QString> userInfo;
00237   if ( result[0].type() != QVariant::Map ) {
00238     kError(5323) << "Could not fetch user's info out of the result from the server,"
00239                  << "not a map.";
00240     emit q->error( Blogger1::ParsingError,
00241                         i18n( "Could not fetch user's info out of the result "
00242                               "from the server, not a map." ) );
00243   } else {
00244     const QMap<QString,QVariant> resultMap = result[0].toMap();
00245     userInfo["nickname"]=resultMap["nickname"].toString();
00246     userInfo["userid"]=resultMap["userid"].toString();
00247     userInfo["url"]=resultMap["url"].toString();
00248     userInfo["email"]=resultMap["email"].toString();
00249     userInfo["lastname"]=resultMap["lastname"].toString();
00250     userInfo["firstname"]=resultMap["firstname"].toString();
00251 
00252     emit q->fetchedUserInfo( userInfo );
00253   }
00254 }
00255 
00256 void Blogger1Private::slotListBlogs( const QList<QVariant> &result, const QVariant &id )
00257 {
00258   Q_Q( Blogger1 );
00259   Q_UNUSED( id );
00260 
00261   kDebug(5323) << "Blog::slotListBlogs";
00262   kDebug(5323) << "TOP:" << result[0].typeName();
00263   QList<QMap<QString,QString> > blogsList;
00264   if ( result[0].type() != QVariant::List ) {
00265     kError(5323) << "Could not fetch blogs out of the result from the server,"
00266                  << "not a list.";
00267     emit q->error( Blogger1::ParsingError,
00268                         i18n( "Could not fetch blogs out of the result "
00269                               "from the server, not a list." ) );
00270   } else {
00271     const QList<QVariant> posts = result[0].toList();
00272     QList<QVariant>::ConstIterator it = posts.begin();
00273     QList<QVariant>::ConstIterator end = posts.end();
00274     for ( ; it != end; ++it ) {
00275       kDebug(5323) << "MIDDLE:" << ( *it ).typeName();
00276       const QMap<QString, QVariant> postInfo = ( *it ).toMap();
00277       QMap<QString,QString> blogInfo;
00278       blogInfo[ "id" ] = postInfo["blogid"].toString();
00279       blogInfo[ "name" ] = postInfo["blogName"].toString();
00280       kDebug(5323) << "Blog information retrieved: ID =" << blogInfo["id"]
00281           << ", Name =" << blogInfo["name"];
00282       blogsList << blogInfo;
00283     }
00284     emit q->listedBlogs( blogsList );
00285   }
00286 }
00287 
00288 void Blogger1Private::slotListRecentPosts( const QList<QVariant> &result, const QVariant &id )
00289 {
00290   Q_Q( Blogger1 );
00291   int count = id.toInt(); // not sure if needed, actually the API should
00292 // not give more posts
00293 
00294   kDebug(5323) << "Blog::slotListRecentPosts";
00295   kDebug(5323) << "TOP:" << result[0].typeName();
00296 
00297   QList <BlogPost> fetchedPostList;
00298 
00299   if ( result[0].type() != QVariant::List ) {
00300     kError(5323) << "Could not fetch list of posts out of the"
00301                  << "result from the server, not a list.";
00302     emit q->error( Blogger1::ParsingError,
00303                    i18n( "Could not fetch list of posts out of the result "
00304                          "from the server, not a list." ) );
00305   } else {
00306     const QList<QVariant> postReceived = result[0].toList();
00307     QList<QVariant>::ConstIterator it = postReceived.begin();
00308     QList<QVariant>::ConstIterator end = postReceived.end();
00309     for ( ; it != end; ++it ) {
00310       BlogPost post;
00311       kDebug(5323) << "MIDDLE:" << ( *it ).typeName();
00312       const QMap<QString, QVariant> postInfo = ( *it ).toMap();
00313       if ( readPostFromMap( &post, postInfo ) ) {
00314         kDebug(5323) << "Post with ID:"
00315                      << post.postId()
00316                      << "appended in fetchedPostList";
00317         post.setStatus( BlogPost::Fetched );
00318         fetchedPostList.append( post );
00319       } else {
00320         kError(5323) << "readPostFromMap failed!";
00321         emit q->error( Blogger1::ParsingError, i18n( "Could not read post." ) );
00322       }
00323       if ( --count == 0 ) {
00324         break;
00325       }
00326     }
00327   }
00328   kDebug(5323) << "Emitting listRecentPostsFinished()";
00329   emit q->listedRecentPosts( fetchedPostList );
00330 }
00331 
00332 void Blogger1Private::slotFetchPost( const QList<QVariant> &result, const QVariant &id )
00333 {
00334   Q_Q( Blogger1 );
00335   kDebug(5323) << "Blog::slotFetchPost";
00336 
00337   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00338   mCallMap.remove( id.toInt() );
00339 
00340   //array of structs containing ISO.8601
00341   // dateCreated, String userid, String postid, String content;
00342   // TODO: Time zone for the dateCreated!
00343   kDebug (5323) << "TOP:" << result[0].typeName();
00344   if ( result[0].type() != QVariant::Map ) {
00345     kError(5323) << "Could not fetch post out of the result from "
00346                   << "the server.";
00347     emit q->errorPost( Blogger1::ParsingError,
00348                           i18n( "Could not fetch post out of the result "
00349                                 "from the server." ), post );
00350     post->setError( i18n( "Could not fetch post out of the "
00351                               "result from the server." ) );
00352     post->setStatus( BlogPost::Error );
00353   } else {
00354     const QMap<QString, QVariant> postInfo = result[0].toMap();
00355     if ( readPostFromMap( post, postInfo ) ) {
00356       kDebug(5323) << "Emitting fetchedPost( post.postId()="
00357                    << post->postId() << ");";
00358       post->setStatus( BlogPost::Fetched );
00359       emit q->fetchedPost( post );
00360     } else {
00361       kError(5323) << "readPostFromMap failed!";
00362       emit q->errorPost( Blogger1::ParsingError,
00363                             i18n( "Could not read post." ), post );
00364       post->setError( i18n( "Could not read post." ) );
00365       post->setStatus( BlogPost::Error );
00366     }
00367   }
00368 
00369 }
00370 
00371 void Blogger1Private::slotCreatePost( const QList<QVariant> &result, const QVariant &id )
00372 {
00373   Q_Q( Blogger1 );
00374   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00375   mCallMap.remove( id.toInt() );
00376 
00377   kDebug(5323) << "Blog::slotCreatePost";
00378   //array of structs containing ISO.8601
00379   // dateCreated, String userid, String postid, String content;
00380   // TODO: Time zone for the dateCreated!
00381   kDebug (5323) << "TOP:" << result[0].typeName();
00382   if ( result[0].type() != QVariant::String && result[0].type() != QVariant::Int ) {
00383     kError(5323) << "Could not read the postId, not a string or an integer.";
00384     emit q->errorPost( Blogger1::ParsingError,
00385                           i18n( "Could not read the postId, not a string or an integer." ),
00386                           post );
00387   } else {
00388     QString id;
00389     if ( result[0].type() == QVariant::String ) {
00390       id = result[0].toString();
00391     }
00392     if ( result[0].type() == QVariant::Int ) {
00393       id = QString( "%1" ).arg( result[0].toInt() );
00394     }
00395     post->setPostId( id );
00396     post->setStatus( KBlog::BlogPost::Created );
00397     emit q->createdPost( post );
00398     kDebug(5323) << "emitting createdPost()"
00399                  << "for title: \"" << post->title()
00400                  << "\" server id: " << id;
00401   }
00402 
00403 }
00404 
00405 void Blogger1Private::slotModifyPost( const QList<QVariant> &result, const QVariant &id )
00406 {
00407   Q_Q( Blogger1 );
00408   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00409   mCallMap.remove( id.toInt() );
00410 
00411   kDebug(5323) << "Blog::slotModifyPost";
00412   //array of structs containing ISO.8601
00413   // dateCreated, String userid, String postid, String content;
00414   // TODO: Time zone for the dateCreated!
00415   kDebug(5323) << "TOP:" << result[0].typeName();
00416   if ( result[0].type() != QVariant::Bool ) {
00417     kError(5323) << "Could not read the result, not a boolean.";
00418     emit q->errorPost( Blogger1::ParsingError,
00419                           i18n( "Could not read the result, not a boolean." ),
00420                           post );
00421   } else {
00422     post->setStatus( KBlog::BlogPost::Modified );
00423     emit q->modifiedPost( post );
00424     kDebug(5323) << "emitting modifiedPost() for title: \""
00425                             << post->title() << "\"";
00426   }
00427 }
00428 
00429 void Blogger1Private::slotRemovePost( const QList<QVariant> &result, const QVariant &id )
00430 {
00431   Q_Q( Blogger1 );
00432   KBlog::BlogPost *post = mCallMap[ id.toInt() ];
00433   mCallMap.remove( id.toInt() );
00434 
00435   kDebug(5323) << "Blog::slotRemovePost";
00436   //array of structs containing ISO.8601
00437   // dateCreated, String userid, String postid, String content;
00438   // TODO: Time zone for the dateCreated!
00439   kDebug(5323) << "TOP:" << result[0].typeName();
00440   if ( result[0].type() != QVariant::Bool ) {
00441     kError(5323) << "Could not read the result, not a boolean.";
00442     emit q->errorPost( Blogger1::ParsingError,
00443                           i18n( "Could not read the result, not a boolean." ),
00444                           post );
00445   } else {
00446     post->setStatus( KBlog::BlogPost::Removed );
00447     emit q->removedPost( post );
00448     kDebug(5323) << "emitting removedPost()";
00449   }
00450 }
00451 
00452 void Blogger1Private::slotError( int number,
00453                                  const QString &errorString,
00454                                  const QVariant &id )
00455 {
00456   Q_Q( Blogger1 );
00457   Q_UNUSED( number );
00458   BlogPost *post = mCallMap[ id.toInt() ];
00459 
00460   emit q->errorPost( Blogger1::XmlRpc, errorString, post );
00461 }
00462 
00463 bool Blogger1Private::readPostFromMap(
00464     BlogPost *post, const QMap<QString, QVariant> &postInfo )
00465 {
00466   // FIXME: integrate error handling
00467   if ( !post ) {
00468     return false;
00469   }
00470   QStringList mapkeys = postInfo.keys();
00471   kDebug(5323) << endl << "Keys:" << mapkeys.join( ", " );
00472   kDebug(5323) << endl;
00473 
00474   KDateTime dt( postInfo["dateCreated"].toDateTime(), KDateTime::UTC );
00475   if ( dt.isValid() && !dt.isNull() ) {
00476     post->setCreationDateTime( dt );
00477   }
00478   dt = KDateTime ( postInfo["lastModified"].toDateTime(), KDateTime::UTC );
00479   if ( dt.isValid() && !dt.isNull() ) {
00480     post->setModificationDateTime( dt );
00481   }
00482   post->setPostId( postInfo["postid"].toString() );
00483 
00484   QString title( postInfo["title"].toString() );
00485   QString description( postInfo["description"].toString() );
00486   QString contents( postInfo["content"].toString() );
00487   QStringList category;
00488 
00489   // Check for hacked title/category support (e.g. in Wordpress)
00490   QRegExp titleMatch = QRegExp( "<title>([^<]*)</title>" );
00491   QRegExp categoryMatch = QRegExp( "<category>([^<]*)</category>" );
00492   contents.remove( titleMatch );
00493   if ( titleMatch.numCaptures() > 0 ) {
00494     // Get the title value from the regular expression match
00495     title = titleMatch.cap( 1 );
00496   }
00497   contents.remove( categoryMatch );
00498   if ( categoryMatch.numCaptures() > 0 ) {
00499     // Get the category value from the regular expression match
00500     category = categoryMatch.capturedTexts();
00501   }
00502 
00503   post->setTitle( title );
00504   post->setContent( contents );
00505   post->setCategories( category );
00506   return true;
00507 }
00508 
00509 bool Blogger1Private::readArgsFromPost( QList<QVariant> *args, const BlogPost &post )
00510 {
00511   if ( !args ) {
00512     return false;
00513   }
00514   QStringList categories = post.categories();
00515   QString content = "<title>" + post.title() + "</title>";
00516   QStringList::const_iterator it;
00517   for ( it = categories.constBegin(); it != categories.constEnd(); ++it ) {
00518     content += "<category>" + *it + "</category>";
00519   }
00520   content += post.content();
00521   *args << QVariant( content );
00522   *args << QVariant( !post.isPrivate() );
00523   return true;
00524 }
00525 
00526 QString Blogger1Private::getCallFromFunction( FunctionToCall type )
00527 {
00528   switch ( type ) {
00529     case GetRecentPosts: return "blogger.getRecentPosts";
00530     case CreatePost:        return "blogger.newPost";
00531     case ModifyPost:       return "blogger.editPost";
00532     case FetchPost:        return "blogger.getPost";
00533     default: return QString();
00534   }
00535 }
00536 
00537 #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"
  • kabc
  • kblog
  • kcal
  • kimap
  • kioslave
  •   imap4
  •   mbox
  • kldap
  • kmime
  • kpimidentities
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.5.5
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