• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

akregator

  • sources
  • kde-4.14
  • kdepim
  • akregator
  • export
akregatorstorageexporter.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of akregatorstorageexporter
3  *
4  * Copyright (C) 2009 Frank Osterfeld <osterfeld@kde.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 #include "feedstorage.h"
23 #include "storage.h"
24 #include "storagefactory.h"
25 #include "storagefactoryregistry.h"
26 #include "plugin.h"
27 
28 #include <syndication/atom/constants.h>
29 #include <syndication/constants.h>
30 
31 #include <QDateTime>
32 #include <QFile>
33 #include <QIODevice>
34 #include <QStringList>
35 #include <QXmlStreamWriter>
36 #include <QVariant>
37 #include <QDebug>
38 
39 #include <KComponentData>
40 #include <KGlobal>
41 #include <KPluginLoader>
42 #include <KService>
43 #include <KServiceTypeTrader>
44 #include <KUrl>
45 
46 #include <iostream>
47 
48 #include <cassert>
49 
50 using namespace Akregator;
51 using namespace Akregator::Backend;
52 
53 namespace {
54  static QString akregatorNamespace() {
55  return QString::fromLatin1("http://akregator.kde.org/StorageExporter#");
56  }
57 
58  enum TextMode {
59  PlainText,
60  Html
61  };
62 
63  enum Status
64  {
65  Deleted=0x01,
66  Trash=0x02,
67  New=0x04,
68  Read=0x08,
69  Keep=0x10
70  };
71 
72  class Element
73  {
74  public:
75  Element( const QString& ns_, const QString& name_ ) : ns( ns_ ), name( name_ ), qualifiedName( ns + QLatin1Char(':') + name )
76  {
77  }
78 
79  const QString ns;
80  const QString name;
81  const QString qualifiedName;
82 
83  void writeStartElement( QXmlStreamWriter& writer ) const
84  {
85  if ( !ns.isNull() )
86  writer.writeStartElement( ns, name );
87  else
88  writer.writeStartElement( name );
89  }
90 
91  void write( const QVariant& value , QXmlStreamWriter& writer, TextMode mode = PlainText ) const
92  {
93  const QVariant qv( value );
94  Q_ASSERT( qv.canConvert( QVariant::String ) );
95  const QString str = qv.toString();
96  if ( str.isEmpty() )
97  return;
98 
99  if ( ns.isEmpty() )
100  writer.writeStartElement( name );
101  else
102  writer.writeStartElement( ns, name );
103  if ( mode == Html )
104  {
105  writer.writeAttribute( QLatin1String("type"), QLatin1String("html") );
106  }
107  writer.writeCharacters( str );
108  writer.writeEndElement();
109  }
110  };
111 
112  struct Elements
113  {
114  Elements() : atomNS( Syndication::Atom::atom1Namespace() ),
115  akregatorNS(akregatorNamespace() ),
116  commentNS( Syndication::commentApiNamespace() ),
117  title( atomNS, QLatin1String("title") ),
118  summary( atomNS, QLatin1String("summary") ),
119  content( atomNS, QLatin1String("content") ),
120  link( atomNS, QLatin1String("link") ),
121  language( atomNS, QLatin1String("language") ),
122  feed( atomNS, QLatin1String("feed") ),
123  guid( atomNS, QLatin1String("id") ),
124  published( atomNS, QLatin1String("published") ),
125  updated( atomNS, QLatin1String("updated") ),
126  commentsCount( Syndication::slashNamespace(), QLatin1String("comments") ),
127  commentsFeed( commentNS, QLatin1String("commentRss") ),
128  commentPostUri( commentNS, QLatin1String("comment") ),
129  commentsLink( akregatorNS, QLatin1String("commentsLink") ),
130  hash( akregatorNS, QLatin1String("hash") ),
131  guidIsHash( akregatorNS, QLatin1String("idIsHash") ),
132  name( atomNS, QLatin1String("name") ),
133  uri( atomNS, QLatin1String("uri") ),
134  email( atomNS, QLatin1String("email") ),
135  author( atomNS, QLatin1String("author") ),
136  category( atomNS, QLatin1String("category") ),
137  entry( atomNS, QLatin1String("entry") ),
138  itemProperties( akregatorNS, QLatin1String("itemProperties") ),
139  readStatus( akregatorNS, QLatin1String("readStatus") ),
140  deleted( akregatorNS, QLatin1String("deleted") ),
141  important( akregatorNS, QLatin1String("important") )
142 
143  {}
144  const QString atomNS;
145  const QString akregatorNS;
146  const QString commentNS;
147  const Element title;
148  const Element summary;
149  const Element content;
150  const Element link;
151  const Element language;
152  const Element feed;
153  const Element guid;
154  const Element published;
155  const Element updated;
156  const Element commentsCount;
157  const Element commentsFeed;
158  const Element commentPostUri;
159  const Element commentsLink;
160  const Element hash;
161  const Element guidIsHash;
162  const Element name;
163  const Element uri;
164  const Element email;
165  const Element author;
166  const Element category;
167  const Element entry;
168  const Element itemProperties;
169  const Element readStatus;
170  const Element deleted;
171  const Element important;
172  static const Elements instance;
173  };
174 
175  const Elements Elements::instance;
176 
177  void writeAttributeIfNotEmpty( const QString& ns, const QString& element, const QVariant& value, QXmlStreamWriter& writer )
178  {
179  const QString text = value.toString();
180  if ( text.isEmpty() )
181  return;
182  writer.writeAttribute( ns, element, text );
183  }
184 
185  void writeAttributeIfNotEmpty( const QString& element, const QVariant& value, QXmlStreamWriter& writer )
186  {
187  const QString text = value.toString();
188  if ( text.isEmpty() )
189  return;
190  writer.writeAttribute( element, text );
191  }
192 
193  void writeEnclosure( const QString& url, const QString& type, int length, QXmlStreamWriter& writer )
194  {
195  Elements::instance.link.writeStartElement( writer );
196  writer.writeAttribute( QLatin1String("rel"), QLatin1String("enclosure") );
197  writeAttributeIfNotEmpty( QLatin1String("href"), url, writer );
198  writeAttributeIfNotEmpty( QLatin1String("type"), type, writer );
199  if ( length > 0 )
200  writer.writeAttribute( QLatin1String("length"), QString::number( length ) );
201  writer.writeEndElement();
202  }
203 
204  void writeLink( const QString& url, QXmlStreamWriter& writer )
205  {
206  if ( url.isEmpty() )
207  return;
208  Elements::instance.link.writeStartElement( writer );
209  writer.writeAttribute( QLatin1String("rel"), QLatin1String("alternate") );
210  writeAttributeIfNotEmpty( QLatin1String("href"), url, writer );
211  writer.writeEndElement();
212  }
213 
214  void writeAuthor( const QString& name, const QString& uri, const QString& email, QXmlStreamWriter& writer )
215  {
216  if ( name.isEmpty() && uri.isEmpty() && email.isEmpty() )
217  return;
218 
219  const QString atomNS = Syndication::Atom::atom1Namespace();
220  Elements::instance.author.writeStartElement( writer );
221  Elements::instance.name.write( name, writer );
222  Elements::instance.uri.write( uri, writer );
223  Elements::instance.email.write( email, writer );
224  writer.writeEndElement(); // </author>
225  }
226 
227  static void writeItem( FeedStorage* storage, const QString& guid, QXmlStreamWriter& writer ) {
228  Elements::instance.entry.writeStartElement( writer );
229  Elements::instance.guid.write( guid, writer );
230 
231  const uint published = storage->pubDate( guid );
232  if ( published > 0 ) {
233  const QString pdStr = QDateTime::fromTime_t( published ).toString( Qt::ISODate );
234  Elements::instance.published.write( pdStr, writer );
235  }
236 
237  const int status = storage->status( guid );
238 
239  Elements::instance.itemProperties.writeStartElement( writer );
240 
241  if ( status & Deleted ) {
242  Elements::instance.deleted.write( QString::fromLatin1("true"), writer );
243  writer.writeEndElement(); // </itemProperties>
244  writer.writeEndElement(); // </item>
245  return;
246  }
247 
248  Elements::instance.hash.write( QString::number( storage->hash( guid ) ), writer );
249  if ( storage->guidIsHash( guid ) )
250  Elements::instance.guidIsHash.write( QString::fromLatin1("true"), writer );
251  if ( status & New )
252  Elements::instance.readStatus.write( QString::fromLatin1("new"), writer );
253  else if ( ( status & Read ) == 0 )
254  Elements::instance.readStatus.write( QString::fromLatin1("unread"), writer );
255  if ( status & Keep )
256  Elements::instance.important.write( QString::fromLatin1("true"), writer );
257  writer.writeEndElement(); // </itemProperties>
258 
259  Elements::instance.title.write( storage->title( guid ), writer, Html );
260  writeLink( storage->guidIsPermaLink( guid ) ? guid : storage->link( guid ), writer );
261 
262  Elements::instance.summary.write( storage->description( guid ), writer, Html );
263  Elements::instance.content.write( storage->content( guid ), writer, Html );
264  writeAuthor( storage->authorName( guid ),
265  storage->authorUri( guid ),
266  storage->authorEMail( guid ),
267  writer );
268 
269  if ( const int commentsCount = storage->comments( guid ) )
270  Elements::instance.commentsCount.write( QString::number( commentsCount ), writer );
271 
272  Elements::instance.commentsLink.write( storage->commentsLink( guid ), writer );
273 
274  bool hasEnc = false;
275  QString encUrl, encType;
276  int encLength = 0;
277  storage->enclosure( guid, hasEnc, encUrl, encType, encLength );
278  if ( hasEnc )
279  writeEnclosure( encUrl, encType, encLength, writer );
280  writer.writeEndElement(); // </item>
281  }
282 
283  static void serialize( FeedStorage* storage, const QString& url, QIODevice* device ) {
284  assert( storage );
285  assert( device );
286  QXmlStreamWriter writer( device );
287  writer.setAutoFormatting( true );
288  writer.setAutoFormattingIndent( 2 );
289  writer.writeStartDocument();
290 
291  Elements::instance.feed.writeStartElement( writer );
292 
293  writer.writeDefaultNamespace( Syndication::Atom::atom1Namespace() );
294  writer.writeNamespace( Syndication::commentApiNamespace(), QLatin1String("comment"));
295  writer.writeNamespace( akregatorNamespace(), QLatin1String("akregator") );
296  writer.writeNamespace( Syndication::itunesNamespace(), QLatin1String("itunes") );
297 
298  Elements::instance.title.write( QString::fromLatin1("Akregator Export for %1").arg( url ), writer, Html );
299 
300 
301  Q_FOREACH( const QString& i, storage->articles() )
302  writeItem( storage, i, writer );
303  writer.writeEndElement(); // </feed>
304  writer.writeEndDocument();
305  }
306 
307  static void serialize( Storage* storage, const QString& url, QIODevice* device ) {
308  serialize( storage->archiveFor( url ), url, device );
309  }
310 
311  static KService::List queryStoragePlugins() {
312  return KServiceTypeTrader::self()->query( QLatin1String("Akregator/Plugin"),
313  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 ) ) );
314  }
315 
316  static Plugin* createFromService( const KService::Ptr& service )
317  {
318  KPluginLoader loader( *service );
319  KPluginFactory* factory = loader.factory();
320  if ( !factory ) {
321  qCritical() << QString::fromLatin1( " Could not create plugin factory for: %1\n"
322  " Error message: %2" ).arg( service->library(), loader.errorString() );
323  return 0;
324  }
325  return factory->create<Akregator::Plugin>();
326  }
327 
328  static void printUsage() {
329  std::cout << "akregatorstorageexporter [--base64] url" << std::endl;
330  }
331 }
332 
333 
334 int main( int argc, char** argv ) {
335  KGlobal::setActiveComponent( KComponentData( "akregatorstorageexporter" ) );
336  const QString backend = QString::fromLatin1( "metakit" );
337 
338  if ( argc < 2 ) {
339  printUsage();
340  return 1;
341  }
342 
343  const bool base64 = qstrcmp( argv[1], "--base64" ) == 0;
344 
345  if ( base64 && argc < 3 ) {
346  printUsage();
347  return 1;
348  }
349 
350  const int pos = base64 ? 2 : 1;
351  const QString url = KUrl::fromEncoded( base64 ? QByteArray::fromBase64( argv[pos] ) : QByteArray( argv[pos] ) ).toString();
352 
353  Q_FOREACH( const KService::Ptr& i, queryStoragePlugins() )
354  if ( Plugin* const plugin = createFromService( i ) )
355  plugin->initialize();
356 
357  const StorageFactory* const storageFactory = StorageFactoryRegistry::self()->getFactory( backend );
358  if ( !storageFactory ) {
359  qCritical( "Could not create storage factory for %s.", qPrintable( backend ) );
360  return 1;
361  }
362 
363  Storage* const storage = storageFactory->createStorage( QStringList() );
364  if ( !storage ) {
365  qCritical( "Could not create storage object for %s.", qPrintable( backend ) );
366  return 1;
367  }
368 
369  QFile out;
370  if ( !out.open( stdout, QIODevice::WriteOnly ) ) {
371  qCritical( "Could not open stdout for writing: %s", qPrintable( out.errorString() ) );
372  return 1;
373  }
374 
375  serialize( storage, url, &out );
376 
377  return 0;
378 }
QIODevice
storagefactoryregistry.h
QDateTime::toString
QString toString(Qt::DateFormat format) const
Akregator::Backend::FeedStorage::hash
virtual uint hash(const QString &guid) const =0
TextMode
TextMode
Definition: akregatorstorageexporter.cpp:58
Akregator::Backend::FeedStorage::articles
virtual QStringList articles(const QString &tagID=QString()) const =0
returns the guids of all articles in this storage.
QXmlStreamWriter::writeNamespace
void writeNamespace(const QString &namespaceUri, const QString &prefix)
Akregator::Backend::FeedStorage::status
virtual int status(const QString &guid) const =0
QXmlStreamWriter
QByteArray
AKREGATOR_PLUGIN_INTERFACE_VERSION
#define AKREGATOR_PLUGIN_INTERFACE_VERSION
Definition: plugin.h:37
Akregator::Backend::FeedStorage::authorName
virtual QString authorName(const QString &guid) const =0
QIODevice::errorString
QString errorString() const
Akregator::Backend::FeedStorage::guidIsHash
virtual bool guidIsHash(const QString &guid) const =0
uint
unsigned int uint
Definition: article.h:41
plugin.h
Status
Status
Definition: akregatorstorageexporter.cpp:63
Akregator::Backend::Storage
Storage is the main interface to the article archive.
Definition: storage.h:43
QXmlStreamWriter::setAutoFormattingIndent
void setAutoFormattingIndent(int spacesOrTabs)
Akregator::Backend::StorageFactoryRegistry::self
static StorageFactoryRegistry * self()
Definition: storagefactoryregistry.cpp:43
Akregator::Plugin
Definition: plugin.h:41
Akregator::New
article was fetched in the last fetch of it's feed and not read yet.
Definition: types.h:33
QFile
Akregator::Backend::FeedStorage::content
virtual QString content(const QString &guid) const =0
QDateTime::fromTime_t
QDateTime fromTime_t(uint seconds)
QString::number
QString number(int n, int base)
Akregator::Backend::FeedStorage::title
virtual QString title(const QString &guid) const =0
Akregator::Backend::FeedStorage::comments
virtual int comments(const QString &guid) const =0
Akregator::Backend::StorageFactory
Definition: storagefactory.h:37
QString::isEmpty
bool isEmpty() const
Akregator::Read
article is read
Definition: types.h:32
Akregator::Backend::FeedStorage
Definition: feedstorage.h:66
QString
storagefactory.h
storage.h
main
int main(int argc, char **argv)
Definition: akregatorstorageexporter.cpp:334
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
Akregator::Backend::StorageFactoryRegistry::getFactory
StorageFactory * getFactory(const QString &typestr)
Definition: storagefactoryregistry.cpp:64
QStringList
Akregator::Backend::FeedStorage::pubDate
virtual uint pubDate(const QString &guid) const =0
Akregator::Backend::FeedStorage::guidIsPermaLink
virtual bool guidIsPermaLink(const QString &guid) const =0
Akregator::Backend::FeedStorage::enclosure
virtual void enclosure(const QString &guid, bool &hasEnclosure, QString &url, QString &type, int &length) const =0
Akregator::Backend::StorageFactory::createStorage
virtual Storage * createStorage(const QStringList &params) const =0
creates a storage object with given parameters
QLatin1Char
QXmlStreamWriter::writeAttribute
void writeAttribute(const QString &qualifiedName, const QString &value)
Akregator::Backend::FeedStorage::authorUri
virtual QString authorUri(const QString &guid) const =0
QLatin1String
QByteArray::fromBase64
QByteArray fromBase64(const QByteArray &base64)
QXmlStreamWriter::setAutoFormatting
void setAutoFormatting(bool enable)
Akregator::Backend::FeedStorage::authorEMail
virtual QString authorEMail(const QString &guid) const =0
Akregator::Backend::Storage::archiveFor
virtual FeedStorage * archiveFor(const QString &url)=0
QXmlStreamWriter::writeEndDocument
void writeEndDocument()
Akregator::Backend::FeedStorage::commentsLink
virtual QString commentsLink(const QString &guid) const =0
QString::fromLatin1
QString fromLatin1(const char *str, int size)
Akregator::Backend::FeedStorage::link
virtual QString link(const QString &guid) const =0
QXmlStreamWriter::writeStartDocument
void writeStartDocument()
feedstorage.h
QXmlStreamWriter::writeCharacters
void writeCharacters(const QString &text)
QXmlStreamWriter::writeDefaultNamespace
void writeDefaultNamespace(const QString &namespaceUri)
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QVariant::toString
QString toString() const
Akregator::Backend::FeedStorage::description
virtual QString description(const QString &guid) const =0
QXmlStreamWriter::writeEndElement
void writeEndElement()
QXmlStreamWriter::writeStartElement
void writeStartElement(const QString &qualifiedName)
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:34:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal