Commit 04aaef46 authored by Volker Krause's avatar Volker Krause
Browse files

Some new NNTP resource features:

- encryption and authentication
- config dialog
- envelope fetching

svn path=/trunk/KDE/kdepim/akonadi/; revision=757572
parent 73fa1c73
......@@ -178,7 +178,8 @@ QStringList SerializerPluginMail::parts(const Item & item) const
return QStringList();
MessagePtr msg = item.payload<MessagePtr>();
QStringList list;
if ( msg->hasContent() ) {
// FIXME: we actually want "has any header" here, but the kmime api doesn't offer that yet
if ( msg->hasContent() || msg->hasHeader( "Message-ID" ) ) {
list << Item::PartEnvelope << Item::PartHeader;
if ( !msg->body().isEmpty() || !msg->contents().isEmpty() )
list << Item::PartBody;
......
......@@ -8,6 +8,8 @@ include_directories(
set( nntpresource_SRCS
nntpcollectionattribute.cpp
nntpresource.cpp
configdialog.cpp
settings.cpp
main.cpp
)
......@@ -15,7 +17,8 @@ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" )
install( FILES nntpresource.desktop DESTINATION "${CMAKE_INSTALL_PREFIX}/share/akonadi/agents" )
kde4_add_ui_files(nntpresource_SRCS configdialog.ui)
kde4_add_kcfg_files(nntpresource_SRCS settingsbase.kcfgc)
kde4_add_executable(akonadi_nntp_resource RUN_UNINSTALLED ${nntpresource_SRCS})
target_link_libraries(akonadi_nntp_resource akonadi ${QT_QTCORE_LIBRARIES} ${QT_QTDBUS_LIBRARIES} ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBRARY} ${KDE4_KMIME_LIBS})
......
/*
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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 "configdialog.h"
#include "settings.h"
#include <kconfigdialogmanager.h>
ConfigDialog::ConfigDialog(QWidget * parent) :
KDialog( parent )
{
ui.setupUi( mainWidget() );
mManager = new KConfigDialogManager( this, Settings::self() );
mManager->updateWidgets();
ui.password->setText( Settings::self()->password() );
connect( this, SIGNAL(okClicked()), SLOT(save()) );
}
void ConfigDialog::save()
{
if ( ui.kcfg_StorePassword->isChecked() )
Settings::self()->setPassword( ui.password->text() );
mManager->updateSettings();
}
#include "configdialog.moc"
/*
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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 CONFIGDIALOG_H
#define CONFIGDIALOG_H
#include <kdialog.h>
#include "ui_configdialog.h"
class KConfigDialogManager;
class ConfigDialog : public KDialog
{
Q_OBJECT
public:
ConfigDialog( QWidget *parent = 0 );
private slots:
void save();
private:
Ui::ConfigDialog ui;
KConfigDialogManager* mManager;
};
#endif
<ui version="4.0" >
<author>Volker Krause &lt;vkrause@kde.org></author>
<class>ConfigDialog</class>
<widget class="QWidget" name="ConfigDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>513</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QTabWidget" name="tabWidget" >
<property name="enabled" >
<bool>true</bool>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<string>General</string>
</attribute>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>&amp;Name:</string>
</property>
<property name="buddy" >
<cstring>kcfg_Name</cstring>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2" >
<widget class="KLineEdit" name="kcfg_Name" />
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>&amp;Server:</string>
</property>
<property name="buddy" >
<cstring>kcfg_Server</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2" >
<widget class="KLineEdit" name="kcfg_Server" />
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>Port:</string>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="KIntNumInput" name="kcfg_Port" />
</item>
<item row="2" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>181</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="3" >
<widget class="KButtonGroup" name="kcfg_Encryption" >
<property name="title" >
<string>Encryption</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" colspan="2" >
<layout class="QHBoxLayout" >
<item>
<widget class="QRadioButton" name="radioButton" >
<property name="text" >
<string>&amp;None</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_2" >
<property name="text" >
<string>&amp;SSL</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_3" >
<property name="text" >
<string>&amp;TLS</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>191</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" >
<widget class="KPushButton" name="checkServerButton" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>&amp;Check server</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0" colspan="3" >
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Authentication</string>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" colspan="2" >
<widget class="QCheckBox" name="kcfg_RequiresAuthentication" >
<property name="text" >
<string>Server requires authentication</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_5" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>&amp;Username:</string>
</property>
<property name="buddy" >
<cstring>kcfg_UserName</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="KLineEdit" name="kcfg_UserName" >
<property name="enabled" >
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_4" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>&amp;Password:</string>
</property>
<property name="buddy" >
<cstring>password</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="KLineEdit" name="password" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="passwordMode" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QCheckBox" name="kcfg_StorePassword" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>Store password in KWallet</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="1" colspan="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>317</width>
<height>41</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2" >
<attribute name="title" >
<string>Advanced</string>
</attribute>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>Download at most:</string>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="KIntNumInput" name="kcfg_MaxDownload" >
<property name="minimum" >
<number>1</number>
</property>
<property name="suffix" >
<string> articles</string>
</property>
</widget>
</item>
<item row="0" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KButtonGroup</class>
<extends>QGroupBox</extends>
<header>kbuttongroup.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KIntNumInput</class>
<extends>QWidget</extends>
<header>knuminput.h</header>
</customwidget>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
<customwidget>
<class>KPushButton</class>
<extends>QPushButton</extends>
<header>kpushbutton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>kcfg_RequiresAuthentication</sender>
<signal>toggled(bool)</signal>
<receiver>kcfg_UserName</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>83</x>
<y>196</y>
</hint>
<hint type="destinationlabel" >
<x>127</x>
<y>227</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_RequiresAuthentication</sender>
<signal>toggled(bool)</signal>
<receiver>password</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>59</x>
<y>206</y>
</hint>
<hint type="destinationlabel" >
<x>105</x>
<y>269</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_RequiresAuthentication</sender>
<signal>toggled(bool)</signal>
<receiver>label_5</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>48</x>
<y>213</y>
</hint>
<hint type="destinationlabel" >
<x>46</x>
<y>232</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_RequiresAuthentication</sender>
<signal>toggled(bool)</signal>
<receiver>label_4</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>140</x>
<y>201</y>
</hint>
<hint type="destinationlabel" >
<x>83</x>
<y>265</y>
</hint>
</hints>
</connection>
<connection>
<sender>kcfg_RequiresAuthentication</sender>
<signal>toggled(bool)</signal>
<receiver>kcfg_StorePassword</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>232</x>
<y>209</y>
</hint>
<hint type="destinationlabel" >
<x>242</x>
<y>305</y>
</hint>
</hints>
</connection>
</connections>
</ui>
......@@ -19,6 +19,8 @@
#include "nntpresource.h"
#include "nntpcollectionattribute.h"
#include "configdialog.h"
#include "settings.h"
#include <libakonadi/collectionattributefactory.h>
#include <libakonadi/collectionmodifyjob.h>
......@@ -27,6 +29,7 @@
#include <libakonadi/session.h>
#include <kmime/kmime_message.h>
#include <kmime/kmime_newsarticle.h>
#include <kmime/kmime_util.h>
#include <QDate>
......@@ -43,8 +46,6 @@ NntpResource::NntpResource(const QString & id)
: ResourceBase( id )
{
CollectionAttributeFactory::registerAttribute<NntpCollectionAttribute>();
mConfig = settings()->value( "General/Url", QString("nntp://localhost/") ).toString();
}
NntpResource::~ NntpResource()
......@@ -55,6 +56,7 @@ bool NntpResource::retrieveItem(const Akonadi::Item& item, const QStringList &pa
{
Q_UNUSED( parts );
KIO::Job* job = KIO::storedGet( KUrl( item.reference().remoteId() ), KIO::NoReload, KIO::HideProgressInfo );
setupKioJob( job );
connect( job, SIGNAL( result(KJob*) ), SLOT( fetchArticleResult(KJob*) ) );
return true;
}
......@@ -64,7 +66,7 @@ void NntpResource::retrieveCollections()
remoteCollections.clear();
Collection rootCollection;
rootCollection.setParent( Collection::root() );
rootCollection.setRemoteId( baseUrl() );
rootCollection.setRemoteId( baseUrl().url() );
rootCollection.setName( name() );
rootCollection.setCachePolicyId( 1 );
QStringList contentTypes;
......@@ -72,7 +74,7 @@ void NntpResource::retrieveCollections()
rootCollection.setContentTypes( contentTypes );
remoteCollections << rootCollection;
KUrl url = KUrl( baseUrl() );
KUrl url = baseUrl();
QDate lastList = settings()->value( "General/LastGroupList" ).toDate();
if ( lastList.isValid() ) {
mIncremental = true;
......@@ -85,6 +87,7 @@ void NntpResource::retrieveCollections()
}
KIO::Job* job = KIO::listDir( url, KIO::HideProgressInfo, true );
setupKioJob( job );
connect( job, SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList&)),
SLOT(listGroups(KIO::Job*, const KIO::UDSEntryList&)) );
connect( job, SIGNAL( result(KJob*) ), SLOT( listGroupsResult(KJob*) ) );
......@@ -93,16 +96,17 @@ void NntpResource::retrieveCollections()
void NntpResource::retrieveItems(const Akonadi::Collection & col, const QStringList &parts)
{
Q_UNUSED( parts );
KUrl url = KUrl( baseUrl() );
KUrl url = baseUrl();
url.setPath( col.remoteId() );
NntpCollectionAttribute *attr = col.attribute<NntpCollectionAttribute>();
if ( attr && attr->lastArticle() > 0 )
url.addQueryItem( "first", QString::number( attr->lastArticle() + 1 ) );
else
url.addQueryItem( "max", "5" );
url.addQueryItem( "max", QString::number( Settings::self()->maxDownload() ) );
KIO::Job* job = KIO::listDir( url, KIO::HideProgressInfo, true );
setupKioJob( job );
connect( job, SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList&)),
SLOT(listGroup(KIO::Job*, const KIO::UDSEntryList&)) );
connect( job, SIGNAL( result(KJob*) ), SLOT( listGroupResult(KJob*) ) );
......@@ -122,7 +126,7 @@ void NntpResource::listGroups(KIO::Job * job, const KIO::UDSEntryList & list)
Collection c;
c.setName( name );
c.setRemoteId( name );
c.setParentRemoteId( baseUrl() );
c.setParentRemoteId( baseUrl().url() );
c.setContentTypes( contentTypes );
remoteCollections << c;
......@@ -147,10 +151,47 @@ void NntpResource::listGroup(KIO::Job * job, const KIO::UDSEntryList & list)
{
Q_UNUSED( job );
foreach ( const KIO::UDSEntry &entry, list ) {
DataReference ref( -1, baseUrl() + currentCollection().remoteId() + QDir::separator() + entry.stringValue( KIO::UDSEntry::UDS_NAME ) );
KUrl url = baseUrl();
url.setPath( currentCollection().remoteId() + "/" + entry.stringValue( KIO::UDSEntry::UDS_NAME ) );
DataReference ref( -1, url.url() );
Item item( ref );
item.setMimeType( "message/news" );
KMime::NewsArticle *art = new KMime::NewsArticle();
foreach ( uint field, entry.listFields() ) {
if ( field >= KIO::UDSEntry::UDS_EXTRA && field <= KIO::UDSEntry::UDS_EXTRA_END ) {
const QString value = entry.stringValue( field );
int pos = value.indexOf( ':' );
if ( pos >= value.length() - 1 )
continue; // value is empty
const QString hdrName = value.left( pos );
const QString hdrValue = value.right( value.length() - ( hdrName.length() + 2 ) );
if ( hdrName == "Subject" ) {
art->subject()->from7BitString( hdrValue.toLatin1() );
if ( art->subject()->isEmpty() )
art->subject()->fromUnicodeString( i18n("no subject"), art->defaultCharset() );
} else if ( hdrName == "From" ) {
art->from()->from7BitString( hdrValue.toLatin1() );
} else if ( hdrName == "Date" ) {
art->date()->from7BitString( hdrValue.toLatin1() );
} else if ( hdrName == "Message-ID" ) {
art->messageID()->from7BitString( hdrValue.simplified().toLatin1() );
} else if ( hdrName == "References" ) {
if( !hdrValue.isEmpty() )
art->references()->from7BitString( hdrValue.toLatin1() );
} else if ( hdrName == "Lines" ) {
art->lines()->setNumberOfLines( hdrValue.toInt() );
} else {
// optional extra headers
art->setHeader( new KMime::Headers::Generic( hdrName.toLatin1(), art, hdrValue.toLatin1() ) );