diff options
Diffstat (limited to 'lib/compatibility/knewstuff')
24 files changed, 4205 insertions, 0 deletions
diff --git a/lib/compatibility/knewstuff/Makefile.am b/lib/compatibility/knewstuff/Makefile.am new file mode 100644 index 00000000..d0718429 --- /dev/null +++ b/lib/compatibility/knewstuff/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS = -I$(srcdir)/.. $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libknewstuff.la + +libknewstuff_la_LDFLAGS = $(all_libraries) +libknewstuff_la_LIBADD = $(LIB_KIO) +libknewstuff_la_SOURCES = engine.cpp entry.cpp downloaddialog.cpp \ + uploaddialog.cpp providerdialog.cpp provider.cpp knewstuff.cpp \ + knewstuffgeneric.cpp knewstuffsecure.cpp security.cpp + +KDE_ICON=AUTO diff --git a/lib/compatibility/knewstuff/cr16-action-knewstuff.png b/lib/compatibility/knewstuff/cr16-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..ef5ea45e --- /dev/null +++ b/lib/compatibility/knewstuff/cr16-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/cr32-action-knewstuff.png b/lib/compatibility/knewstuff/cr32-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..757e9266 --- /dev/null +++ b/lib/compatibility/knewstuff/cr32-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/cr64-action-knewstuff.png b/lib/compatibility/knewstuff/cr64-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..ad6d5e56 --- /dev/null +++ b/lib/compatibility/knewstuff/cr64-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/downloaddialog.cpp b/lib/compatibility/knewstuff/downloaddialog.cpp new file mode 100644 index 00000000..be3cf66d --- /dev/null +++ b/lib/compatibility/knewstuff/downloaddialog.cpp @@ -0,0 +1,628 @@ +/* + This file is part of KNewStuff. + Copyright (c) 2003 Josef Spillner <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "downloaddialog.h" +#include "downloaddialog.moc" + +#include <klocale.h> +#include <ktabctl.h> +#include <klistview.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kiconloader.h> + +#include <knewstuff/entry.h> +#include <knewstuff/knewstuffgeneric.h> +#include <knewstuff/engine.h> + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qdom.h> +#include <qlabel.h> +#include <qtextbrowser.h> +#include <qtimer.h> // hack + +using namespace KNS; + +class NumSortListViewItem : public KListViewItem +{ + public: + NumSortListViewItem( QListView * parent, QString label1, QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null, QString label5 = QString::null, QString label6 = QString::null, QString label7 = QString::null, QString label8 = QString::null ) : + KListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8 ) + { + } + + QString key(int col, bool asc) const { + if (col == 2) + { + + QString s; + s.sprintf("%08d", text(col).toInt()); + return s; + } + return KListViewItem::key( col, asc ); + } +}; + +// BEGIN deprecated for KDE 4 +DownloadDialog::DownloadDialog(Engine *engine, QWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(QWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::open(QString type) +{ + DownloadDialog d; + d.setType(type); + d.load(); + d.exec(); +} +// END deprecated for KDE 4 + +DownloadDialog::DownloadDialog(Engine *engine, QWidget *, const QString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(QWidget *, const QString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::init(Engine *engine) +{ + resize(700, 400); + + m_engine = engine; + m_page = NULL; + + connect(this, SIGNAL(aboutToShowPage(QWidget*)), SLOT(slotPage(QWidget*))); + + if(!engine) + { + m_loader = new ProviderLoader(this); + connect(m_loader, SIGNAL(providersLoaded(Provider::List*)), SLOT(slotProviders(Provider::List*))); + } +} + +DownloadDialog::~DownloadDialog() +{ +} + +void DownloadDialog::load() +{ + m_loader->load(m_filter, m_providerlist); +} + +void DownloadDialog::load(QString providerList) +{ + m_loader->load(m_filter, providerList); +} + +void DownloadDialog::clear() +{ + QMap<QWidget*, QValueList<KListView*>* >::Iterator it; + for(it = m_map.begin(); it != m_map.end(); ++it) + { + QValueList<KListView*> *v = it.data(); + kdDebug() << "clear listviews in " << v << endl; + if(v) + { + (*(v->at(0)))->clear(); + (*(v->at(1)))->clear(); + (*(v->at(2)))->clear(); + + //delete (*it); + } + + delete it.key(); + } + m_map.clear(); +} + +void DownloadDialog::slotProviders(Provider::List *list) +{ + Provider *p; + /*QFrame *frame;*/ + + for(p = list->first(); p; p = list->next()) + { + kdDebug() << "++ provider ++ " << p->name() << endl; + + if(!m_filter.isEmpty()) + loadProvider(p); + else + addProvider(p); + /*if(p == list->getFirst()) + slotPage(m_frame);*/ // only if !qtbug + } +} + +void DownloadDialog::addProvider(Provider *p) +{ + QFrame *frame; + KTabCtl *ctl; + QWidget *w_d, *w_r, *w_l; + QWidget *w2; + KListView *lvtmp_r, *lvtmp_d, *lvtmp_l; + QTextBrowser *rt; + QString tmp; + int ret; + QPixmap pix; + + if(m_map.count() == 0) + { + frame = addPage(i18n("Welcome"), i18n("Welcome"), QPixmap("")); + delete frame; + } + + kdDebug() << "addProvider()/begin" << endl; + + ret = true; + if(!p->icon().isValid()) ret = false; + else ret = KIO::NetAccess::download(p->icon(), tmp, this); + if(ret) pix = QPixmap(tmp); + else pix = KGlobal::iconLoader()->loadIcon("knewstuff", KIcon::Panel); + frame = addPage(p->name(), p->name(), pix); + m_frame = frame; + + w2 = new QWidget(frame); + w_d = new QWidget(frame); + w_r = new QWidget(frame); + w_l = new QWidget(frame); + + ctl = new KTabCtl(frame); + ctl->addTab(w_r, i18n("Highest Rated")); + ctl->addTab(w_d, i18n("Most Downloads")); + ctl->addTab(w_l, i18n("Latest")); + + m_curtab = 0; + connect(ctl, SIGNAL(tabSelected(int)), SLOT(slotTab(int))); + + QHBoxLayout *box = new QHBoxLayout(frame); + box->add(ctl); + + lvtmp_r = new KListView(w_r); + lvtmp_r->addColumn(i18n("Name")); + lvtmp_r->addColumn(i18n("Version")); + lvtmp_r->addColumn(i18n("Rating")); + lvtmp_r->setSorting(2, false); + + lvtmp_d = new KListView(w_d); + lvtmp_d->addColumn(i18n("Name")); + lvtmp_d->addColumn(i18n("Version")); + lvtmp_d->addColumn(i18n("Downloads")); + lvtmp_d->setSorting(2, false); + + lvtmp_l = new KListView(w_l); + lvtmp_l->addColumn(i18n("Name")); + lvtmp_l->addColumn(i18n("Version")); + lvtmp_l->addColumn(i18n("Release Date")); + lvtmp_l->setSorting(2, false); + + connect(lvtmp_r, SIGNAL(selectionChanged()), SLOT(slotSelected())); + connect(lvtmp_d, SIGNAL(selectionChanged()), SLOT(slotSelected())); + connect(lvtmp_l, SIGNAL(selectionChanged()), SLOT(slotSelected())); + + rt = new QTextBrowser(frame); + rt->setMinimumWidth(150); + + QPushButton *in = new QPushButton(i18n("Install"), frame); + QPushButton *de = new QPushButton(i18n("Details"), frame); + in->setEnabled(false); + de->setEnabled(false); + + box->addSpacing(spacingHint()); + QVBoxLayout *vbox = new QVBoxLayout(box); + vbox->add(rt); + vbox->addSpacing(spacingHint()); + vbox->add(de); + vbox->add(in); + + connect(in, SIGNAL(clicked()), SLOT(slotInstall())); + connect(de, SIGNAL(clicked()), SLOT(slotDetails())); + + QVBoxLayout *box2 = new QVBoxLayout(w_r); + box2->add(lvtmp_r); + QVBoxLayout *box3 = new QVBoxLayout(w_d); + box3->add(lvtmp_d); + QVBoxLayout *box4 = new QVBoxLayout(w_l); + box4->add(lvtmp_l); + + QValueList<KListView*> *v = new QValueList<KListView*>; + *v << lvtmp_r << lvtmp_d << lvtmp_l; + m_map[frame] = v; + m_rts[frame] = rt; + QValueList<QPushButton*> *vb = new QValueList<QPushButton*>; + *vb << in << de; + m_buttons[frame] = vb; + m_providers[frame] = p; + + kdDebug() << "addProvider()/end; lvtmp_r = " << lvtmp_r << endl; + + if(m_engine) slotPage(frame); + + QTimer::singleShot(100, this, SLOT(slotFinish())); +} + +void DownloadDialog::slotResult(KIO::Job *job) +{ + QDomDocument dom; + QDomElement knewstuff; + + kdDebug() << "got data: " << m_data[job] << endl; + + kapp->config()->setGroup("KNewStuffStatus"); + + dom.setContent(m_data[job]); + knewstuff = dom.documentElement(); + + for(QDomNode pn = knewstuff.firstChild(); !pn.isNull(); pn = pn.nextSibling()) + { + QDomElement stuff = pn.toElement(); + + kdDebug() << "element: " << stuff.tagName() << endl; + + if(stuff.tagName() == "stuff") + { + Entry *entry = new Entry(stuff); + kdDebug() << "TYPE::" << entry->type() << " FILTER::" << m_filter << endl; + if(!entry->type().isEmpty()) + { + if((!m_filter.isEmpty()) && (entry->type() != m_filter)) continue; + } + + if((!m_filter.isEmpty()) && (m_jobs[job])) + { + Provider *p = m_jobs[job]; + addProvider(p); + slotPage(m_frame); + m_jobs[job] = 0; + } + addEntry(entry); + } + } + + m_data[job] = ""; +} + +int DownloadDialog::installStatus(Entry *entry) +{ + QDate date; + QString datestring; + int installed; + + kapp->config()->setGroup("KNewStuffStatus"); + datestring = kapp->config()->readEntry(entry->name()); + if(datestring.isNull()) installed = 0; + else + { + date = QDate::fromString(datestring, Qt::ISODate); + if(!date.isValid()) installed = 0; + else if(date < entry->releaseDate()) installed = -1; + else installed = 1; + } + + return installed; +} + +void DownloadDialog::addEntry(Entry *entry) +{ + QPixmap pix; + int installed; + + /*if(m_engine) + { + if(m_map.count() == 0) + { + m_frame = addPage(i18n("Welcome"), i18n("Welcome"), QPixmap("")); + Provider *p = new Provider(); + p->setName(i18n("Generic")); + addProvider(p); + slotPage(m_frame); + } + }*/ + installed = installStatus(entry); + + if(installed > 0) pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small); + else if(installed < 0) pix = KGlobal::iconLoader()->loadIcon("history", KIcon::Small); + else pix = QPixmap(); + + KListViewItem *tmp_r = new KListViewItem(lv_r, + entry->name(), entry->version(), QString("%1").arg(entry->rating())); + KListViewItem *tmp_d = new NumSortListViewItem(lv_d, + entry->name(), entry->version(), QString("%1").arg(entry->downloads())); + KListViewItem *tmp_l = new KListViewItem(lv_l, + entry->name(), entry->version(), KGlobal::locale()->formatDate(entry->releaseDate())); + + tmp_r->setPixmap(0, pix); + tmp_d->setPixmap(0, pix); + tmp_l->setPixmap(0, pix); + + m_entries.append(entry); + + kdDebug() << "added entry " << entry->name() << endl; +} + +void DownloadDialog::slotData(KIO::Job *job, const QByteArray &a) +{ + QCString tmp(a, a.size() + 1); + m_data[job].append(QString::fromUtf8(tmp)); +} + +void DownloadDialog::slotDetails() +{ + Entry *e = getEntry(); + if(!e) return; + + QString lang = KGlobal::locale()->language(); + + QString info = i18n + ( + "Name: %1\n" + "Author: %2\n" + "License: %3\n" + "Version: %4\n" + "Release: %5\n" + "Rating: %6\n" + "Downloads: %7\n" + "Release date: %8\n" + "Summary: %9\n" + ).arg(e->name() + ).arg(e->author() + ).arg(e->license() + ).arg(e->version() + ).arg(e->release() + ).arg(e->rating() + ).arg(e->downloads() + ).arg(KGlobal::locale()->formatDate(e->releaseDate()) + ).arg(e->summary(lang) + ); + + info.append(i18n + ( + "Preview: %1\n" + "Payload: %2\n" + ).arg(e->preview().url() + ).arg(e->payload().url() + )); + + KMessageBox::information(this, info, i18n("Details")); +} + +void DownloadDialog::slotInstall() +{ + Entry *e = getEntry(); + if(!e) return; + + kdDebug() << "download entry now" << endl; + + if(m_engine) + { + m_engine->download(e); + install(e); + } + else + { + m_s = new KNewStuffGeneric(e->type(), this); + + m_entry = e; + + KURL source = e->payload(); + KURL dest = KURL(m_s->downloadDestination(e)); + + KIO::FileCopyJob *job = KIO::file_copy(source, dest, -1, true); + connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotInstalled(KIO::Job*))); + } +} + +void DownloadDialog::install(Entry *e) +{ + kapp->config()->setGroup("KNewStuffStatus"); + kapp->config()->writeEntry(m_entryname, e->releaseDate().toString(Qt::ISODate)); + kapp->config()->sync(); + + QPixmap pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small); + m_entryitem = lv_r->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + m_entryitem = lv_d->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + m_entryitem = lv_l->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + + + QPushButton *in; + in = *(m_buttons[m_page]->at(0)); + if(in) in->setEnabled(false); +} + +void DownloadDialog::slotInstalled(KIO::Job *job) +{ + bool ret = (job->error() == 0); + KIO::FileCopyJob *cjob; + + if(ret) + { + cjob = static_cast<KIO::FileCopyJob*>(job); + if(cjob) + { + ret = m_s->install(cjob->destURL().path()); + } + else ret = false; + } + + if(ret) + { + install(m_entry); + + KMessageBox::information(this, i18n("Installation successful."), i18n("Installation")); + } + else KMessageBox::error(this, i18n("Installation failed."), i18n("Installation")); + + delete m_s; +} + +void DownloadDialog::slotTab(int tab) +{ + kdDebug() << "switch tab to: " << tab << endl; + m_curtab = tab; +} + +void DownloadDialog::slotSelected() +{ + QString tmp; + bool enabled; + Entry *e = getEntry(); + QString lang = KGlobal::locale()->language(); + + if(e) + { + if(!e->preview(lang).isValid()) + { + m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><i>%4</i><br>(%5)").arg( + e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(e->summary(lang)).arg(e->license())); + } + else + { + KIO::NetAccess::download(e->preview(lang), tmp, this); + m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><img src='%4'><br><i>%5</i><br>(%6)").arg( + e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(tmp).arg(e->summary(lang)).arg(e->license())); + } + + if(installStatus(e) == 1) enabled = false; + else enabled = true; + + QPushButton *de, *in; + in = *(m_buttons[m_page]->at(0)); + de = *(m_buttons[m_page]->at(1)); + if(in) in->setEnabled(enabled); + if(de) de->setEnabled(true); + } +} + +Entry *DownloadDialog::getEntry() +{ + if(m_curtab == 0) m_entryitem = lv_r->currentItem(); + else if(m_curtab == 1) m_entryitem = lv_d->currentItem(); + else if(m_curtab == 2) m_entryitem = lv_l->currentItem(); + else return 0; + + m_entryname = m_entryitem->text(0); + + for(Entry *e = m_entries.first(); e; e = m_entries.next()) + { + if(e->name() == m_entryname) return e; + } + + return 0; +} + +void DownloadDialog::slotPage(QWidget *w) +{ + Provider *p; + + kdDebug() << "changed widget!!!" << endl; + + if(m_map.find(w) == m_map.end()) return; + + m_page = w; + + lv_r = *(m_map[w]->at(0)); + lv_d = *(m_map[w]->at(1)); + lv_l = *(m_map[w]->at(2)); + p = m_providers[w]; + m_rt = m_rts[w]; + + kdDebug() << "valid change!!!; lv_r = " << lv_r << endl; + + if(m_engine) return; + + if(!m_filter.isEmpty()) return; + + lv_r->clear(); + lv_d->clear(); + lv_l->clear(); + + kdDebug() << "-- fetch -- " << p->downloadUrl() << endl; + + loadProvider(p); +} + +void DownloadDialog::loadProvider(Provider *p) +{ + KIO::TransferJob *job = KIO::get(p->downloadUrl()); + + m_jobs[job] = p; + + connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotResult(KIO::Job*))); + connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)), + SLOT(slotData(KIO::Job*, const QByteArray&))); +} + +void DownloadDialog::setType(QString type) +{ + m_filter = type; +} + +void DownloadDialog::setProviderList(const QString& providerList) +{ + m_providerlist = providerList; +} + +void DownloadDialog::slotOk() +{ +} + +void DownloadDialog::slotApply() +{ +} + +void DownloadDialog::open(const QString& type, const QString& caption) +{ + DownloadDialog d(0, caption); + d.setType(type); + d.load(); + d.exec(); +} + +void DownloadDialog::slotFinish() +{ + showPage(1); + //updateBackground(); +} + diff --git a/lib/compatibility/knewstuff/downloaddialog.h b/lib/compatibility/knewstuff/downloaddialog.h new file mode 100644 index 00000000..34b2b22b --- /dev/null +++ b/lib/compatibility/knewstuff/downloaddialog.h @@ -0,0 +1,237 @@ +/* + This file is part of KNewStuff. + Copyright (c) 2003 Josef Spillner <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_DOWNLOADDIALOG_H +#define KNEWSTUFF_DOWNLOADDIALOG_H + +#include <kdialogbase.h> +#include <knewstuff/provider.h> + +namespace KIO +{ + class Job; +} + +class KListView; +class QTextBrowser; +class QFrame; +class KNewStuffGeneric; + +namespace KNS +{ + +class ProviderLoader; +class Entry; +class Provider; +class Engine; + +/** + * @short Common download dialog for data browsing and installation. + * + * It provides an easy-to-use convenience method named open() which does all + * the work, unless a more complex operation is needed. + * \code + * KNewStuff::DownloadDialog::open("kdesktop/wallpapers"); + * \endcode + * + * @author Josef Spillner ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class KDE_EXPORT DownloadDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(Engine *engine, QWidget *parent, const QString& caption); + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(QWidget *parent, const QString& caption); + + /** + Destructor. + */ + ~DownloadDialog(); + + /** + Restricts the display of available data to a certain data type. + + @param type a Hotstuff data type such as "korganizer/calendar" + */ + void setType(QString type); + // ### KDE 4.0: use const QString& + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + */ + void load(); + + /** + Explicitly uses this provider list instead of the one read from + the application configuration. + + @param providerList the URL of the provider list + + @since 3.4 + */ + void setProviderList(const QString& providerList); + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + + @param providerList the URl to the list of providers; if empty + we first try the ProvidersUrl from KGlobal::config, then we + fall back to a hardcoded value. + */ + void load(QString providerList); // KDE4: merge with load() above + + /** + Adds another provider to the download dialog. + This is normally done internally. + + @param p the Hotstuff provider to be added + */ + void addProvider(Provider *p); + + /** + Adds an additional entry to the current provider. + This is normally done internally. + + @param entry a Hotstuff data entry to be added + */ + void addEntry(Entry *entry); + + /** + Clears the entry list of the current provider. + This is normally done internally. + */ + void clear(); + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + @param caption the dialog caption + */ + static void open(const QString& type, const QString& caption); + + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + */ + DownloadDialog(Engine *engine, QWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + */ + DownloadDialog(QWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + */ + static void open(QString type); + // ### KDE 4.0: remove and make caption/parent argument optional + + public slots: + /** + Availability of the provider list. + + @param list list of Hotstuff providers + */ + void slotProviders(Provider::List *list); + + protected slots: + void slotApply(); + void slotOk(); + + private slots: + void slotResult(KIO::Job *job); + void slotData(KIO::Job *job, const QByteArray &a); + void slotInstall(); + void slotDetails(); + void slotInstalled(KIO::Job *job); + void slotTab(int tab); + void slotSelected(); + void slotPage(QWidget *w); + void slotFinish(); + + private: + void init(Engine *e); + Entry *getEntry(); + void loadProvider(Provider *p); + void install(Entry *e); + int installStatus(Entry *e); + + ProviderLoader *m_loader; + QString m_entryname; + KListView *lv_r, *lv_d, *lv_l; + QTextBrowser *m_rt; + QFrame *m_frame; + QListViewItem *m_entryitem; + QPtrList<Entry> m_entries; + Entry *m_entry; + KNewStuffGeneric *m_s; + int m_curtab; + QMap<QWidget*, QValueList<KListView*>* > m_map; + QMap<QWidget*, Provider*> m_providers; + QMap<QWidget*, QTextBrowser*> m_rts; + QMap<QWidget*, QValueList<QPushButton*>* > m_buttons; + QMap<KIO::Job*, Provider*> m_jobs; + QMap<KIO::Job*, QString> m_data; + QString m_filter; + QString m_providerlist; + Engine *m_engine; + QWidget *m_page; +}; + +} + +#endif + diff --git a/lib/compatibility/knewstuff/engine.cpp b/lib/compatibility/knewstuff/engine.cpp new file mode 100644 index 00000000..c141aeeb --- /dev/null +++ b/lib/compatibility/knewstuff/engine.cpp @@ -0,0 +1,420 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qcstring.h> +#include <qdom.h> +#include <qfileinfo.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kio/job.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + +#include "knewstuff.h" +#include "downloaddialog.h" +#include "uploaddialog.h" +#include "providerdialog.h" + +#include "engine.h" +#include "engine.moc" + +using namespace KNS; + +Engine::Engine( KNewStuff *newStuff, const QString &type, + QWidget *parentWidget ) : + mParentWidget( parentWidget ), mDownloadDialog( 0 ), + mUploadDialog( 0 ), mProviderDialog( 0 ), mUploadProvider( 0 ), + mNewStuff( newStuff ), mType( type ) +{ + mProviderLoader = new ProviderLoader( mParentWidget ); + + mNewStuffList.setAutoDelete( true ); +} + +Engine::Engine( KNewStuff *newStuff, const QString &type, + const QString &providerList, QWidget *parentWidget ) : + mParentWidget( parentWidget ), + mDownloadDialog( 0 ), mUploadDialog( 0 ), + mProviderDialog( 0 ), mUploadProvider( 0 ), + mProviderList( providerList ), mNewStuff( newStuff ), + mType( type ) +{ + mProviderLoader = new ProviderLoader( mParentWidget ); + mNewStuffList.setAutoDelete( true ); +} + +Engine::~Engine() +{ + delete mProviderLoader; + + delete mUploadDialog; + delete mDownloadDialog; +} + +void Engine::download() +{ + kdDebug(5850) << "Engine::download()" << endl; + + connect( mProviderLoader, + SIGNAL( providersLoaded( Provider::List * ) ), + SLOT( getMetaInformation( Provider::List * ) ) ); + mProviderLoader->load( mType, mProviderList ); +} + +void Engine::getMetaInformation( Provider::List *providers ) +{ + mProviderLoader->disconnect(); + + mNewStuffJobData.clear(); + + if ( !mDownloadDialog ) { + mDownloadDialog = new DownloadDialog( this, mParentWidget ); + mDownloadDialog->show(); + } + mDownloadDialog->clear(); + + Provider *p; + for ( p = providers->first(); p; p = providers->next() ) { + if ( p->downloadUrl().isEmpty() ) continue; + + KIO::TransferJob *job = KIO::get( p->downloadUrl() ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotNewStuffJobResult( KIO::Job * ) ) ); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), + SLOT( slotNewStuffJobData( KIO::Job *, const QByteArray & ) ) ); + + mNewStuffJobData.insert( job, "" ); + mProviderJobs[ job ] = p; + } +} + +void Engine::slotNewStuffJobData( KIO::Job *job, const QByteArray &data ) +{ + if ( data.isEmpty() ) return; + + kdDebug(5850) << "Engine:slotNewStuffJobData()" << endl; + + QCString str( data, data.size() + 1 ); + + mNewStuffJobData[ job ].append( QString::fromUtf8( str ) ); +} + +void Engine::slotNewStuffJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error downloading new stuff descriptions." << endl; + job->showErrorDialog( mParentWidget ); + } else { + QString knewstuffDoc = mNewStuffJobData[ job ]; + + kdDebug(5850) << "---START---" << endl << knewstuffDoc << "---END---" << endl; + + mDownloadDialog->addProvider( mProviderJobs[ job ] ); + + QDomDocument doc; + if ( !doc.setContent( knewstuffDoc ) ) { + kdDebug(5850) << "Error parsing knewstuff.xml." << endl; + return; + } else { + QDomElement knewstuff = doc.documentElement(); + + if ( knewstuff.isNull() ) { + kdDebug(5850) << "No document in knewstuffproviders.xml." << endl; + } else { + QDomNode p; + for ( p = knewstuff.firstChild(); !p.isNull(); p = p.nextSibling() ) { + QDomElement stuff = p.toElement(); + if ( stuff.tagName() != "stuff" ) continue; + if ( stuff.attribute("type", mType) != mType ) continue; + + Entry *entry = new Entry( stuff ); + mNewStuffList.append( entry ); + + mDownloadDialog->show(); + + mDownloadDialog->addEntry( entry ); + + kdDebug(5850) << "KNEWSTUFF: " << entry->name() << endl; + + kdDebug(5850) << " SUMMARY: " << entry->summary() << endl; + kdDebug(5850) << " VERSION: " << entry->version() << endl; + kdDebug(5850) << " RELEASEDATE: " << entry->releaseDate().toString() << endl; + kdDebug(5850) << " RATING: " << entry->rating() << endl; + + kdDebug(5850) << " LANGS: " << entry->langs().join(", ") << endl; + } + } + } + } + + mNewStuffJobData.remove( job ); + mProviderJobs.remove( job ); + + if ( mNewStuffJobData.count() == 0 ) { + mDownloadDialog->show(); + mDownloadDialog->raise(); + } +} + +void Engine::download( Entry *entry ) +{ + kdDebug(5850) << "Engine::download(entry)" << endl; + + KURL source = entry->payload(); + mDownloadDestination = mNewStuff->downloadDestination( entry ); + + if ( mDownloadDestination.isEmpty() ) { + kdDebug(5850) << "Empty downloadDestination. Cancelling download." << endl; + return; + } + + KURL destination = KURL( mDownloadDestination ); + + kdDebug(5850) << " SOURCE: " << source.url() << endl; + kdDebug(5850) << " DESTINATION: " << destination.url() << endl; + + KIO::FileCopyJob *job = KIO::file_copy( source, destination, -1, true ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotDownloadJobResult( KIO::Job * ) ) ); +} + +void Engine::slotDownloadJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error downloading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + return; + } + + if ( mNewStuff->install( mDownloadDestination ) ) { + if ( !mIgnoreInstallResult ) { + KMessageBox::information( mParentWidget, + i18n("Successfully installed hot new stuff.") ); + } + } else + if ( !mIgnoreInstallResult ){ + KMessageBox::error( mParentWidget, + i18n("Failed to install hot new stuff.") ); + } +} + +void Engine::upload(const QString &fileName, const QString &previewName ) +{ + mUploadFile = fileName; + mPreviewFile = previewName; + + connect( mProviderLoader, + SIGNAL( providersLoaded( Provider::List * ) ), + SLOT( selectUploadProvider( Provider::List * ) ) ); + mProviderLoader->load( mType ); +} + +void Engine::selectUploadProvider( Provider::List *providers ) +{ + kdDebug(5850) << "Engine:selectUploadProvider()" << endl; + + mProviderLoader->disconnect(); + + if ( !mProviderDialog ) { + mProviderDialog = new ProviderDialog( this, mParentWidget ); + } + + mProviderDialog->clear(); + + mProviderDialog->show(); + mProviderDialog->raise(); + + for( Provider *p = providers->first(); p; p = providers->next() ) { + mProviderDialog->addProvider( p ); + } +} + +void Engine::requestMetaInformation( Provider *provider ) +{ + mUploadProvider = provider; + + if ( !mUploadDialog ) { + mUploadDialog = new UploadDialog( this, mParentWidget ); + } + mUploadDialog->setPreviewFile( mPreviewFile ); + mUploadDialog->show(); + mUploadDialog->raise(); +} + +void Engine::upload( Entry *entry ) +{ + if ( mUploadFile.isNull()) { + mUploadFile = entry->fullName(); + mUploadFile = locateLocal( "data", QString(kapp->instanceName()) + "/upload/" + mUploadFile ); + + if ( !mNewStuff->createUploadFile( mUploadFile ) ) { + KMessageBox::error( mParentWidget, i18n("Unable to create file to upload.") ); + emit uploadFinished( false ); + return; + } + } + + QString lang = entry->langs().first(); + QFileInfo fi( mUploadFile ); + entry->setPayload( KURL::fromPathOrURL( fi.fileName() ), lang ); + + if ( !createMetaFile( entry ) ) { + emit uploadFinished( false ); + return; + } + + QString text = i18n("The files to be uploaded have been created at:\n"); + text.append( i18n("Data file: %1\n").arg( mUploadFile) ); + if (!mPreviewFile.isEmpty()) { + text.append( i18n("Preview image: %1\n").arg( mPreviewFile) ); + } + text.append( i18n("Content information: %1\n").arg( mUploadMetaFile) ); + text.append( i18n("Those files can now be uploaded.\n") ); + text.append( i18n("Beware that any people might have access to them at any time.") ); + + QString caption = i18n("Upload Files"); + + if ( mUploadProvider->noUpload() ) { + KURL noUploadUrl = mUploadProvider->noUploadUrl(); + if ( noUploadUrl.isEmpty() ) { + text.append( i18n("Please upload the files manually.") ); + KMessageBox::information( mParentWidget, text, caption ); + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("Upload Info"), + KStdGuiItem::close() ); + if ( result == KMessageBox::Yes ) { + kapp->invokeBrowser( noUploadUrl.url() ); + } + } + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("&Upload"), KStdGuiItem::cancel() ); + if ( result == KMessageBox::Yes ) { + KURL destination = mUploadProvider->uploadUrl(); + destination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *job = KIO::file_copy( KURL::fromPathOrURL( mUploadFile ), destination ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadPayloadJobResult( KIO::Job * ) ) ); + } else { + emit uploadFinished( false ); + } + } +} + +bool Engine::createMetaFile( Entry *entry ) +{ + QDomDocument doc("knewstuff"); + doc.appendChild( doc.createProcessingInstruction( + "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); + QDomElement de = doc.createElement("knewstuff"); + doc.appendChild( de ); + + entry->setType(type()); + de.appendChild( entry->createDomElement( doc, de ) ); + + kdDebug(5850) << "--DOM START--" << endl << doc.toString() + << "--DOM_END--" << endl; + + if ( mUploadMetaFile.isNull() ) { + mUploadMetaFile = entry->fullName() + ".meta"; + mUploadMetaFile = locateLocal( "data", QString(kapp->instanceName()) + "/upload/" + mUploadMetaFile ); + } + + QFile f( mUploadMetaFile ); + if ( !f.open( IO_WriteOnly ) ) { + mUploadMetaFile = QString::null; + return false; + } + + QTextStream ts( &f ); + ts.setEncoding( QTextStream::UnicodeUTF8 ); + ts << doc.toString(); + + f.close(); + + return true; +} + +void Engine::slotUploadPayloadJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + if (mPreviewFile.isEmpty()) { + slotUploadPreviewJobResult(job); + return; + } + + QFileInfo fi( mPreviewFile ); + + KURL previewDestination = mUploadProvider->uploadUrl(); + previewDestination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *newJob = KIO::file_copy( KURL::fromPathOrURL( mPreviewFile ), previewDestination ); + connect( newJob, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadPreviewJobResult( KIO::Job * ) ) ); +} + +void Engine::slotUploadPreviewJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff preview." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( true ); + return; + } + + QFileInfo fi( mUploadMetaFile ); + + KURL metaDestination = mUploadProvider->uploadUrl(); + metaDestination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *newJob = KIO::file_copy( KURL::fromPathOrURL( mUploadMetaFile ), metaDestination ); + connect( newJob, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadMetaJobResult( KIO::Job * ) ) ); +} + +void Engine::slotUploadMetaJobResult( KIO::Job *job ) +{ + mUploadMetaFile = QString::null; + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff metadata." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + KMessageBox::information( mParentWidget, + i18n("Successfully uploaded new stuff.") ); + emit uploadFinished( true ); +} + +void Engine::ignoreInstallResult(bool ignore) +{ + mIgnoreInstallResult = ignore; +} diff --git a/lib/compatibility/knewstuff/engine.h b/lib/compatibility/knewstuff/engine.h new file mode 100644 index 00000000..dd3f2b30 --- /dev/null +++ b/lib/compatibility/knewstuff/engine.h @@ -0,0 +1,189 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_ENGINE_H +#define KNEWSTUFF_ENGINE_H + +#include <qmap.h> +#include <qobject.h> +#include <qstring.h> + +#include "entry.h" +#include "provider.h" + +namespace KIO { class Job; } + +class KNewStuff; + +namespace KNS { + +class DownloadDialog; +class UploadDialog; +class ProviderDialog; + +/** + * @short Central class combining all possible KNewStuff operations. + * + * In most cases, Engine objects are built and used internally. + * Using this class explicitely does however give fine-grained control about the + * upload and download operations. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class Engine : public QObject +{ + Q_OBJECT + public: + /** + Constructor. + + @param newStuff a KNewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param parentWidget the parent window + */ + Engine( KNewStuff *newStuff, const QString &type, QWidget *parentWidget = 0 ); + /** + Constructor. + + @param newStuff a KNewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param providerList the URL of the provider list + @param parentWidget the parent window + */ + Engine( KNewStuff *newStuff, const QString &type, const QString &providerList, QWidget *parentWidget = 0 ); + + /** + Destructor. + */ + virtual ~Engine(); + + /** + Returns the previously set data type. + + @return the Hotstuff data type + */ + QString type() const { return mType; } + + /** + Returns the previously set parent widget. + + @return parent widget + */ + QWidget *parentWidget() const { return mParentWidget; } + + /** + Initiates the download process, retrieving provider lists and invoking + the download dialog. + */ + void download(); + + /** + Initiates the upload process, invoking the provider selection dialog + and the file upload dialog. + + @param fileName name of the payload data file + @param previewName name of the preview image file + */ + void upload( const QString &fileName = QString::null, const QString &previewName = QString::null ); + + /** + Downloads the specified data file. + + @param entry the Hotstuff data object to be downloaded + */ + void download( Entry *entry ); + + /** + Asynchronous lookup of provider information such as upload and + download locations, icon etc. + + @param provider the Hotstuff provider to request information from + */ + void requestMetaInformation( Provider *provider ); + + /** + Uploads the specified data file to the provider-dependent location. + + @param entry the Hotstuff data object to be uploaded + */ + void upload( Entry *entry ); + + /** + Ignores the return value of the install method. Used internally to + avoid showing of the success/failure dialog when installation is done + in another place, like in @ref KNewStuffSecure + */ + void ignoreInstallResult(bool ignore); + + signals: + /** Emitted when the upload has finished. + @param result indicates the success/failure of the upload + */ + void uploadFinished( bool result ); + protected slots: + void getMetaInformation( Provider::List *providers ); + void selectUploadProvider( Provider::List *providers ); + + void slotNewStuffJobData( KIO::Job *job, const QByteArray &data ); + void slotNewStuffJobResult( KIO::Job *job ); + + void slotDownloadJobResult( KIO::Job *job ); + + void slotUploadPayloadJobResult( KIO::Job *job ); + void slotUploadPreviewJobResult (KIO::Job *job ); + void slotUploadMetaJobResult( KIO::Job *job ); + + protected: + bool createMetaFile( Entry * ); + + private: + QWidget *mParentWidget; + + ProviderLoader *mProviderLoader; + + QMap<KIO::Job *,QString> mNewStuffJobData; + QMap<KIO::Job *,Provider *> mProviderJobs; + + QPtrList<Entry> mNewStuffList; + + DownloadDialog *mDownloadDialog; + UploadDialog *mUploadDialog; + ProviderDialog *mProviderDialog; + + QString mDownloadDestination; + + Provider *mUploadProvider; + + QString mUploadMetaFile; + QString mUploadFile; + QString mPreviewFile; + QString mProviderList; + + KNewStuff *mNewStuff; + + QString mType; + + bool mIgnoreInstallResult; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/entry.cpp b/lib/compatibility/knewstuff/entry.cpp new file mode 100644 index 00000000..1d4f7e72 --- /dev/null +++ b/lib/compatibility/knewstuff/entry.cpp @@ -0,0 +1,294 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "entry.h" + +#include <kglobal.h> +#include <klocale.h> + +using namespace KNS; + +Entry::Entry() : + mRelease( 0 ), mReleaseDate( QDate::currentDate() ), mRating( 0 ), + mDownloads( 0 ) +{ +} + +Entry::Entry( const QDomElement &e ) +{ + parseDomElement( e ); +} + +Entry::~Entry() +{ +} + + +void Entry::setName( const QString &name ) +{ + mName = name; +} + +QString Entry::name() const +{ + return mName; +} + + +void Entry::setType( const QString &type ) +{ + mType = type; +} + +QString Entry::type() const +{ + return mType; +} + + +void Entry::setAuthor( const QString &author ) +{ + mAuthor = author; +} + +QString Entry::author() const +{ + return mAuthor; +} + + +void Entry::setLicence( const QString &license ) +{ + mLicence = license; +} + +QString Entry::license() const +{ + return mLicence; +} + + +void Entry::setSummary( const QString &text, const QString &lang ) +{ + mSummaryMap.insert( lang, text ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +QString Entry::summary( const QString &lang ) const +{ + if ( mSummaryMap.isEmpty() ) return QString::null; + + if ( !mSummaryMap[ lang ].isEmpty() ) return mSummaryMap[ lang ]; + else { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mSummaryMap[ *it ].isEmpty() ) return mSummaryMap[ *it ]; + } + if ( !mSummaryMap[ QString::null ].isEmpty() ) return mSummaryMap[ QString::null ]; + else return *(mSummaryMap.begin()); +} + + +void Entry::setVersion( const QString &version ) +{ + mVersion = version; +} + +QString Entry::version() const +{ + return mVersion; +} + + +void Entry::setRelease( int release ) +{ + mRelease = release; +} + +int Entry::release() const +{ + return mRelease; +} + + +void Entry::setReleaseDate( const QDate &d ) +{ + mReleaseDate = d; +} + +QDate Entry::releaseDate() const +{ + return mReleaseDate; +} + + +void Entry::setPayload( const KURL &url, const QString &lang ) +{ + mPayloadMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::payload( const QString &lang ) const +{ + KURL payload = mPayloadMap[ lang ]; + if ( payload.isEmpty() ) { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPayloadMap[ *it ].isEmpty() ) return mPayloadMap[ *it ]; + } + if ( payload.isEmpty() ) payload = mPayloadMap [ QString::null ]; + if ( payload.isEmpty() && !mPayloadMap.isEmpty() ) { + payload = *(mPayloadMap.begin()); + } + return payload; +} + + +void Entry::setPreview( const KURL &url, const QString &lang ) +{ + mPreviewMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::preview( const QString &lang ) const +{ + KURL preview = mPreviewMap[ lang ]; + if ( preview.isEmpty() ) { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPreviewMap[ *it ].isEmpty() ) return mPreviewMap[ *it ]; + } + if ( preview.isEmpty() ) preview = mPreviewMap [ QString::null ]; + if ( preview.isEmpty() && !mPreviewMap.isEmpty() ) { + preview = *(mPreviewMap.begin()); + } + return preview; +} + + +void Entry::setRating( int rating ) +{ + mRating = rating; +} + +int Entry::rating() +{ + return mRating; +} + + +void Entry::setDownloads( int downloads ) +{ + mDownloads = downloads; +} + +int Entry::downloads() +{ + return mDownloads; +} + +QString Entry::fullName() +{ + return name() + "-" + version() + "-" + QString::number( release() ); +} + +QStringList Entry::langs() +{ + return mLangs; +} + +void Entry::parseDomElement( const QDomElement &element ) +{ + if ( element.tagName() != "stuff" ) return; + mType = element.attribute("type"); + + QDomNode n; + for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement e = n.toElement(); + if ( e.tagName() == "name" ) setName( e.text().stripWhiteSpace() ); + if ( e.tagName() == "author" ) setAuthor( e.text().stripWhiteSpace() ); + if ( e.tagName() == "licence" ) setLicence( e.text().stripWhiteSpace() ); + if ( e.tagName() == "summary" ) { + QString lang = e.attribute( "lang" ); + setSummary( e.text().stripWhiteSpace(), lang ); + } + if ( e.tagName() == "version" ) setVersion( e.text().stripWhiteSpace() ); + if ( e.tagName() == "release" ) setRelease( e.text().toInt() ); + if ( e.tagName() == "releasedate" ) { + QDate date = QDate::fromString( e.text().stripWhiteSpace(), Qt::ISODate ); + setReleaseDate( date ); + } + if ( e.tagName() == "preview" ) { + QString lang = e.attribute( "lang" ); + setPreview( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "payload" ) { + QString lang = e.attribute( "lang" ); + setPayload( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "rating" ) setRating( e.text().toInt() ); + if ( e.tagName() == "downloads" ) setDownloads( e.text().toInt() ); + } +} + +QDomElement Entry::createDomElement( QDomDocument &doc, + QDomElement &parent ) +{ + QDomElement entry = doc.createElement( "stuff" ); + entry.setAttribute("type", mType); + parent.appendChild( entry ); + + addElement( doc, entry, "name", name() ); + addElement( doc, entry, "author", author() ); + addElement( doc, entry, "licence", license() ); + addElement( doc, entry, "version", version() ); + addElement( doc, entry, "release", QString::number( release() ) ); + addElement( doc, entry, "rating", QString::number( rating() ) ); + addElement( doc, entry, "downloads", QString::number( downloads() ) ); + + addElement( doc, entry, "releasedate", + releaseDate().toString( Qt::ISODate ) ); + + QStringList ls = langs(); + QStringList::ConstIterator it; + for( it = ls.begin(); it != ls.end(); ++it ) { + QDomElement e = addElement( doc, entry, "summary", summary( *it ) ); + e.setAttribute( "lang", *it ); + e = addElement( doc, entry, "preview", preview( *it ).url() ); + e.setAttribute( "lang", *it ); + e = addElement( doc, entry, "payload", payload( *it ).url() ); + e.setAttribute( "lang", *it ); + } + + return entry; +} + +QDomElement Entry::addElement( QDomDocument &doc, QDomElement &parent, + const QString &tag, const QString &value ) +{ + QDomElement n = doc.createElement( tag ); + n.appendChild( doc.createTextNode( value ) ); + parent.appendChild( n ); + + return n; +} diff --git a/lib/compatibility/knewstuff/entry.h b/lib/compatibility/knewstuff/entry.h new file mode 100644 index 00000000..3a16964d --- /dev/null +++ b/lib/compatibility/knewstuff/entry.h @@ -0,0 +1,257 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_ENTRY_H +#define KNEWSTUFF_ENTRY_H + +#include <qdatetime.h> +#include <qdom.h> +#include <qmap.h> +#include <qstring.h> +#include <qstringlist.h> + +#include <kurl.h> + +namespace KNS { + +/** + * @short KNewStuff data entry container. + * + * This class provides accessor methods to the data objects + * as used by KNewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class KDE_EXPORT Entry +{ + public: + Entry(); + /** + * Constructor. + */ + Entry( const QDomElement & ); + + /** + * Destructor. + */ + ~Entry(); + + /** + * Sets the (unique) name for this data object. + */ + void setName( const QString & ); + + /** + * Retrieve the name of the data object. + * + * @return object name + */ + QString name() const; + + /** + * Sets the application type, e.g. 'kdesktop/wallpaper'. + */ + void setType( const QString & ); + + /** + * Retrieve the type of the data object. + * + * @return object type + */ + QString type() const; + + /** + * Sets the full name of the object's author. + */ + void setAuthor( const QString & ); + + /** + * Retrieve the author's name of the object. + * + * @return object author + */ + QString author() const; + + /** + * Sets the license (abbreviation) applicable to the object. + */ + void setLicence( const QString & ); + + /** + * Retrieve the license name of the object. + * + * @return object license + */ + QString license() const; + + /** + * Sets a short description on what the object is all about. + */ + void setSummary( const QString &, const QString &lang = QString::null ); + + /** + * Retrieve a short description about the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object description + */ + QString summary( const QString &lang = QString::null ) const; + + /** + * Sets the version number. + */ + void setVersion( const QString & ); + + /** + * Retrieve the version string of the object. + * + * @return object version + */ + QString version() const; + + /** + * Sets the release number, which is increased for feature-equal objects + * with the same version number, but slightly updated contents. + */ + void setRelease( int ); + + /** + * Retrieve the release number of the object + * + * @return object release + */ + int release() const; + + /** + * Sets the release date. + */ + void setReleaseDate( const QDate & ); + + /** + * Retrieve the date of the object's publication. + * + * @return object release date + */ + QDate releaseDate() const; + + /** + * Sets the object's file. + */ + void setPayload( const KURL &, const QString &lang = QString::null ); + + /** + * Retrieve the file name of the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object filename + */ + KURL payload( const QString &lang = QString::null ) const; + + /** + * Sets the object's preview file, if available. This should be a + * picture file. + */ + void setPreview( const KURL &, const QString &lang = QString::null ); + + /** + * Retrieve the file name of an image containing a preview of the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object preview filename + */ + KURL preview( const QString &lang = QString::null ) const; + + /** + * Sets the rating between 0 (worst) and 10 (best). + * + * @internal + */ + void setRating( int ); + + /** + * Retrieve the rating for the object, which has been determined by its + * users and thus might change over time. + * + * @return object rating + */ + int rating(); + + /** + * Sets the number of downloads. + * + * @internal + */ + void setDownloads( int ); + + /** + * Retrieve the download count for the object, which has been determined + * by its hosting sites and thus might change over time. + * + * @return object download count + */ + int downloads(); + + /** + * Return the full name for the meta information. It is constructed as + * name-version-release. + */ + QString fullName(); + + /** + * Return the list of languages this object supports. + */ + QStringList langs(); + + /** + * @internal + */ + void parseDomElement( const QDomElement & ); + + /** + * @internal + */ + QDomElement createDomElement( QDomDocument &, QDomElement &parent ); + + protected: + QDomElement addElement( QDomDocument &doc, QDomElement &parent, + const QString &tag, const QString &value ); + + private: + QString mName; + QString mType; + QString mAuthor; + QString mLicence; + QMap<QString,QString> mSummaryMap; + QString mVersion; + int mRelease; + QDate mReleaseDate; + QMap<QString,KURL> mPayloadMap; + QMap<QString,KURL> mPreviewMap; + int mRating; + int mDownloads; + + QStringList mLangs; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/knewstuff.cpp b/lib/compatibility/knewstuff/knewstuff.cpp new file mode 100644 index 00000000..5387e647 --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuff.cpp @@ -0,0 +1,86 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include "engine.h" + +#include "knewstuff.h" + +using namespace KNS; + +KAction* KNS::standardAction(const QString& what, + const QObject *recvr, + const char *slot, KActionCollection* parent, + const char *name) +{ + return new KAction(i18n("Download New %1").arg(what), "knewstuff", + 0, recvr, slot, parent, name); +} + +KNewStuff::KNewStuff( const QString &type, QWidget *parentWidget ) +{ + mEngine = new Engine( this, type, parentWidget ); +} + +KNewStuff::KNewStuff( const QString &type, const QString &providerList, QWidget *parentWidget ) +{ + mEngine = new Engine( this, type, providerList, parentWidget ); +} + +QString KNewStuff::type() const +{ + return mEngine->type(); +} + +QWidget *KNewStuff::parentWidget() const +{ + return mEngine->parentWidget(); +} + +KNewStuff::~KNewStuff() +{ + delete mEngine; +} + +void KNewStuff::download() +{ + mEngine->download(); +} + +QString KNewStuff::downloadDestination( Entry * ) +{ + return KGlobal::dirs()->saveLocation( "tmp" ) + + KApplication::randomString( 10 ); +} + +void KNewStuff::upload() +{ + mEngine->upload(); +} + +void KNewStuff::upload( const QString &fileName, const QString previewName ) +{ + mEngine->upload(fileName, previewName); +} diff --git a/lib/compatibility/knewstuff/knewstuff.h b/lib/compatibility/knewstuff/knewstuff.h new file mode 100644 index 00000000..9d2d10ed --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuff.h @@ -0,0 +1,161 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_H +#define KNEWSTUFF_H + +#include <qstring.h> + +#include <kdemacros.h> + +class QObject; +class QWidget; +class KAction; +class KActionCollection; + +namespace KNS { +class Engine; +class Entry; + +KAction* standardAction(const QString& what, + const QObject *recvr, + const char *slot, + KActionCollection* parent, + const char *name = 0); +} + +/** + * @short This class provides the functionality to download and upload "new stuff". + * + * Applications have to subclass KNewStuff, implement the pure virtual functions + * and link to against libknewstuff. + * + * By calling download() the download process is started which means that a list + * of "providers" is fetched from a "master server", information about new stuff + * is collected from the providers and presented to the user. Selected entries + * get downloaded and installed to the application. The required functions to + * install new stuff are provided by implementing install(). The location where + * the downloaded files are stored can be customized by reimplementing + * downloadDestination(). + * + * By calling upload() the upload process is started which means the user has to + * select a provider from the list fetched from the master server and to put in + * information about the entry to be uploaded. Then the file to be uploaded is + * fetched from the application by calling createUploadFile() and transfered to + * the upload destination specified in the provider list. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + * + * @since 3.3 + */ +class KDE_EXPORT KNewStuff +{ + public: + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuff( const QString &type, QWidget *parentWidget = 0 ); + + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param providerList the URL of the provider list + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuff( const QString &type, const QString &providerList, QWidget *parentWidget = 0 ); + virtual ~KNewStuff(); + + /** + Return type of data. + */ + QString type() const; + + /** + Return parent widget. + */ + QWidget *parentWidget() const; + + /** + Start download process. + */ + void download(); + + /** + Start upload process. + */ + void upload(); + + /** + Upload with pre-defined files. + */ + void upload( const QString &fileName, const QString previewName ); + + /** + Install file to application. The given fileName points to the file + downloaded by the KNewStuff engine. This is a temporary file by default. + The application can do whatever is needed to handle the information + contained in the file. + + The function returns true, when the installation + was successful and false if were errors. + + @param fileName name of downloaded file + */ + virtual bool install( const QString &fileName ) = 0; + /** + Create a file to be uploaded to a "new stuff provider" and return the + filename. The format of the file is application specific. The only + constraint is that the corresponding install() implementation is able to + use the file. + + @param fileName name of the file to be written + @return @c true on success, @c false on error. + */ + virtual bool createUploadFile( const QString &fileName ) = 0; + + /** + Return a filename which should be used as destination for downloading the + specified new stuff entry. Reimplement this function, if you don't want + the new stuff to be downloaded to a temporary file. + */ + virtual QString downloadDestination( KNS::Entry *entry ); + + + protected: + /** + Get the pointer to the engine. Needed by subclasses to access the KNS::Engine object. + */ + KNS::Engine *engine() { return mEngine; } + + + private: + KNS::Engine *mEngine; +}; + +#endif diff --git a/lib/compatibility/knewstuff/knewstuffgeneric.cpp b/lib/compatibility/knewstuff/knewstuffgeneric.cpp new file mode 100644 index 00000000..22673dac --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffgeneric.cpp @@ -0,0 +1,140 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qfile.h> +#include <qtextstream.h> +#include <qdir.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kprocess.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <ktar.h> + +#include "entry.h" + +#include "knewstuffgeneric.h" + +using namespace std; + +KNewStuffGeneric::KNewStuffGeneric( const QString &type, QWidget *parent ) + : KNewStuff( type, parent ) +{ + mConfig = KGlobal::config(); +} + +KNewStuffGeneric::~KNewStuffGeneric() +{ +} + +bool KNewStuffGeneric::install( const QString &fileName ) +{ + kdDebug(5850) << "KNewStuffGeneric::install(): " << fileName << endl; + QStringList list, list2; + + mConfig->setGroup("KNewStuff"); + + QString uncompress = mConfig->readEntry( "Uncompress" ); + if ( !uncompress.isEmpty() ) { + kdDebug(5850) << "Uncompression method: " << uncompress << endl; + KTar tar(fileName, uncompress); + tar.open(IO_ReadOnly); + const KArchiveDirectory *dir = tar.directory(); + dir->copyTo(destinationPath(0)); + tar.close(); + QFile::remove(fileName); + } + + QString cmd = mConfig->readEntry( "InstallationCommand" ); + if ( !cmd.isEmpty() ) { + kdDebug(5850) << "InstallationCommand: " << cmd << endl; + list = QStringList::split( " ", cmd ); + for ( QStringList::iterator it = list.begin(); it != list.end(); ++it) { + list2 << (*it).replace("%f", fileName); + } + KProcess proc; + proc << list2; + proc.start( KProcess::Block ); + } + + return true; +} + +bool KNewStuffGeneric::createUploadFile( const QString & /*fileName*/ ) +{ + return false; +} + +QString KNewStuffGeneric::destinationPath( KNS::Entry *entry ) +{ + QString path, file, target; + + mConfig->setGroup("KNewStuff"); + + if( entry ) target = entry->fullName(); + else target = "/"; + QString res = mConfig->readEntry( "StandardResource" ); + if ( res.isEmpty() ) + { + target = mConfig->readEntry("TargetDir"); + if ( !target.isEmpty()) + { + res = "data"; + if ( entry ) target.append("/" + entry->fullName()); + else target.append("/"); + } + } + if ( res.isEmpty() ) + { + path = mConfig->readEntry( "InstallPath" ); + } + if ( res.isEmpty() && path.isEmpty() ) + { + if ( !entry ) return QString::null; + else return KNewStuff::downloadDestination( entry ); + } + + if ( !path.isEmpty() ) + { + file = QDir::home().path() + "/" + path + "/"; + if ( entry ) file += entry->fullName(); + } + else file = locateLocal( res.utf8() , target ); + + return file; +} + +QString KNewStuffGeneric::downloadDestination( KNS::Entry *entry ) +{ + QString file = destinationPath(entry); + + if ( KStandardDirs::exists( file ) ) { + int result = KMessageBox::warningContinueCancel( parentWidget(), + i18n("The file '%1' already exists. Do you want to override it?") + .arg( file ), + QString::null, i18n("Overwrite") ); + if ( result == KMessageBox::Cancel ) return QString::null; + } + + return file; +} diff --git a/lib/compatibility/knewstuff/knewstuffgeneric.h b/lib/compatibility/knewstuff/knewstuffgeneric.h new file mode 100644 index 00000000..5443e24a --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffgeneric.h @@ -0,0 +1,86 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFFGENERIC_H +#define KNEWSTUFFGENERIC_H + +#include "knewstuff.h" + +class KConfig; + +/** + * @short Basic KNewStuff class with predefined actions. + * + * This class is used for data uploads and installation. + * \code + * QString payload, preview; + * KNewStuffGeneric *ns = new KNewStuffGeneric("kamikaze/level", this); + * ns->upload(payload, preview); + * \endcode + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class KDE_EXPORT KNewStuffGeneric : public KNewStuff +{ + public: + /** + Constructor. + + @param type a Hotstuff data type such as "korganizer/calendar" + @param parent the parent window. + */ + KNewStuffGeneric( const QString &type, QWidget *parent = 0 ); + ~KNewStuffGeneric(); + + /** + Installs a downloaded file according to the application's configuration. + + @param fileName filename of the donwloaded file + @return @c true in case of installation success, @c false otherwise + */ + bool install( const QString &fileName ); + + /** + Creates a file suitable for upload. + Note that this method always fails, since using KNewStuffGeneric + means that the provided file must already be in a usable format. + + @param fileName the name of the file to upload after its creation + @return @c true in case of creation success, @c false otherwise + */ + bool createUploadFile( const QString &fileName ); + + /** + Queries the preferred destination file for a download. + + @param entry a Hotstuff data entry + @return destination filename, or 0 to return directory only + */ + QString downloadDestination( KNS::Entry *entry ); + + private: + QString destinationPath( KNS::Entry *entry ); + + KConfig *mConfig; +}; + +#endif diff --git a/lib/compatibility/knewstuff/knewstuffsecure.cpp b/lib/compatibility/knewstuff/knewstuffsecure.cpp new file mode 100644 index 00000000..270d9449 --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffsecure.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** + knewstuffsecure.cpp - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia <[email protected]> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ +//qt includes +#include <qfileinfo.h> + +//kde includes +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktar.h> +#include <ktempdir.h> + +//app includes +#include "engine.h" +#include "knewstuffsecure.h" +#include "security.h" + +using namespace KNS; + +KNewStuffSecure::KNewStuffSecure(const QString &type, QWidget *parentWidget) + : KNewStuff(type, parentWidget) +{ + m_tempDir = 0L; + connect(engine(), SIGNAL(uploadFinished(bool)), SLOT(slotUploadFinished(bool))); +} + + +KNewStuffSecure::~KNewStuffSecure() +{ + removeTempDirectory(); +} + +bool KNewStuffSecure::install(const QString &fileName) +{ + bool ok = true; + + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + KTar tar(fileName, "application/x-gzip"); + if (tar.open(IO_ReadOnly)) + { + const KArchiveDirectory *directory = tar.directory(); + directory->copyTo(m_tempDir->name(), true); + m_tarName = ""; + QStringList entries = directory->entries(); + for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) + { + if (*it != "signature" && *it != "md5sum") + { + m_tarName = *it; + break; + } + } + tar.close(); + if (m_tarName.isEmpty()) + ok = false; + else + { + m_tarName.prepend(m_tempDir->name()); + connect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); + Security::ref()->checkValidity(m_tarName); + } + } else + ok = false; + if (!ok) + KMessageBox::error(parentWidget(), i18n("There was an error with the downloaded resource tarball file. Possible causes are damaged archive or invalid directory structure in the archive."), i18n("Resource Installation Error")); + return ok; +} + +void KNewStuffSecure::slotValidated(int result) +{ + QString errorString; + QString signatureStr; + bool valid = true; + if (result == -1) + { + errorString ="<br>- " + i18n("No keys were found."); + valid = false; + } else + if (result == 0) + { + errorString ="<br>- " + i18n("The validation failed for unknown reason."); + valid = false; + } else + { + KeyStruct key = Security::ref()->signatureKey(); + if (!(result & Security::MD5_OK )) + { + errorString = "<br>- " + i18n("The MD5SUM check failed, the archive might be broken."); + valid = false; + } + if (result & Security::SIGNED_BAD) + { + errorString += "<br>- " + i18n("The signature is bad, the archive might be broken or altered."); + valid = false; + } + if (result & Security::SIGNED_OK) + { + if (result & Security::TRUSTED) + { + kdDebug() << "Signed and trusted " << endl; + } else + { + errorString += "<br>- " + i18n("The signature is valid, but untrusted."); + valid = false; + } + } + if (result & Security::UNKNOWN) + { + errorString += "<br>- " + i18n("The signature is unknown."); + valid = false; + } else + { + signatureStr = i18n("The resource was signed with key <i>0x%1</i>, belonging to <i>%2 <%3></i>.").arg(key.id.right(8)).arg(key.name).arg(key.mail); + } + } + if (!valid) + { + signatureStr.prepend( "<br>"); + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("<qt>There is a problem with the resource file you have downloaded. The errors are :<b>%1</b><br>%2<br><br>Installation of the resource is <b>not recommended</b>.<br><br>Do you want to proceed with the installation?</qt>").arg(errorString).arg(signatureStr), i18n("Problematic Resource File")) == KMessageBox::Continue) + valid = true; + } else + KMessageBox::information(parentWidget(), i18n("<qt>%1<br><br>Press OK to install it.</qt>").arg(signatureStr), i18n("Valid Resource"), "Show Valid Signature Information"); + if (valid) + { + installResource(); + emit installFinished(); + } else + { + KConfig *cfg = KGlobal::config(); + cfg->deleteGroup("KNewStuffStatus"); + cfg->setGroup("KNewStuffStatus"); + for (QMap<QString, QString>::ConstIterator it = m_installedResources.constBegin(); it != m_installedResources.constEnd(); ++it) + { + cfg->writeEntry(it.key(), it.data()); + } + cfg->sync(); + } + removeTempDirectory(); + disconnect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); +} + +void KNewStuffSecure::downloadResource() +{ + KConfig *cfg = KGlobal::config(); + m_installedResources = cfg->entryMap("KNewStuffStatus"); + engine()->ignoreInstallResult(true); + KNewStuff::download(); +} + +bool KNewStuffSecure::createUploadFile(const QString &fileName) +{ + Q_UNUSED(fileName); + return true; +} + +void KNewStuffSecure::uploadResource(const QString& fileName) +{ + connect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + QFileInfo f(fileName); + m_signedFileName = m_tempDir->name() + "/" + f.fileName(); + KIO::NetAccess::file_copy(KURL::fromPathOrURL(fileName), KURL::fromPathOrURL(m_signedFileName), -1, true); + Security::ref()->signFile(m_signedFileName); +} + +void KNewStuffSecure::slotFileSigned(int result) +{ + if (result == 0) + { + KMessageBox::error(parentWidget(), i18n("The signing failed for unknown reason.")); + } else + { + if (result & Security::BAD_PASSPHRASE) + { + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("There are no keys usable for signing or you did not entered the correct passphrase.\nProceed without signing the resource?")) == KMessageBox::Cancel) + { + disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + removeTempDirectory(); + return; + } + } + KTar tar(m_signedFileName + ".signed", "application/x-gzip"); + tar.open(IO_WriteOnly); + QStringList files; + files << m_signedFileName; + files << m_tempDir->name() + "/md5sum"; + files << m_tempDir->name() + "/signature"; + + for (QStringList::Iterator it_f = files.begin(); it_f != files.end(); ++it_f) + { + QFile file(*it_f); + file.open(IO_ReadOnly); + QByteArray bArray = file.readAll(); + tar.writeFile(QFileInfo(file).fileName(), "user", "group", bArray.size(), bArray.data()); + file.close(); + } + tar.close(); + KIO::NetAccess::file_move(KURL::fromPathOrURL(m_signedFileName + ".signed"), KURL::fromPathOrURL(m_signedFileName), -1, true); + KNewStuff::upload(m_signedFileName, QString::null); + disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + } +} + +void KNewStuffSecure::slotUploadFinished(bool result) +{ + Q_UNUSED(result); + removeTempDirectory(); +} + +void KNewStuffSecure::removeTempDirectory() +{ + if (m_tempDir) + { + KIO::NetAccess::del(KURL().fromPathOrURL(m_tempDir->name()), parentWidget()); + delete m_tempDir; + m_tempDir = 0L; + } +} + +#include "knewstuffsecure.moc" diff --git a/lib/compatibility/knewstuff/knewstuffsecure.h b/lib/compatibility/knewstuff/knewstuffsecure.h new file mode 100644 index 00000000..2aed131a --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffsecure.h @@ -0,0 +1,101 @@ +/*************************************************************************** + knewstuffsecure.h - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia <[email protected]> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + +#ifndef KNEWSTUFFSECURE_H +#define KNEWSTUFFSECURE_H + +//qt includes +#include <qobject.h> + +//kde includes +#include "knewstuff.h" + +class KTempDir; +/** +Makes possible downloading and installing signed resource files from a server. +You must subclass it and implement the @ref installResource() pure +virtual method to install a resource. For uploading you must create a resource +tarball (which is installabale by @ref installResource()) and call the +@ref uploadResource() method with this tarball as the argument. +Signing and verification is done by the gpg application, so the user must +have it installed, otherwise this class does not give any extra security compared +to the standard KNewStuff class. + +@since 3.4 + +@author Andras Mantia <[email protected]> +*/ +class KDE_EXPORT KNewStuffSecure : public QObject, public KNewStuff +{ + Q_OBJECT + +public: + /** Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuffSecure(const QString &type, QWidget *parentWidget=0); + virtual ~KNewStuffSecure(); + + /** Installs the downloaded resource. Do not call or reimplement directly. + It's reimplemented from KNewStuff for internal reasons. + */ + bool install( const QString &fileName ); + + /** Reimplemented for internal reasons. */ + bool createUploadFile(const QString &fileName); + + /** Initiates a download. This is the method that must be called in + * order to download a signed resource. */ + void downloadResource(); + + /** Signs the file and uploads to the central server. + * @param fileName The file to be signed and uploaded + */ + void uploadResource(const QString &fileName); + + +private slots: + /** Checks the validity of the downloaded tarball and installs it*/ + void slotValidated(int result); + /** The file is signed, so it can be uploaded.*/ + void slotFileSigned(int result); + /** Called when the upload has finished. + @param result the result of the upload + Be careful if you reimplement it, as it deletes the temporary directory + m_tempDir used for upload. You must also delete it (call the parent's method) + if you reimplement it. + */ + void slotUploadFinished(bool result); + +signals: + void installFinished(); + +protected: + /** Installs the resource specified by m_tarName. Implement it in the subclass. */ + virtual void installResource() = 0; + /** Removes the temporary directory m_tempDir. */ + void removeTempDirectory(); + + KTempDir *m_tempDir; + QString m_tarName; + QString m_signedFileName; + QMap<QString, QString> m_installedResources; +}; + +#endif diff --git a/lib/compatibility/knewstuff/provider.cpp b/lib/compatibility/knewstuff/provider.cpp new file mode 100644 index 00000000..2ab48f18 --- /dev/null +++ b/lib/compatibility/knewstuff/provider.cpp @@ -0,0 +1,223 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kconfig.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kglobal.h> +#include <kmessagebox.h> +#include <klocale.h> + +#include "provider.h" +#include "provider.moc" + +using namespace KNS; + +Provider::Provider() : mNoUpload( false ) +{ +} + +Provider::Provider( const QDomElement &e ) : mNoUpload( false ) +{ + parseDomElement( e ); +} + +Provider::~Provider() +{ +} + + +void Provider::setName( const QString &name ) +{ + mName = name; +} + +QString Provider::name() const +{ + return mName; +} + + +void Provider::setIcon( const KURL &url ) +{ + mIcon = url; +} + +KURL Provider::icon() const +{ + return mIcon; +} + + +void Provider::setDownloadUrl( const KURL &url ) +{ + mDownloadUrl = url; +} + +KURL Provider::downloadUrl() const +{ + return mDownloadUrl; +} + + +void Provider::setUploadUrl( const KURL &url ) +{ + mUploadUrl = url; +} + +KURL Provider::uploadUrl() const +{ + return mUploadUrl; +} + + +void Provider::setNoUploadUrl( const KURL &url ) +{ + mNoUploadUrl = url; +} + +KURL Provider::noUploadUrl() const +{ + return mNoUploadUrl; +} + + +void Provider::setNoUpload( bool enabled ) +{ + mNoUpload = enabled; +} + +bool Provider::noUpload() const +{ + return mNoUpload; +} + + +void Provider::parseDomElement( const QDomElement &element ) +{ + if ( element.tagName() != "provider" ) return; + + setDownloadUrl( KURL( element.attribute("downloadurl") ) ); + setUploadUrl( KURL( element.attribute("uploadurl") ) ); + setNoUploadUrl( KURL( element.attribute("nouploadurl") ) ); + setIcon( KURL( element.attribute("icon") ) ); + + QDomNode n; + for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement p = n.toElement(); + + if ( p.tagName() == "noupload" ) setNoUpload( true ); + if ( p.tagName() == "title" ) setName( p.text().stripWhiteSpace() ); + } +} + +QDomElement Provider::createDomElement( QDomDocument &doc, QDomElement &parent ) +{ + QDomElement entry = doc.createElement( "stuff" ); + parent.appendChild( entry ); + + QDomElement n = doc.createElement( "name" ); + n.appendChild( doc.createTextNode( name() ) ); + entry.appendChild( n ); + + return entry; +} + + +ProviderLoader::ProviderLoader( QWidget *parentWidget ) : + mParentWidget( parentWidget ) +{ + mProviders.setAutoDelete( true ); +} + +void ProviderLoader::load( const QString &type, const QString &providersList ) +{ + kdDebug(5850) << "ProviderLoader::load()" << endl; + + mProviders.clear(); + mJobData = ""; + + KConfig *cfg = KGlobal::config(); + cfg->setGroup("KNewStuff"); + + QString providersUrl = providersList; + if( providersUrl.isEmpty() ) + providersUrl = cfg->readEntry( "ProvidersUrl" ); + + if ( providersUrl.isEmpty() ) { + // TODO: Replace the default by the real one. + QString server = cfg->readEntry( "MasterServer", + "http://korganizer.kde.org" ); + + providersUrl = server + "/knewstuff/" + type + "/providers.xml"; + } + + kdDebug(5850) << "ProviderLoader::load(): providersUrl: " << providersUrl << endl; + + KIO::TransferJob *job = KIO::get( KURL( providersUrl ) ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotJobResult( KIO::Job * ) ) ); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), + SLOT( slotJobData( KIO::Job *, const QByteArray & ) ) ); + +// job->dumpObjectInfo(); +} + +void ProviderLoader::slotJobData( KIO::Job *, const QByteArray &data ) +{ + kdDebug(5850) << "ProviderLoader::slotJobData()" << endl; + + if ( data.size() == 0 ) return; + + QCString str( data, data.size() + 1 ); + + mJobData.append( QString::fromUtf8( str ) ); +} + +void ProviderLoader::slotJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + job->showErrorDialog( mParentWidget ); + } + + kdDebug(5850) << "--PROVIDERS-START--" << endl << mJobData << "--PROV_END--" + << endl; + + QDomDocument doc; + if ( !doc.setContent( mJobData ) ) { + KMessageBox::error( mParentWidget, i18n("Error parsing providers list.") ); + return; + } + + QDomElement providers = doc.documentElement(); + + if ( providers.isNull() ) { + kdDebug(5850) << "No document in Providers.xml." << endl; + } + + QDomNode n; + for ( n = providers.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement p = n.toElement(); + + mProviders.append( new Provider( p ) ); + } + + emit providersLoaded( &mProviders ); +} diff --git a/lib/compatibility/knewstuff/provider.h b/lib/compatibility/knewstuff/provider.h new file mode 100644 index 00000000..69898bc4 --- /dev/null +++ b/lib/compatibility/knewstuff/provider.h @@ -0,0 +1,206 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_PROVIDER_H +#define KNEWSTUFF_PROVIDER_H + +#include <qcstring.h> +#include <qdom.h> +#include <qobject.h> +#include <qptrlist.h> +#include <qstring.h> + +#include <kurl.h> + +namespace KIO { class Job; } + +namespace KNS { + +/** + * @short KNewStuff provider container. + * + * This class provides accessors for the provider object. + * as used by KNewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class Provider +{ + public: + typedef QPtrList<Provider> List; + + /** + * Constructor. + */ + Provider(); + + /** + * Constructor with XML feed. + */ + Provider( const QDomElement & ); + + /** + * Destructor. + */ + ~Provider(); + + /** + * Sets the common name of the provider. + */ + void setName( const QString & ); + + /** + * Retrieves the common name of the provider. + * + * @return provider name + */ + QString name() const; + + /** + * Sets the download URL. + */ + void setDownloadUrl( const KURL & ); + + /** + * Retrieves the download URL. + * + * @return download URL + */ + KURL downloadUrl() const; + + /** + * Sets the upload URL. + */ + void setUploadUrl( const KURL & ); + + /** + * Retrieves the upload URL. + * + * @return upload URL + */ + KURL uploadUrl() const; + + /** + * Sets the URL where a user is led if the provider does not support + * uploads. + * + * @see setNoUpload + */ + void setNoUploadUrl( const KURL & ); + + /** + * Retrieves the URL where a user is led if the provider does not + * support uploads. + * + * @return website URL + */ + KURL noUploadUrl() const; + + /** + * Indicate whether provider supports uploads. + */ + void setNoUpload( bool ); + + /** + * Query whether provider supports uploads. + * + * @return upload support status + */ + bool noUpload() const; + + /** + * Sets the URL for an icon for this provider. + * The icon should be in 32x32 format. If not set, the default icon + * of KDialogBase is used. + */ + void setIcon( const KURL & ); + + /** + * Retrieves the icon URL for this provider. + * + * @return icon URL + */ + KURL icon() const; + + protected: + void parseDomElement( const QDomElement & ); + + QDomElement createDomElement( QDomDocument &, QDomElement &parent ); + + private: + QString mName; + KURL mDownloadUrl; + KURL mUploadUrl; + KURL mNoUploadUrl; + KURL mIcon; + bool mNoUpload; +}; + +/** + * KNewStuff provider loader. + * This class sets up a list of all possible providers by querying + * the main provider database for this specific application. + * It should probably not be used directly by the application. + */ +class ProviderLoader : public QObject +{ + Q_OBJECT + public: + /** + * Constructor. + * + * @param parentWidget the parent widget + */ + ProviderLoader( QWidget *parentWidget ); + + /** + * Starts asynchronously loading the list of providers of the + * specified type. + * + * @param type data type such as 'kdesktop/wallpaper'. + * @param providerList the URl to the list of providers; if empty + * we first try the ProvidersUrl from KGlobal::config, then we + * fall back to a hardcoded value. + */ + void load( const QString &type, const QString &providerList = QString::null ); + + signals: + /** + * Indicates that the list of providers has been successfully loaded. + */ + void providersLoaded( Provider::List * ); + + protected slots: + void slotJobData( KIO::Job *, const QByteArray & ); + void slotJobResult( KIO::Job * ); + + private: + QWidget *mParentWidget; + + QString mJobData; + + Provider::List mProviders; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/providerdialog.cpp b/lib/compatibility/knewstuff/providerdialog.cpp new file mode 100644 index 00000000..00374a34 --- /dev/null +++ b/lib/compatibility/knewstuff/providerdialog.cpp @@ -0,0 +1,95 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qlayout.h> +#include <qstring.h> +#include <qlabel.h> + +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "engine.h" +#include "provider.h" + +#include "providerdialog.h" +#include "providerdialog.moc" + +using namespace KNS; + +class ProviderItem : public KListViewItem +{ + public: + ProviderItem( KListView *parent, Provider *provider ) : + KListViewItem( parent ), mProvider( provider ) + { + setText( 0, provider->name() ); + } + + Provider *provider() { return mProvider; } + + private: + Provider *mProvider; +}; + +ProviderDialog::ProviderDialog( Engine *engine, QWidget *parent ) : + KDialogBase( Plain, i18n("Hot New Stuff Providers"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + QFrame *topPage = plainPage(); + + QBoxLayout *topLayout = new QVBoxLayout( topPage ); + + QLabel *description = new QLabel( i18n("Please select one of the providers listed below:"), topPage ); + topLayout->addWidget( description ); + + mListView = new KListView( topPage ); + mListView->addColumn( i18n("Name") ); + topLayout->addWidget( mListView ); +} + +void ProviderDialog::clear() +{ + mListView->clear(); +} + +void ProviderDialog::addProvider( Provider *provider ) +{ + new ProviderItem( mListView, provider ); + if ( mListView->childCount() == 1 ) { + mListView->setSelected(mListView->firstChild(), true); + } else if (mListView->childCount() > 1) { + mListView->setSelected(mListView->firstChild(), false); + } +} + +void ProviderDialog::slotOk() +{ + ProviderItem *item = static_cast<ProviderItem *>( mListView->selectedItem() ); + if ( !item ) { + KMessageBox::error( this, i18n("No provider selected.") ); + return; + } + + mEngine->requestMetaInformation( item->provider() ); + + accept(); +} diff --git a/lib/compatibility/knewstuff/providerdialog.h b/lib/compatibility/knewstuff/providerdialog.h new file mode 100644 index 00000000..c75cc3a1 --- /dev/null +++ b/lib/compatibility/knewstuff/providerdialog.h @@ -0,0 +1,76 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_PROVIDERDIALOG_H +#define KNEWSTUFF_PROVIDERDIALOG_H + +#include <kdialogbase.h> + +class KListView; + +namespace KNS { + +class Provider; +class Engine; + +/** + * @short Dialog displaying a list of Hotstuff providers. + * + * This is normally used in the process of uploading data, thus limiting the + * list to providers which support uploads. + * One of the providers is then chosen by the user for further operation. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class ProviderDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a KNewStuff engine object + @param parent the parent window + */ + ProviderDialog( Engine *engine, QWidget *parent ); + + /** + Clears the list of providers. + */ + void clear(); + + /** + Adds a Hotstuff provider to the list. + */ + void addProvider( Provider * ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + KListView *mListView; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/security.cpp b/lib/compatibility/knewstuff/security.cpp new file mode 100644 index 00000000..f7099c72 --- /dev/null +++ b/lib/compatibility/knewstuff/security.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + security.cpp - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia <[email protected]> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + + //qt includes +#include <qfile.h> +#include <qfileinfo.h> +#include <qstringlist.h> +#include <qtimer.h> + + //kde includes +#include <kdebug.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmdcodec.h> +#include <kmessagebox.h> +#include <kpassdlg.h> +#include <kprocio.h> + + //app includes +#include "security.h" + +using namespace KNS; + +Security::Security() +{ + m_keysRead = false; + m_gpgRunning = false; + readKeys(); + readSecretKeys(); +} + + +Security::~Security() +{ +} + +void Security::readKeys() +{ + if (m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(readKeys())); + return; + } + m_runMode = List; + m_keys.clear(); + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys"; + connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *))); + connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *))); + if (!readProcess->start(KProcess::NotifyOnExit, true)) + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and retrieve the available keys. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>")); + else + m_gpgRunning = true; +} + +void Security::readSecretKeys() +{ + if (m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(readSecretKeys())); + return; + } + m_runMode = ListSecret; + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-secret-keys"; + connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *))); + connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *))); + if (readProcess->start(KProcess::NotifyOnExit, true)) + m_gpgRunning = true; +} + +void Security::slotProcessExited(KProcess *process) +{ + switch (m_runMode) + { + case ListSecret: + m_keysRead = true; + break; + case Verify: emit validityResult(m_result); + break; + case Sign: emit fileSigned(m_result); + break; + + } + m_gpgRunning = false; + delete process; +} + +void Security::slotDataArrived(KProcIO *procIO) +{ + QString data; + while (procIO->readln(data, true) != -1) + { + switch (m_runMode) + { + case List: + case ListSecret: + if (data.startsWith("pub") || data.startsWith("sec")) + { + KeyStruct key; + if (data.startsWith("pub")) + key.secret = false; + else + key.secret = true; + QStringList line = QStringList::split(":", data, true); + key.id = line[4]; + QString shortId = key.id.right(8); + QString trustStr = line[1]; + key.trusted = false; + if (trustStr == "u" || trustStr == "f") + key.trusted = true; + data = line[9]; + key.mail=data.section('<', -1, -1); + key.mail.truncate(key.mail.length() - 1); + key.name=data.section('<',0,0); + if (key.name.find("(")!=-1) + key.name=key.name.section('(',0,0); + m_keys[shortId] = key; + } + break; + case Verify: + data = data.section("]",1,-1).stripWhiteSpace(); + if (data.startsWith("GOODSIG")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= SIGNED_OK; + QString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("NO_PUBKEY")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= UNKNOWN; + } else + if (data.startsWith("BADSIG")) + { + m_result |= SIGNED_BAD; + QString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("TRUST_ULTIMATE")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= TRUSTED; + } + break; + + case Sign: + if (data.find("passphrase.enter") != -1) + { + QCString password; + KeyStruct key = m_keys[m_secretKey]; + int result = KPasswordDialog::getPassword(password, i18n("<qt>Enter passphrase for key <b>0x%1</b>, belonging to<br><i>%2<%3></i>:</qt>").arg(m_secretKey).arg(key.name).arg(key.mail)); + if (result == KPasswordDialog::Accepted) + { + procIO->writeStdin(password, true); + password.fill(' '); + } + else + { + m_result |= BAD_PASSPHRASE; + slotProcessExited(procIO); + return; + } + } else + if (data.find("BAD_PASSPHRASE") != -1) + { + m_result |= BAD_PASSPHRASE; + } + break; + } + } +} + +void Security::checkValidity(const QString& filename) +{ + m_fileName = filename; + slotCheckValidity(); +} + +void Security::slotCheckValidity() +{ + if (!m_keysRead || m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(slotCheckValidity())); + return; + } + if (m_keys.count() == 0) + { + emit validityResult(-1); + return; + } + + m_result = 0; + m_runMode = Verify; + QFileInfo f(m_fileName); + //check the MD5 sum + QString md5sum; + const char* c = ""; + KMD5 context(c); + QFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(file); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_ReadOnly)) + { + QString md5sum_file; + file.readLine(md5sum_file, 50); + if (!md5sum.isEmpty() && !md5sum_file.isEmpty() && md5sum_file.startsWith(md5sum)) + m_result |= MD5_OK; + file.close(); + } + m_result |= SIGNED_BAD; + m_signatureKey.id = ""; + m_signatureKey.name = ""; + m_signatureKey.mail = ""; + m_signatureKey.trusted = false; + + //verify the signature + KProcIO *verifyProcess=new KProcIO(); + *verifyProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--verify" << f.dirPath() + "/signature"<< m_fileName; + connect(verifyProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *))); + connect(verifyProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *))); + if (verifyProcess->start(KProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and check the validity of the file. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>")); + emit validityResult(0); + delete verifyProcess; + } +} + +void Security::signFile(const QString &fileName) +{ + m_fileName = fileName; + slotSignFile(); +} + +void Security::slotSignFile() +{ + if (!m_keysRead || m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(slotSignFile())); + return; + } + + QStringList secretKeys; + for (QMap<QString, KeyStruct>::Iterator it = m_keys.begin(); it != m_keys.end(); ++it) + { + if (it.data().secret) + secretKeys.append(it.key()); + } + + if (secretKeys.count() == 0) + { + emit fileSigned(-1); + return; + } + + m_result = 0; + QFileInfo f(m_fileName); + + //create the MD5 sum + QString md5sum; + const char* c = ""; + KMD5 context(c); + QFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(file); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_WriteOnly)) + { + QTextStream stream(&file); + stream << md5sum; + m_result |= MD5_OK; + file.close(); + } + + if (secretKeys.count() > 1) + { + bool ok; + secretKeys = KInputDialog::getItemList(i18n("Select Signing Key"), i18n("Key used for signing:"), secretKeys, secretKeys[0], false, &ok); + if (ok) + m_secretKey = secretKeys[0]; + else + { + emit fileSigned(0); + return; + } + } else + m_secretKey = secretKeys[0]; + + //verify the signature + KProcIO *signProcess=new KProcIO(); + *signProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--no-tty"<<"--detach-sign" << "-u" << m_secretKey << "-o" << f.dirPath() + "/signature" << m_fileName; + connect(signProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *))); + connect(signProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *))); + m_runMode = Sign; + if (signProcess->start(KProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and sign the file. Make sure that <i>gpg</i> is installed, otherwise signing of the resources will not be possible.</qt>")); + emit fileSigned(0); + delete signProcess; + } +} + +#include "security.moc" diff --git a/lib/compatibility/knewstuff/security.h b/lib/compatibility/knewstuff/security.h new file mode 100644 index 00000000..5eea64ae --- /dev/null +++ b/lib/compatibility/knewstuff/security.h @@ -0,0 +1,141 @@ +/*************************************************************************** + security.h - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia <[email protected]> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Library General Public License as * + * published by the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + + +#ifndef SECURITY_H +#define SECURITY_H + +//qt includes +#include <qmap.h> +#include <qobject.h> + +class KProcIO; +class KProcess; + +struct KeyStruct { + QString id; + QString name; + QString mail; + bool trusted; + bool secret; +}; + +/** +Handles security releated issues, like signing, verifying. +It is a private class, not meant to be used by third party applications. + +@author Andras Mantia <[email protected]> +*/ + +namespace KNS { + +class Security : public QObject +{ +Q_OBJECT +public: + static Security* const ref() + { + static Security *m_ref; + if (!m_ref) m_ref = new Security(); + return m_ref; + } + ~Security(); + + + /** Verifies the integrity and the signature of a tarball file. + * @param fileName the file to be verified. It should be a tar.gz (.tgz) file. The directory where + * the file is should contain a "signature" and a "md5sum" file, otherwise verification will fail. + * The method is asynchronous and the result is signalled with @ref validityResult. + */ + void checkValidity(const QString &fileName); + + /** Creates a signature and an md5sum file for the fileName and packs + * everything into a gzipped tarball. + * @param fileName the file with full path to sign + * + * The method is asynchronous and the result is signalled with @ref fileSigned. + */ + void signFile(const QString &fileName); + /** Get the key used for signing. This method is valid only if: + * - the checkValidity was called + * - the result of the validity check does not have the UNKNOWN bit set + * + * @return the key used for signing the file + */ + KeyStruct signatureKey() {return m_signatureKey;} + + enum Results { + MD5_OK = 1, /// The MD5 sum check is OK + SIGNED_OK = 2, /// The file is signed with a good signature + SIGNED_BAD = 4, /// The file is signed with a bad signature + TRUSTED = 8, /// The signature is trusted + UNKNOWN = 16, ///The key is unknown + SIGNED_BAD_CLEAR = 27, ///used to clear the SIGNED_BAD flag + BAD_PASSPHRASE = 32 ///wrong passhprase entered + }; + +public slots: + /** Reads the available public keys */ + void readKeys(); + /** Reads the available secret keys */ + void readSecretKeys(); + /** Verifies the integrity and the signature of a tarball file (@see m_fileName). + */ + void slotCheckValidity(); + + /** Creates a signature and an md5sum file for the @see m_fileName and packs + * everything into a gzipped tarball. + */ + void slotSignFile(); + +private: + Security(); + + enum RunMode { + List = 0, ///read the public keys + ListSecret, ///read the secret keys + Verify, ///verify the signature + Sign ///create signature + }; + + KeyStruct m_signatureKey; + int m_result; + int m_runMode; + bool m_gpgRunning; /// true if gpg is currently running + bool m_keysRead; /// true if all the keys were read + QMap<QString, KeyStruct> m_keys; /// holds information about the available key + QString m_fileName; /// the file to sign/verify + QString m_secretKey; /// the key used for signing + +private slots: + void slotProcessExited(KProcess *process); + void slotDataArrived(KProcIO *process); + +signals: + /** Sent when the validity check is done. + * + * @return the result of the check. See @ref Results + */ + void validityResult(int result); + /** Sent when the signing is done. + * + * @return the result of the operation. See @ref Results + */ + void fileSigned(int result); +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/uploaddialog.cpp b/lib/compatibility/knewstuff/uploaddialog.cpp new file mode 100644 index 00000000..5116785d --- /dev/null +++ b/lib/compatibility/knewstuff/uploaddialog.cpp @@ -0,0 +1,176 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qspinbox.h> +#include <qstring.h> +#include <ktextedit.h> + +#include <klistview.h> +#include <klocale.h> +#include <kdebug.h> +#include <kurlrequester.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kapplication.h> + +#include "engine.h" +#include "entry.h" + +#include "uploaddialog.h" +#include "uploaddialog.moc" + +using namespace KNS; + +UploadDialog::UploadDialog( Engine *engine, QWidget *parent ) : + KDialogBase( Plain, i18n("Share Hot New Stuff"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + mEntryList.setAutoDelete( true ); + + QFrame *topPage = plainPage(); + + QGridLayout *topLayout = new QGridLayout( topPage ); + topLayout->setSpacing( spacingHint() ); + + QLabel *nameLabel = new QLabel( i18n("Name:"), topPage ); + topLayout->addWidget( nameLabel, 0, 0 ); + mNameEdit = new QLineEdit( topPage ); + topLayout->addWidget( mNameEdit, 0, 1 ); + + QLabel *authorLabel = new QLabel( i18n("Author:"), topPage ); + topLayout->addWidget( authorLabel, 1, 0 ); + mAuthorEdit = new QLineEdit( topPage ); + topLayout->addWidget( mAuthorEdit, 1, 1 ); + + QLabel *versionLabel = new QLabel( i18n("Version:"), topPage ); + topLayout->addWidget( versionLabel, 2, 0 ); + mVersionEdit = new QLineEdit( topPage ); + topLayout->addWidget( mVersionEdit, 2, 1 ); + + QLabel *releaseLabel = new QLabel( i18n("Release:"), topPage ); + topLayout->addWidget( releaseLabel, 3, 0 ); + mReleaseSpin = new QSpinBox( topPage ); + mReleaseSpin->setMinValue( 1 ); + topLayout->addWidget( mReleaseSpin, 3, 1 ); + + QLabel *licenceLabel = new QLabel( i18n("License:"), topPage ); + topLayout->addWidget( licenceLabel, 4, 0 ); + mLicenceCombo = new QComboBox( topPage ); + mLicenceCombo->setEditable( true ); + mLicenceCombo->insertItem( i18n("GPL") ); + mLicenceCombo->insertItem( i18n("LGPL") ); + mLicenceCombo->insertItem( i18n("BSD") ); + topLayout->addWidget( mLicenceCombo, 4, 1 ); + + QLabel *languageLabel = new QLabel( i18n("Language:"), topPage ); + topLayout->addWidget( languageLabel, 5, 0 ); + mLanguageCombo = new QComboBox( topPage ); + topLayout->addWidget( mLanguageCombo, 5, 1 ); + mLanguageCombo->insertStringList( KGlobal::locale()->languageList() ); + + QLabel *previewLabel = new QLabel( i18n("Preview URL:"), topPage ); + topLayout->addWidget( previewLabel, 6, 0 ); + mPreviewUrl = new KURLRequester( topPage ); + topLayout->addWidget( mPreviewUrl, 6, 1 ); + + QLabel *summaryLabel = new QLabel( i18n("Summary:"), topPage ); + topLayout->addMultiCellWidget( summaryLabel, 7, 7, 0, 1 ); + mSummaryEdit = new KTextEdit( topPage ); + topLayout->addMultiCellWidget( mSummaryEdit, 8, 8, 0, 1 ); + + KConfig *conf = kapp->config(); + conf->setGroup("KNewStuffUpload"); + QString name = conf->readEntry("name"); + QString author = conf->readEntry("author"); + QString version = conf->readEntry("version"); + QString release = conf->readEntry("release"); + QString preview = conf->readEntry("preview"); + QString summary = conf->readEntry("summary"); + QString lang = conf->readEntry("language"); + QString licence = conf->readEntry("licence"); + + if(!name.isNull()) + { + int prefill = KMessageBox::questionYesNo(this, i18n("Old upload information found, fill out fields?"), QString::null, i18n("Fill Out Fields"), i18n("Do Not Fill Out")); + if(prefill == KMessageBox::Yes) + { + mNameEdit->setText(name); + mAuthorEdit->setText(author); + mVersionEdit->setText(version); + mReleaseSpin->setValue(release.toInt()); + mPreviewUrl->setURL(preview); + mSummaryEdit->setText(summary); + if(!lang.isEmpty()) mLanguageCombo->setCurrentText(lang); + if(!licence.isEmpty()) mLicenceCombo->setCurrentText(licence); + } + } +} + +UploadDialog::~UploadDialog() +{ + mEntryList.clear(); +} + +void UploadDialog::slotOk() +{ + if ( mNameEdit->text().isEmpty() ) { + KMessageBox::error( this, i18n("Please put in a name.") ); + return; + } + + Entry *entry = new Entry; + + mEntryList.append( entry ); + + entry->setName( mNameEdit->text() ); + entry->setAuthor( mAuthorEdit->text() ); + entry->setVersion( mVersionEdit->text() ); + entry->setRelease( mReleaseSpin->value() ); + entry->setLicence( mLicenceCombo->currentText() ); + entry->setPreview( KURL( mPreviewUrl->url().section("/", -1) ), mLanguageCombo->currentText() ); + entry->setSummary( mSummaryEdit->text(), mLanguageCombo->currentText() ); + + KConfig *conf = kapp->config(); + conf->setGroup("KNewStuffUpload"); + conf->writeEntry("name", mNameEdit->text()); + conf->writeEntry("author", mAuthorEdit->text()); + conf->writeEntry("version", mVersionEdit->text()); + conf->writeEntry("release", mReleaseSpin->value()); + conf->writeEntry("licence", mLicenceCombo->currentText()); + conf->writeEntry("preview", mPreviewUrl->url()); + conf->writeEntry("summary", mSummaryEdit->text()); + conf->writeEntry("language", mLanguageCombo->currentText()); + conf->sync(); + + mEngine->upload( entry ); + + accept(); +} + +void UploadDialog::setPreviewFile( const QString &previewFile ) +{ + mPreviewUrl->setURL( previewFile ); +} + diff --git a/lib/compatibility/knewstuff/uploaddialog.h b/lib/compatibility/knewstuff/uploaddialog.h new file mode 100644 index 00000000..8e962ccb --- /dev/null +++ b/lib/compatibility/knewstuff/uploaddialog.h @@ -0,0 +1,92 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef KNEWSTUFF_UPLOADDIALOG_H +#define KNEWSTUFF_UPLOADDIALOG_H + +#include <kdialogbase.h> + +class QLineEdit; +class QSpinBox; +class KURLRequester; +class QTextEdit; +class QComboBox; + +namespace KNS { + +class Engine; +class Entry; + +/** + * @short KNewStuff file upload dialog. + * + * Using this dialog, data can easily be uploaded to the Hotstuff servers. + * It should however not be used on its own, instead a KNewStuff (or + * KNewStuffGeneric) object invokes it. + * + * @author Cornelius Schumacher ([email protected]) + * \par Maintainer: + * Josef Spillner ([email protected]) + */ +class UploadDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a KNewStuff engine object to be used for uploads + @param parent the parent window + */ + UploadDialog( Engine *engine, QWidget *parent ); + + /** + Destructor. + */ + ~UploadDialog(); + + /** + Sets the preview filename. + This is only meaningful if the application supports previews. + + @param previewFile the preview image file + */ + void setPreviewFile( const QString &previewFile ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + QLineEdit *mNameEdit; + QLineEdit *mAuthorEdit; + QLineEdit *mVersionEdit; + QSpinBox *mReleaseSpin; + KURLRequester *mPreviewUrl; + QTextEdit *mSummaryEdit; + QComboBox *mLanguageCombo; + QComboBox *mLicenceCombo; + + QPtrList<Entry> mEntryList; +}; + +} + +#endif |