28 #include <syndication/atom/constants.h>
29 #include <syndication/constants.h>
31 #include <QCoreApplication>
36 #include <QStringList>
37 #include <QXmlStreamWriter>
40 #include <KComponentData>
42 #include <KPluginLoader>
44 #include <KServiceTypeTrader>
51 using namespace Akregator;
52 using namespace Akregator::Backend;
55 static QString akregatorNamespace() {
56 return QString::fromLatin1(
"http://akregator.kde.org/StorageExporter#");
76 Element(
const QString& ns_,
const QString& name_ ) : ns( ns_ ), name( name_ ), qualifiedName( ns + QLatin1Char(
':') + name )
82 const QString qualifiedName;
84 void writeStartElement( QXmlStreamWriter& writer )
const
87 writer.writeStartElement( ns, name );
89 writer.writeStartElement( name );
92 void write(
const QVariant& value , QXmlStreamWriter& writer,
TextMode mode = PlainText )
const
94 const QVariant qv( value );
95 Q_ASSERT( qv.canConvert( QVariant::String ) );
96 const QString str = qv.toString();
101 writer.writeStartElement( name );
103 writer.writeStartElement( ns, name );
106 writer.writeAttribute( QLatin1String(
"type"), QLatin1String(
"html") );
108 writer.writeCharacters( str );
109 writer.writeEndElement();
115 Elements() : atomNS( Syndication::Atom::atom1Namespace() ),
116 akregatorNS(akregatorNamespace() ),
117 commentNS( Syndication::commentApiNamespace() ),
118 title( atomNS, QLatin1String(
"title") ),
119 summary( atomNS, QLatin1String(
"summary") ),
120 content( atomNS, QLatin1String(
"content") ),
121 link( atomNS, QLatin1String(
"link") ),
122 language( atomNS, QLatin1String(
"language") ),
123 feed( atomNS, QLatin1String(
"feed") ),
124 guid( atomNS, QLatin1String(
"id") ),
125 published( atomNS, QLatin1String(
"published") ),
126 updated( atomNS, QLatin1String(
"updated") ),
127 commentsCount( Syndication::slashNamespace(), QLatin1String(
"comments") ),
128 commentsFeed( commentNS, QLatin1String(
"commentRss") ),
129 commentPostUri( commentNS, QLatin1String(
"comment") ),
130 commentsLink( akregatorNS, QLatin1String(
"commentsLink") ),
131 hash( akregatorNS, QLatin1String(
"hash") ),
132 guidIsHash( akregatorNS, QLatin1String(
"idIsHash") ),
133 name( atomNS, QLatin1String(
"name") ),
134 uri( atomNS, QLatin1String(
"uri") ),
135 email( atomNS, QLatin1String(
"email") ),
136 author( atomNS, QLatin1String(
"author") ),
137 category( atomNS, QLatin1String(
"category") ),
138 entry( atomNS, QLatin1String(
"entry") ),
139 itemProperties( akregatorNS, QLatin1String(
"itemProperties") ),
140 readStatus( akregatorNS, QLatin1String(
"readStatus") ),
141 deleted( akregatorNS, QLatin1String(
"deleted") ),
142 important( akregatorNS, QLatin1String(
"important") )
145 const QString atomNS;
146 const QString akregatorNS;
147 const QString commentNS;
149 const Element summary;
150 const Element content;
152 const Element language;
155 const Element published;
156 const Element updated;
157 const Element commentsCount;
158 const Element commentsFeed;
159 const Element commentPostUri;
160 const Element commentsLink;
162 const Element guidIsHash;
166 const Element author;
167 const Element category;
169 const Element itemProperties;
170 const Element readStatus;
171 const Element deleted;
172 const Element important;
173 static const Elements instance;
176 const Elements Elements::instance;
178 void writeAttributeIfNotEmpty(
const QString& ns,
const QString& element,
const QVariant& value, QXmlStreamWriter& writer )
180 const QString text = value.toString();
181 if ( text.isEmpty() )
183 writer.writeAttribute( ns, element, text );
186 void writeAttributeIfNotEmpty(
const QString& element,
const QVariant& value, QXmlStreamWriter& writer )
188 const QString text = value.toString();
189 if ( text.isEmpty() )
191 writer.writeAttribute( element, text );
194 void writeEnclosure(
const QString& url,
const QString& type,
int length, QXmlStreamWriter& writer )
196 Elements::instance.link.writeStartElement( writer );
197 writer.writeAttribute( QLatin1String(
"rel"), QLatin1String(
"enclosure") );
198 writeAttributeIfNotEmpty( QLatin1String(
"href"), url, writer );
199 writeAttributeIfNotEmpty( QLatin1String(
"type"), type, writer );
201 writer.writeAttribute( QLatin1String(
"length"), QString::number( length ) );
202 writer.writeEndElement();
205 void writeLink(
const QString& url, QXmlStreamWriter& writer )
209 Elements::instance.link.writeStartElement( writer );
210 writer.writeAttribute( QLatin1String(
"rel"), QLatin1String(
"alternate") );
211 writeAttributeIfNotEmpty( QLatin1String(
"href"), url, writer );
212 writer.writeEndElement();
215 void writeAuthor(
const QString& name,
const QString& uri,
const QString& email, QXmlStreamWriter& writer )
217 if ( name.isEmpty() && uri.isEmpty() && email.isEmpty() )
220 const QString atomNS = Syndication::Atom::atom1Namespace();
221 Elements::instance.author.writeStartElement( writer );
222 Elements::instance.name.write( name, writer );
223 Elements::instance.uri.write( uri, writer );
224 Elements::instance.email.write( email, writer );
225 writer.writeEndElement();
228 static void writeItem(
FeedStorage* storage,
const QString& guid, QXmlStreamWriter& writer ) {
229 Elements::instance.entry.writeStartElement( writer );
230 Elements::instance.guid.write( guid, writer );
233 if ( published > 0 ) {
234 const QString pdStr = QDateTime::fromTime_t( published ).toString( Qt::ISODate );
235 Elements::instance.published.write( pdStr, writer );
238 const int status = storage->
status( guid );
240 Elements::instance.itemProperties.writeStartElement( writer );
242 if ( status & Deleted ) {
243 Elements::instance.deleted.write( QString::fromLatin1(
"true"), writer );
244 writer.writeEndElement();
245 writer.writeEndElement();
249 Elements::instance.hash.write( QString::number( storage->
hash( guid ) ), writer );
251 Elements::instance.guidIsHash.write( QString::fromLatin1(
"true"), writer );
253 Elements::instance.readStatus.write( QString::fromLatin1(
"new"), writer );
254 else if ( ( status &
Read ) == 0 )
255 Elements::instance.readStatus.write( QString::fromLatin1(
"unread"), writer );
257 Elements::instance.important.write( QString::fromLatin1(
"true"), writer );
258 writer.writeEndElement();
260 Elements::instance.title.write( storage->
title( guid ), writer, Html );
263 Elements::instance.summary.write( storage->
description( guid ), writer, Html );
264 Elements::instance.content.write( storage->
content( guid ), writer, Html );
270 if (
const int commentsCount = storage->
comments( guid ) )
271 Elements::instance.commentsCount.write( QString::number( commentsCount ), writer );
273 Elements::instance.commentsLink.write( storage->
commentsLink( guid ), writer );
276 QString encUrl, encType;
278 storage->
enclosure( guid, hasEnc, encUrl, encType, encLength );
280 writeEnclosure( encUrl, encType, encLength, writer );
281 writer.writeEndElement();
284 static void serialize(
FeedStorage* storage,
const QString& url, QIODevice* device ) {
287 QXmlStreamWriter writer( device );
288 writer.setAutoFormatting(
true );
289 writer.setAutoFormattingIndent( 2 );
290 writer.writeStartDocument();
292 Elements::instance.feed.writeStartElement( writer );
294 writer.writeDefaultNamespace( Syndication::Atom::atom1Namespace() );
295 writer.writeNamespace( Syndication::commentApiNamespace(), QLatin1String(
"comment"));
296 writer.writeNamespace( akregatorNamespace(), QLatin1String(
"akregator") );
297 writer.writeNamespace( Syndication::itunesNamespace(), QLatin1String(
"itunes") );
299 Elements::instance.title.write( QString::fromLatin1(
"Akregator Export for %1").arg( url ), writer, Html );
302 Q_FOREACH(
const QString& i, storage->
articles() )
303 writeItem( storage, i, writer );
304 writer.writeEndElement();
305 writer.writeEndDocument();
308 static void serialize(
Storage* storage,
const QString& url, QIODevice* device ) {
309 serialize( storage->
archiveFor( url ), url, device );
312 static KService::List queryStoragePlugins() {
313 return KServiceTypeTrader::self()->query( QLatin1String(
"Akregator/Plugin"),
314 QString::fromLatin1(
"[X-KDE-akregator-framework-version] == %1 and [X-KDE-akregator-plugintype] == 'storage' and [X-KDE-akregator-rank] > 0" ).arg( QString::number(
AKREGATOR_PLUGIN_INTERFACE_VERSION ) ) );
317 static Plugin* createFromService(
const KService::Ptr& service )
319 KPluginLoader loader( *service );
320 KPluginFactory* factory = loader.factory();
322 qCritical() << QString::fromLatin1(
" Could not create plugin factory for: %1\n"
323 " Error message: %2" ).arg( service->library(), loader.errorString() );
329 static void printUsage() {
330 std::cout <<
"akregatorstorageexporter [--base64] url" << std::endl;
335 int main(
int argc,
char** argv ) {
336 KGlobal::setActiveComponent( KComponentData(
"akregatorstorageexporter" ) );
337 const QString backend = QString::fromLatin1(
"metakit" );
344 const bool base64 = qstrcmp( argv[1],
"--base64" ) == 0;
346 if ( base64 && argc < 3 ) {
351 const int pos = base64 ? 2 : 1;
352 const QString url = KUrl::fromEncoded( base64 ? QByteArray::fromBase64( argv[pos] ) : QByteArray( argv[pos] ) ).toString();
354 Q_FOREACH(
const KService::Ptr& i, queryStoragePlugins() )
355 if (
Plugin*
const plugin = createFromService( i ) )
356 plugin->initialize();
359 if ( !storageFactory ) {
360 qCritical(
"Could not create storage factory for %s.", qPrintable( backend ) );
366 qCritical(
"Could not create storage object for %s.", qPrintable( backend ) );
371 if ( !out.open( stdout, QIODevice::WriteOnly ) ) {
372 qCritical(
"Could not open stdout for writing: %s", qPrintable( out.errorString() ) );
376 serialize( storage, url, &out );
virtual uint hash(const QString &guid) const =0
virtual QStringList articles(const QString &tagID=QString()) const =0
returns the guids of all articles in this storage.
virtual int status(const QString &guid) const =0
#define AKREGATOR_PLUGIN_INTERFACE_VERSION
virtual QString authorName(const QString &guid) const =0
virtual bool guidIsHash(const QString &guid) const =0
Storage is the main interface to the article archive.
static StorageFactoryRegistry * self()
article was fetched in the last fetch of it's feed and not read yet.
virtual QString content(const QString &guid) const =0
virtual QString title(const QString &guid) const =0
virtual int comments(const QString &guid) const =0
int main(int argc, char **argv)
StorageFactory * getFactory(const QString &typestr)
virtual uint pubDate(const QString &guid) const =0
virtual bool guidIsPermaLink(const QString &guid) const =0
virtual void enclosure(const QString &guid, bool &hasEnclosure, QString &url, QString &type, int &length) const =0
virtual Storage * createStorage(const QStringList ¶ms) const =0
creates a storage object with given parameters
virtual QString authorUri(const QString &guid) const =0
virtual QString authorEMail(const QString &guid) const =0
virtual FeedStorage * archiveFor(const QString &url)=0
virtual QString commentsLink(const QString &guid) const =0
virtual QString link(const QString &guid) const =0
virtual QString description(const QString &guid) const =0