Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F16569264
nntpresource.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
nntpresource.cpp
View Options
/*
Copyright (c) 2007 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
"nntpresource.h"
#include
"nntpcollectionattribute.h"
#include
"configdialog.h"
#include
"settings.h"
#include
"settingsadaptor.h"
#include
<attributefactory.h>
#include
<cachepolicy.h>
#include
<collectionmodifyjob.h>
#include
<itemcreatejob.h>
#include
<akonadi/kmime/messageparts.h>
#include
<monitor.h>
#include
<session.h>
#include
<changerecorder.h>
#include
<kmime/kmime_message.h>
#include
<kmime/kmime_newsarticle.h>
#include
<kmime/kmime_util.h>
#include
<KWindowSystem>
#include
<KLocalizedString>
#include
<KIcon>
#include
<QDateTime>
#include
<QDir>
#include
<QInputDialog>
#include
<QLineEdit>
#include
<boost/shared_ptr.hpp>
typedef
boost
::
shared_ptr
<
KMime
::
Message
>
MessagePtr
;
using
namespace
Akonadi
;
NntpResource
::
NntpResource
(
const
QString
&
id
)
:
ResourceBase
(
id
)
{
AttributeFactory
::
registerAttribute
<
NntpCollectionAttribute
>
();
changeRecorder
()
->
fetchCollection
(
true
);
new
SettingsAdaptor
(
Settings
::
self
()
);
QDBusConnection
::
sessionBus
().
registerObject
(
QLatin1String
(
"/Settings"
),
Settings
::
self
(),
QDBusConnection
::
ExportAdaptors
);
}
NntpResource
::~
NntpResource
()
{
}
bool
NntpResource
::
retrieveItem
(
const
Akonadi
::
Item
&
item
,
const
QSet
<
QByteArray
>
&
parts
)
{
Q_UNUSED
(
parts
);
KIO
::
Job
*
job
=
KIO
::
storedGet
(
KUrl
(
item
.
remoteId
()
),
KIO
::
NoReload
,
KIO
::
HideProgressInfo
);
setupKioJob
(
job
);
connect
(
job
,
SIGNAL
(
result
(
KJob
*
)),
SLOT
(
fetchArticleResult
(
KJob
*
))
);
return
true
;
}
void
NntpResource
::
retrieveCollections
()
{
remoteCollections
.
clear
();
Collection
rootCollection
;
rootCollection
.
setParentCollection
(
Collection
::
root
()
);
rootCollection
.
setRemoteId
(
baseUrl
().
url
()
);
rootCollection
.
setName
(
Settings
::
self
()
->
name
()
);
CachePolicy
policy
;
policy
.
setInheritFromParent
(
false
);
policy
.
setSyncOnDemand
(
true
);
policy
.
setLocalParts
(
QStringList
(
MessagePart
::
Envelope
)
);
rootCollection
.
setCachePolicy
(
policy
);
QStringList
contentTypes
;
contentTypes
<<
Collection
::
mimeType
();
rootCollection
.
setContentMimeTypes
(
contentTypes
);
remoteCollections
<<
rootCollection
;
KUrl
url
=
baseUrl
();
QDate
lastList
=
Settings
::
self
()
->
lastGroupList
().
date
();
if
(
lastList
.
isValid
()
)
{
mIncremental
=
true
;
url
.
addQueryItem
(
"since"
,
QString
(
"%1%2%3 000000"
)
.
arg
(
lastList
.
year
()
%
100
,
2
,
10
,
QChar
(
'0'
)
)
.
arg
(
lastList
.
month
(),
2
,
10
,
QChar
(
'0'
)
)
.
arg
(
lastList
.
day
(),
2
,
10
,
QChar
(
'0'
)
)
);
}
else
{
mIncremental
=
false
;
}
KIO
::
ListJob
*
job
=
KIO
::
listDir
(
url
,
KIO
::
HideProgressInfo
,
true
);
setupKioJob
(
job
);
connect
(
job
,
SIGNAL
(
entries
(
KIO
::
Job
*
,
KIO
::
UDSEntryList
)),
SLOT
(
listGroups
(
KIO
::
Job
*
,
KIO
::
UDSEntryList
))
);
connect
(
job
,
SIGNAL
(
result
(
KJob
*
)),
SLOT
(
listGroupsResult
(
KJob
*
))
);
}
void
NntpResource
::
retrieveItems
(
const
Akonadi
::
Collection
&
col
)
{
if
(
!
(
col
.
contentMimeTypes
().
count
()
==
1
&&
col
.
contentMimeTypes
().
first
()
==
"message/news"
)
)
{
// not a newsgroup, skip it
itemsRetrievalDone
();
return
;
}
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"
,
QString
::
number
(
Settings
::
self
()
->
maxDownload
()
)
);
KIO
::
ListJob
*
job
=
KIO
::
listDir
(
url
,
KIO
::
HideProgressInfo
,
true
);
setupKioJob
(
job
);
connect
(
job
,
SIGNAL
(
entries
(
KIO
::
Job
*
,
KIO
::
UDSEntryList
)),
SLOT
(
listGroup
(
KIO
::
Job
*
,
KIO
::
UDSEntryList
))
);
connect
(
job
,
SIGNAL
(
result
(
KJob
*
)),
SLOT
(
listGroupResult
(
KJob
*
))
);
}
void
NntpResource
::
listGroups
(
KIO
::
Job
*
job
,
const
KIO
::
UDSEntryList
&
list
)
{
Q_UNUSED
(
job
);
QString
name
;
QStringList
contentTypes
;
contentTypes
<<
"message/news"
;
for
(
KIO
::
UDSEntryList
::
ConstIterator
it
=
list
.
constBegin
();
it
!=
list
.
constEnd
();
++
it
)
{
name
=
(
*
it
).
stringValue
(
KIO
::
UDSEntry
::
UDS_NAME
);
if
(
name
.
isEmpty
()
)
continue
;
Collection
c
;
c
.
setRemoteId
(
name
);
c
.
setContentMimeTypes
(
contentTypes
);
if
(
Settings
::
self
()
->
flatHierarchy
()
)
{
c
.
setName
(
name
);
c
.
parentCollection
().
setRemoteId
(
baseUrl
().
url
()
);
}
else
{
const
QStringList
path
=
name
.
split
(
'.'
);
Q_ASSERT
(
!
path
.
isEmpty
()
);
c
.
setName
(
path
.
last
()
);
c
.
parentCollection
().
setRemoteId
(
findParent
(
path
)
);
}
remoteCollections
<<
c
;
}
}
void
NntpResource
::
listGroupsResult
(
KJob
*
job
)
{
if
(
job
->
error
()
)
{
emit
error
(
job
->
errorString
()
);
return
;
}
else
{
Settings
::
self
()
->
setLastGroupList
(
QDateTime
::
currentDateTime
()
);
}
if
(
mIncremental
)
collectionsRetrievedIncremental
(
remoteCollections
,
Collection
::
List
()
);
else
collectionsRetrieved
(
remoteCollections
);
}
void
NntpResource
::
listGroup
(
KIO
::
Job
*
job
,
const
KIO
::
UDSEntryList
&
list
)
{
Q_UNUSED
(
job
);
foreach
(
const
KIO
::
UDSEntry
&
entry
,
list
)
{
KUrl
url
=
baseUrl
();
url
.
setPath
(
currentCollection
().
remoteId
()
+
'/'
+
entry
.
stringValue
(
KIO
::
UDSEntry
::
UDS_NAME
)
);
Item
item
;
item
.
setRemoteId
(
url
.
url
()
);
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
()
)
);
}
}
}
item
.
setPayload
(
MessagePtr
(
art
)
);
ItemCreateJob
*
append
=
new
ItemCreateJob
(
item
,
currentCollection
()
);
// TODO: check error
Q_UNUSED
(
append
)
}
}
void
NntpResource
::
listGroupResult
(
KJob
*
job
)
{
if
(
job
->
error
()
)
{
emit
error
(
job
->
errorString
()
);
}
else
{
// store last serial number
Collection
col
=
currentCollection
();
NntpCollectionAttribute
*
attr
=
col
.
attribute
<
NntpCollectionAttribute
>
(
Collection
::
AddIfMissing
);
KIO
::
Job
*
j
=
static_cast
<
KIO
::
Job
*>
(
job
);
if
(
j
->
metaData
().
contains
(
"LastSerialNumber"
)
)
attr
->
setLastArticle
(
j
->
metaData
().
value
(
"LastSerialNumber"
).
toInt
()
);
CollectionModifyJob
*
modify
=
new
CollectionModifyJob
(
col
);
// TODO: check result signal
Q_UNUSED
(
modify
)
}
itemsRetrievalDone
();
}
KUrl
NntpResource
::
baseUrl
()
const
{
KUrl
url
;
if
(
Settings
::
self
()
->
encryption
()
==
Settings
::
SSL
)
url
.
setProtocol
(
"nntps"
);
else
url
.
setProtocol
(
"nntp"
);
url
.
setHost
(
Settings
::
self
()
->
server
()
);
url
.
setPort
(
Settings
::
self
()
->
port
()
);
if
(
Settings
::
self
()
->
requiresAuthentication
()
)
{
url
.
setUser
(
Settings
::
self
()
->
userName
()
);
url
.
setPass
(
Settings
::
self
()
->
password
()
);
}
return
url
;
}
void
NntpResource
::
fetchArticleResult
(
KJob
*
job
)
{
if
(
job
->
error
()
)
{
emit
error
(
job
->
errorString
()
);
return
;
}
KIO
::
StoredTransferJob
*
j
=
static_cast
<
KIO
::
StoredTransferJob
*>
(
job
);
KMime
::
Message
*
msg
=
new
KMime
::
Message
();
msg
->
setContent
(
KMime
::
CRLFtoLF
(
j
->
data
()
)
);
msg
->
parse
();
Item
item
=
currentItem
();
item
.
setMimeType
(
"message/news"
);
item
.
setPayload
(
MessagePtr
(
msg
)
);
itemRetrieved
(
item
);
}
void
NntpResource
::
configure
(
WId
windowId
)
{
ConfigDialog
dlg
;
if
(
windowId
)
{
KWindowSystem
::
setMainWindow
(
&
dlg
,
windowId
);
}
dlg
.
setWindowIcon
(
KIcon
(
"message-news"
)
);
if
(
dlg
.
exec
()
)
{
emit
configurationDialogAccepted
();
}
else
{
emit
configurationDialogRejected
();
}
if
(
!
Settings
::
self
()
->
name
().
isEmpty
()
)
setName
(
Settings
::
self
()
->
name
()
);
}
void
NntpResource
::
setupKioJob
(
KIO
::
Job
*
job
)
const
{
Q_ASSERT
(
job
);
if
(
Settings
::
self
()
->
encryption
()
==
Settings
::
TLS
)
job
->
addMetaData
(
"tls"
,
"on"
);
else
job
->
addMetaData
(
"tls"
,
"off"
);
// TODO connect percent and status message signals to something
}
QString
NntpResource
::
findParent
(
const
QStringList
&
_path
)
{
QStringList
path
=
_path
;
path
.
removeLast
();
if
(
path
.
isEmpty
()
)
return
baseUrl
().
url
();
QString
rid
=
path
.
join
(
"."
);
foreach
(
const
Collection
&
col
,
remoteCollections
)
if
(
col
.
remoteId
()
==
rid
)
return
col
.
remoteId
();
Collection
parent
;
parent
.
setRemoteId
(
rid
);
QStringList
ct
;
ct
<<
Collection
::
mimeType
();
parent
.
setContentMimeTypes
(
ct
);
parent
.
parentCollection
().
setRemoteId
(
findParent
(
path
)
);
parent
.
setName
(
path
.
last
()
);
remoteCollections
<<
parent
;
return
parent
.
remoteId
();
}
void
NntpResource
::
collectionChanged
(
const
Akonadi
::
Collection
&
collection
)
{
if
(
collection
.
remoteId
()
==
baseUrl
().
url
()
&&
!
collection
.
name
().
isEmpty
()
)
{
Settings
::
self
()
->
setName
(
collection
.
name
()
);
setName
(
collection
.
name
()
);
}
changeCommitted
(
collection
);
}
AKONADI_RESOURCE_MAIN
(
NntpResource
)
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Fri, Nov 1, 8:19 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10074903
Default Alt Text
nntpresource.cpp (10 KB)
Attached To
Mode
rKPR kdepim-runtime
Attached
Detach File
Event Timeline
Log In to Comment