1 | /* |
2 | This file is part of the kblog library. |
3 | |
4 | Copyright (c) 2004 Reinhold Kainhofer <reinhold@kainhofer.com> |
5 | Copyright (c) 2006-2007 Christian Weilbach <christian_weilbach@web.de> |
6 | Copyright (c) 2007 Mike McQuaid <mike@mikemcquaid.com> |
7 | |
8 | This library is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU Library General Public |
10 | License as published by the Free Software Foundation; either |
11 | version 2 of the License, or (at your option) any later version. |
12 | |
13 | This library is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | Library General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Library General Public License |
19 | along with this library; see the file COPYING.LIB. If not, write to |
20 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 | Boston, MA 02110-1301, USA. |
22 | */ |
23 | |
24 | #include "metaweblog.h" |
25 | #include "metaweblog_p.h" |
26 | #include "blogpost.h" |
27 | #include "blogmedia.h" |
28 | |
29 | #include <kxmlrpcclient/client.h> |
30 | #include <KDebug> |
31 | #include <KLocalizedString> |
32 | #include <KDateTime> |
33 | #include <kstandarddirs.h> |
34 | |
35 | #include <QtCore/QFile> |
36 | #include <QtCore/QDataStream> |
37 | |
38 | using namespace KBlog; |
39 | |
40 | MetaWeblog::MetaWeblog( const KUrl &server, QObject *parent ) |
41 | : Blogger1( server, *new MetaWeblogPrivate, parent ) |
42 | { |
43 | kDebug(); |
44 | } |
45 | |
46 | MetaWeblog::MetaWeblog( const KUrl &server, MetaWeblogPrivate &dd, QObject *parent ) |
47 | : Blogger1( server, dd, parent ) |
48 | { |
49 | kDebug(); |
50 | } |
51 | |
52 | MetaWeblog::~MetaWeblog() |
53 | { |
54 | kDebug(); |
55 | } |
56 | |
57 | QString MetaWeblog::interfaceName() const |
58 | { |
59 | return QLatin1String( "MetaWeblog" ); |
60 | } |
61 | |
62 | void MetaWeblog::listCategories() |
63 | { |
64 | Q_D( MetaWeblog ); |
65 | kDebug() << "Fetching List of Categories..." ; |
66 | QList<QVariant> args( d->defaultArgs( blogId() ) ); |
67 | d->mXmlRpcClient->call( |
68 | QLatin1String("metaWeblog.getCategories" ), args, |
69 | this, SLOT(slotListCategories(QList<QVariant>,QVariant)), |
70 | this, SLOT(slotError(int,QString,QVariant)) ); |
71 | } |
72 | |
73 | void MetaWeblog::createMedia( KBlog::BlogMedia *media ) |
74 | { |
75 | Q_D( MetaWeblog ); |
76 | if ( !media ) { |
77 | kError() << "MetaWeblog::createMedia: media is a null pointer" ; |
78 | emit error ( Other, i18n( "Media is a null pointer." ) ); |
79 | return; |
80 | } |
81 | unsigned int i = d->mCallMediaCounter++; |
82 | d->mCallMediaMap[ i ] = media; |
83 | kDebug() << "MetaWeblog::createMedia: name=" << media->name(); |
84 | QList<QVariant> args( d->defaultArgs( blogId() ) ); |
85 | QMap<QString, QVariant> map; |
86 | map[QLatin1String("name" )] = media->name(); |
87 | map[QLatin1String("type" )] = media->mimetype(); |
88 | map[QLatin1String("bits" )] = media->data(); |
89 | args << map; |
90 | d->mXmlRpcClient->call( |
91 | QLatin1String("metaWeblog.newMediaObject" ), args, |
92 | this, SLOT(slotCreateMedia(QList<QVariant>,QVariant)), |
93 | this, SLOT(slotError(int,QString,QVariant)), |
94 | QVariant( i ) ); |
95 | |
96 | } |
97 | |
98 | MetaWeblogPrivate::MetaWeblogPrivate() |
99 | { |
100 | kDebug(); |
101 | mCallMediaCounter=1; |
102 | mCatLoaded=false; |
103 | } |
104 | |
105 | MetaWeblogPrivate::~MetaWeblogPrivate() |
106 | { |
107 | kDebug(); |
108 | } |
109 | |
110 | QList<QVariant> MetaWeblogPrivate::defaultArgs( const QString &id ) |
111 | { |
112 | Q_Q( MetaWeblog ); |
113 | QList<QVariant> args; |
114 | if ( !id.isEmpty() ) { |
115 | args << QVariant( id ); |
116 | } |
117 | args << QVariant( q->username() ) |
118 | << QVariant( q->password() ); |
119 | return args; |
120 | } |
121 | |
122 | void MetaWeblogPrivate::loadCategories() |
123 | { |
124 | kDebug(); |
125 | |
126 | if ( mCatLoaded ) { |
127 | return; |
128 | } |
129 | mCatLoaded = true; |
130 | |
131 | if ( mUrl.isEmpty() || mBlogId.isEmpty() || mUsername.isEmpty() ) { |
132 | kDebug() << "We need at least url, blogId and the username to create a unique filename." ; |
133 | return; |
134 | } |
135 | |
136 | QString filename = QLatin1String("kblog/" ) + mUrl.host() + QLatin1Char('_') + mBlogId + QLatin1Char('_') + mUsername; |
137 | filename = KStandardDirs::locateLocal( "data" , filename, true ); |
138 | |
139 | QFile file( filename ); |
140 | if ( !file.open( QIODevice::ReadOnly ) ) { |
141 | kDebug() << "Cannot open cached categories file: " << filename; |
142 | return; |
143 | } |
144 | |
145 | QDataStream stream( &file ); |
146 | stream >> mCategoriesList; |
147 | file.close(); |
148 | } |
149 | |
150 | void MetaWeblogPrivate::saveCategories() |
151 | { |
152 | kDebug(); |
153 | if ( mUrl.isEmpty() || mBlogId.isEmpty() || mUsername.isEmpty() ) { |
154 | kDebug() << "We need at least url, blogId and the username to create a unique filename." ; |
155 | return; |
156 | } |
157 | |
158 | QString filename = QLatin1String("kblog/" ) + mUrl.host() + QLatin1Char('_') + mBlogId + QLatin1Char('_') + mUsername; |
159 | filename = KStandardDirs::locateLocal( "data" , filename, true ); |
160 | |
161 | QFile file( filename ); |
162 | if ( !file.open( QIODevice::WriteOnly ) ) { |
163 | kDebug() << "Cannot open cached categories file: " << filename; |
164 | return; |
165 | } |
166 | |
167 | QDataStream stream( &file ); |
168 | stream << mCategoriesList; |
169 | file.close(); |
170 | } |
171 | |
172 | void MetaWeblogPrivate::slotListCategories( const QList<QVariant> &result, |
173 | const QVariant &id ) |
174 | { |
175 | Q_Q( MetaWeblog ); |
176 | Q_UNUSED( id ); |
177 | |
178 | kDebug() << "MetaWeblogPrivate::slotListCategories" ; |
179 | kDebug() << "TOP:" << result[0].typeName(); |
180 | if ( result[0].type() != QVariant::Map && |
181 | result[0].type() != QVariant::List ) { |
182 | // include fix for not metaweblog standard compatible apis with |
183 | // array of structs instead of struct of structs, e.g. wordpress |
184 | kError() << "Could not list categories out of the result from the server." ; |
185 | emit q->error( MetaWeblog::ParsingError, |
186 | i18n( "Could not list categories out of the result " |
187 | "from the server." ) ); |
188 | } else { |
189 | if ( result[0].type() == QVariant::Map ) { |
190 | const QMap<QString, QVariant> serverMap = result[0].toMap(); |
191 | const QList<QString> serverKeys = serverMap.keys(); |
192 | |
193 | QList<QString>::ConstIterator it = serverKeys.begin(); |
194 | QList<QString>::ConstIterator end = serverKeys.end(); |
195 | for ( ; it != end; ++it ) { |
196 | kDebug() << "MIDDLE:" << ( *it ); |
197 | QMap<QString,QString> category; |
198 | const QMap<QString, QVariant> serverCategory = serverMap[*it].toMap(); |
199 | category[QLatin1String("name" )]= ( *it ); |
200 | category[QLatin1String("description" )] = serverCategory[ QLatin1String("description" ) ].toString(); |
201 | category[QLatin1String("htmlUrl" )] = serverCategory[ QLatin1String("htmlUrl" ) ].toString(); |
202 | category[QLatin1String("rssUrl" )] = serverCategory[ QLatin1String("rssUrl" ) ].toString(); |
203 | category[QLatin1String("categoryId" )] = serverCategory[ QLatin1String("categoryId" ) ].toString(); |
204 | category[QLatin1String("parentId" )] = serverCategory[ QLatin1String("parentId" ) ].toString(); |
205 | mCategoriesList.append( category ); |
206 | } |
207 | kDebug() << "Emitting listedCategories" ; |
208 | emit q->listedCategories( mCategoriesList ); |
209 | } |
210 | } |
211 | if ( result[0].type() == QVariant::List ) { |
212 | // include fix for not metaweblog standard compatible apis with |
213 | // array of structs instead of struct of structs, e.g. wordpress |
214 | const QList<QVariant> serverList = result[0].toList(); |
215 | QList<QVariant>::ConstIterator it = serverList.begin(); |
216 | QList<QVariant>::ConstIterator end = serverList.end(); |
217 | for ( ; it != end; ++it ) { |
218 | kDebug() << "MIDDLE:" << ( *it ).typeName(); |
219 | QMap<QString,QString> category; |
220 | const QMap<QString, QVariant> serverCategory = ( *it ).toMap(); |
221 | category[ QLatin1String("name" ) ] = serverCategory[QLatin1String("categoryName" )].toString(); |
222 | category[QLatin1String("description" )] = serverCategory[ QLatin1String("description" ) ].toString(); |
223 | category[QLatin1String("htmlUrl" )] = serverCategory[ QLatin1String("htmlUrl" ) ].toString(); |
224 | category[QLatin1String("rssUrl" )] = serverCategory[ QLatin1String("rssUrl" ) ].toString(); |
225 | category[QLatin1String("categoryId" )] = serverCategory[ QLatin1String("categoryId" ) ].toString(); |
226 | category[QLatin1String("parentId" )] = serverCategory[ QLatin1String("parentId" ) ].toString(); |
227 | mCategoriesList.append( category ); |
228 | } |
229 | kDebug() << "Emitting listedCategories()" ; |
230 | emit q->listedCategories( mCategoriesList ); |
231 | } |
232 | saveCategories(); |
233 | } |
234 | |
235 | void MetaWeblogPrivate::slotCreateMedia( const QList<QVariant> &result, |
236 | const QVariant &id ) |
237 | { |
238 | Q_Q( MetaWeblog ); |
239 | |
240 | KBlog::BlogMedia *media = mCallMediaMap[ id.toInt() ]; |
241 | mCallMediaMap.remove( id.toInt() ); |
242 | |
243 | kDebug() << "MetaWeblogPrivate::slotCreateMedia, no error!" ; |
244 | kDebug() << "TOP:" << result[0].typeName(); |
245 | if ( result[0].type() != 8 ) { |
246 | kError() << "Could not read the result, not a map." ; |
247 | emit q->errorMedia( MetaWeblog::ParsingError, |
248 | i18n( "Could not read the result, not a map." ), |
249 | media ); |
250 | return; |
251 | } |
252 | const QMap<QString, QVariant> resultStruct = result[0].toMap(); |
253 | const QString url = resultStruct[QLatin1String("url" )].toString(); |
254 | kDebug() << "MetaWeblog::slotCreateMedia url=" << url; |
255 | |
256 | if ( !url.isEmpty() ) { |
257 | media->setUrl( KUrl( url ) ); |
258 | media->setStatus( BlogMedia::Created ); |
259 | kDebug() << "Emitting createdMedia( url=" << url << ");" ; |
260 | emit q->createdMedia( media ); |
261 | } |
262 | } |
263 | |
264 | bool MetaWeblogPrivate::readPostFromMap( BlogPost *post, |
265 | const QMap<QString, QVariant> &postInfo ) |
266 | { |
267 | // FIXME: integrate error handling |
268 | kDebug() << "readPostFromMap()" ; |
269 | if ( !post ) { |
270 | return false; |
271 | } |
272 | QStringList mapkeys = postInfo.keys(); |
273 | kDebug() << endl << "Keys:" << mapkeys.join( QLatin1String(", " ) ); |
274 | kDebug() << endl; |
275 | |
276 | KDateTime dt = |
277 | KDateTime( postInfo[QLatin1String("dateCreated" )].toDateTime(), KDateTime::UTC ); |
278 | if ( dt.isValid() && !dt.isNull() ) { |
279 | post->setCreationDateTime( dt.toLocalZone() ); |
280 | } |
281 | |
282 | dt = |
283 | KDateTime( postInfo[QLatin1String("lastModified" )].toDateTime(), KDateTime::UTC ); |
284 | if ( dt.isValid() && !dt.isNull() ) { |
285 | post->setModificationDateTime( dt.toLocalZone() ); |
286 | } |
287 | |
288 | post->setPostId( postInfo[QLatin1String("postid" )].toString().isEmpty() ? postInfo[QLatin1String("postId" )].toString() : |
289 | postInfo[QLatin1String("postid" )].toString() ); |
290 | |
291 | QString title( postInfo[QLatin1String("title" )].toString() ); |
292 | QString description( postInfo[QLatin1String("description" )].toString() ); |
293 | QStringList categories( postInfo[QLatin1String("categories" )].toStringList() ); |
294 | |
295 | post->setTitle( title ); |
296 | post->setContent( description ); |
297 | if ( !categories.isEmpty() ) { |
298 | kDebug() << "Categories:" << categories; |
299 | post->setCategories( categories ); |
300 | } |
301 | return true; |
302 | } |
303 | |
304 | bool MetaWeblogPrivate::readArgsFromPost( QList<QVariant> *args, const BlogPost &post ) |
305 | { |
306 | if ( !args ) { |
307 | return false; |
308 | } |
309 | QMap<QString, QVariant> map; |
310 | map[QLatin1String("categories" )] = post.categories(); |
311 | map[QLatin1String("description" )] = post.content(); |
312 | map[QLatin1String("title" )] = post.title(); |
313 | map[QLatin1String("lastModified" )] = post.modificationDateTime().dateTime().toUTC(); |
314 | map[QLatin1String("dateCreated" )] = post.creationDateTime().dateTime().toUTC(); |
315 | *args << map; |
316 | *args << QVariant( !post.isPrivate() ); |
317 | return true; |
318 | } |
319 | |
320 | QString MetaWeblogPrivate::getCallFromFunction( FunctionToCall type ) |
321 | { |
322 | switch ( type ) { |
323 | case GetRecentPosts: return QLatin1String("metaWeblog.getRecentPosts" ); |
324 | case CreatePost: return QLatin1String("metaWeblog.newPost" ); |
325 | case ModifyPost: return QLatin1String("metaWeblog.editPost" ); |
326 | case FetchPost: return QLatin1String("metaWeblog.getPost" ); |
327 | default: return QString(); |
328 | } |
329 | } |
330 | #include "moc_metaweblog.cpp" |
331 | |