1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3 #include "mailinglist-magic.h"
6 #include <kconfiggroup.h>
10 #include <QStringList>
13 #include <boost/shared_ptr.hpp>
15 using namespace MessageCore
;
17 typedef QString (*MagicDetectorFunc
) (const KMime::Message::Ptr
&, QByteArray
&, QString
&);
19 /* Sender: (owner-([^@]+)|([^@+]-owner)@ */
20 static QString
check_sender( const KMime::Message::Ptr
&message
,
21 QByteArray
&header_name
,
22 QString
&header_value
)
24 QString header
= message
->sender()->asUnicodeString();
26 if ( header
.isEmpty() )
29 if ( header
.left( 6 ) == "owner-" )
31 header_name
= "Sender";
32 header_value
= header
;
33 header
= header
.mid( 6, header
.indexOf( '@' ) - 6 );
36 int index
= header
.indexOf( "-owner@ " );
40 header
.truncate( index
);
41 header_name
= "Sender";
42 header_value
= header
;
48 /* X-BeenThere: ([^@]+) */
49 static QString
check_x_beenthere( const KMime::Message::Ptr
&message
,
50 QByteArray
&header_name
,
51 QString
&header_value
)
53 QString header
= message
->headerByType( "X-BeenThere" ) ?message
->headerByType( "X-BeenThere" )->asUnicodeString() : "";
54 if ( header
.isNull() || header
.indexOf( '@' ) == -1 )
57 header_name
= "X-BeenThere";
58 header_value
= header
;
59 header
.truncate( header
.indexOf( '@' ) );
63 /* Delivered-To:: <([^@]+) */
64 static QString
check_delivered_to( const KMime::Message::Ptr
&message
,
65 QByteArray
&header_name
,
66 QString
&header_value
)
68 QString header
= message
->headerByType( "Delivered-To" ) ?message
->headerByType( "Delivered-To" )->asUnicodeString() : "";
69 if ( header
.isNull() || header
.left(13 ) != "mailing list"
70 || header
.indexOf( '@' ) == -1 )
73 header_name
= "Delivered-To";
74 header_value
= header
;
76 return header
.mid( 13, header
.indexOf( '@' ) - 13 );
79 /* X-Mailing-List: <?([^@]+) */
80 static QString
check_x_mailing_list( const KMime::Message::Ptr
&message
,
81 QByteArray
&header_name
,
82 QString
&header_value
)
84 QString header
= message
->headerByType( "X-Mailing-List" ) ?message
->headerByType( "X-Mailing-List" )->asUnicodeString() : "";
85 if ( header
.isEmpty() )
88 if ( header
.indexOf( '@' ) < 1 )
91 header_name
= "X-Mailing-List";
92 header_value
= header
;
93 if ( header
[0] == '<' )
94 header
= header
.mid(1, header
.indexOf( '@' ) - 1);
96 header
.truncate( header
.indexOf( '@' ) );
100 /* List-Id: [^<]* <([^.]+) */
101 static QString
check_list_id( const KMime::Message::Ptr
&message
,
102 QByteArray
&header_name
,
103 QString
&header_value
)
105 int lAnglePos
, firstDotPos
;
106 QString header
= message
->headerByType( "List-Id" ) ?message
->headerByType( "List-Id" )->asUnicodeString() : "";
107 if ( header
.isEmpty() )
110 lAnglePos
= header
.indexOf( '<' );
114 firstDotPos
= header
.indexOf( '.', lAnglePos
);
115 if ( firstDotPos
< 0 )
118 header_name
= "List-Id";
119 header_value
= header
.mid( lAnglePos
);
120 header
= header
.mid( lAnglePos
+ 1, firstDotPos
- lAnglePos
- 1 );
125 /* List-Post: <mailto:[^< ]*>) */
126 static QString
check_list_post( const KMime::Message::Ptr
&message
,
127 QByteArray
&header_name
,
128 QString
&header_value
)
130 QString header
= message
->headerByType( "List-Post" ) ?message
->headerByType( "List-Post" )->asUnicodeString() : "";
131 if ( header
.isEmpty() )
134 int lAnglePos
= header
.indexOf( "<mailto:" );
138 header_name
= "List-Post";
139 header_value
= header
;
140 header
= header
.mid( lAnglePos
+ 8, header
.length());
141 header
.truncate( header
.indexOf('@') );
145 /* Mailing-List: list ([^@]+) */
146 static QString
check_mailing_list( const KMime::Message::Ptr
&message
,
147 QByteArray
&header_name
,
148 QString
&header_value
)
150 QString header
= message
->headerByType( "Mailing-List" ) ?message
->headerByType( "Mailing-List" )->asUnicodeString() : "";
151 if ( header
.isEmpty() )
154 if (header
.left( 5 ) != "list " || header
.indexOf( '@' ) < 5 )
157 header_name
= "Mailing-List";
158 header_value
= header
;
159 header
= header
.mid(5, header
.indexOf( '@' ) - 5);
164 /* X-Loop: ([^@]+) */
165 static QString
check_x_loop( const KMime::Message::Ptr
&message
,
166 QByteArray
&header_name
,
167 QString
&header_value
)
169 QString header
= message
->headerByType( "X-Loop" ) ?message
->headerByType( "X-Loop" )->asUnicodeString() : "";
170 if ( header
.isEmpty() )
173 if (header
.indexOf( '@' ) < 2 )
176 header_name
= "X-Loop";
177 header_value
= header
;
178 header
.truncate(header
.indexOf( '@' ));
182 /* X-ML-Name: (.+) */
183 static QString
check_x_ml_name( const KMime::Message::Ptr
&message
,
184 QByteArray
&header_name
,
185 QString
&header_value
)
187 QString header
= message
->headerByType( "X-ML-Name" ) ?message
->headerByType( "X-ML-Name" )->asUnicodeString() : "";
188 if ( header
.isEmpty() )
191 header_name
= "X-ML-Name";
192 header_value
= header
;
193 header
.truncate(header
.indexOf( '@' ));
197 MagicDetectorFunc magic_detector
[] =
202 check_x_mailing_list
,
210 static const int num_detectors
= sizeof (magic_detector
) / sizeof (magic_detector
[0]);
213 headerToAddress( const QString
& header
)
219 if ( header
.isEmpty() )
222 while ( (start
= header
.indexOf( "<", start
)) != -1 ) {
223 if ( (end
= header
.indexOf( ">", ++start
) ) == -1 ) {
224 kDebug()<<"Serious mailing list header parsing error !";
227 //kDebug()<<"Mailing list ="<<header.mid( start, end - start );
228 addr
.append( header
.mid( start
, end
- start
) );
234 MailingList::detect( const KMime::Message::Ptr
&message
)
238 mlist
.setPostURLS( headerToAddress(
239 message
->headerByType( "List-Post" ) ? message
->headerByType( "List-Post" )->asUnicodeString() : "" ) );
240 mlist
.setHelpURLS( headerToAddress(
241 message
->headerByType( "List-Help" ) ? message
->headerByType( "List-Help" )->asUnicodeString() : "" ) );
242 mlist
.setSubscribeURLS( headerToAddress(
243 message
->headerByType( "List-Subscribe" ) ? message
->headerByType( "List-Subscribe" )->asUnicodeString() : ""));
244 mlist
.setUnsubscribeURLS( headerToAddress(
245 message
->headerByType( "List-Unsubscribe" ) ? message
->headerByType( "List-Unsubscribe" )->asUnicodeString() : ""));
246 mlist
.setArchiveURLS( headerToAddress(
247 message
->headerByType( "List-Arhive" ) ? message
->headerByType( "List-Archive" )->asUnicodeString() : "" ) );
248 mlist
.setOwnerURLS( headerToAddress(
249 message
->headerByType( "List-Owner" ) ? message
->headerByType( "List-Owner" )->asUnicodeString() : "" ) );
250 mlist
.setArchivedAt( message
->headerByType( "Archived-At" ) ? message
->headerByType( "Archived-At" )->asUnicodeString() : "" );
251 mlist
.setId( message
->headerByType( "List-Id" ) ? message
->headerByType( "List-Id" )->asUnicodeString() : "" );
257 MailingList::name( const KMime::Message::Ptr
&message
, QByteArray
&header_name
,
258 QString
&header_value
)
261 header_name
= QByteArray();
262 header_value
.clear();
267 for (int i
= 0; i
< num_detectors
; i
++) {
268 mlist
= magic_detector
[i
] (message
, header_name
, header_value
);
269 if ( !mlist
.isNull() )
276 MailingList::MailingList()
277 : mFeatures( None
), mHandler( KMail
)
281 int MailingList::features() const
286 void MailingList::setHandler( MailingList::Handler han
)
291 MailingList::Handler
MailingList::handler() const
296 void MailingList::setPostURLS ( const KUrl::List
& lst
)
305 KUrl::List
MailingList::postURLS() const
310 void MailingList::setSubscribeURLS( const KUrl::List
& lst
)
312 mFeatures
|= Subscribe
;
314 mFeatures
^= Subscribe
;
317 mSubscribeURLS
= lst
;
320 KUrl::List
MailingList::subscribeURLS() const
322 return mSubscribeURLS
;
325 void MailingList::setUnsubscribeURLS( const KUrl::List
& lst
)
327 mFeatures
|= Unsubscribe
;
329 mFeatures
^= Unsubscribe
;
332 mUnsubscribeURLS
= lst
;
335 KUrl::List
MailingList::unsubscribeURLS() const
337 return mUnsubscribeURLS
;
340 void MailingList::setHelpURLS( const KUrl::List
& lst
)
350 KUrl::List
MailingList::helpURLS() const
355 void MailingList::setArchiveURLS( const KUrl::List
& lst
)
357 mFeatures
|= Archive
;
359 mFeatures
^= Archive
;
365 KUrl::List
MailingList::archiveURLS() const
370 void MailingList::setOwnerURLS( const KUrl::List
& lst
)
380 KUrl::List
MailingList::ownerURLS() const
385 void MailingList::setArchivedAt( const QString
& str
)
387 mFeatures
|= ArchivedAt
;
388 if ( str
.isEmpty() ) {
389 mFeatures
^= ArchivedAt
;
394 QString
MailingList::archivedAt() const
399 void MailingList::setId( const QString
& str
)
402 if ( str
.isEmpty() ) {
409 QString
MailingList::id() const
414 void MailingList::writeConfig( KConfigGroup
& config
) const
416 config
.writeEntry( "MailingListFeatures", mFeatures
);
417 config
.writeEntry( "MailingListHandler", (int)mHandler
);
418 config
.writeEntry( "MailingListId", mId
);
419 config
.writeEntry( "MailingListPostingAddress", mPostURLS
.toStringList() );
420 config
.writeEntry( "MailingListSubscribeAddress", mSubscribeURLS
.toStringList() );
421 config
.writeEntry( "MailingListUnsubscribeAddress", mUnsubscribeURLS
.toStringList() );
422 config
.writeEntry( "MailingListArchiveAddress", mArchiveURLS
.toStringList() );
423 config
.writeEntry( "MailingListOwnerAddress", mOwnerURLS
.toStringList() );
424 config
.writeEntry( "MailingListHelpAddress", mHelpURLS
.toStringList() );
425 /* Note: mArchivedAt deliberately not saved here as it refers to a single
426 * instance of a message rather than an element of a general mailing list.
427 * http://reviewboard.kde.org/r/1768/#review2783
431 void MailingList::readConfig( const KConfigGroup
& config
)
433 mFeatures
= config
.readEntry( "MailingListFeatures", 0 );
434 mHandler
= static_cast<MailingList::Handler
>(
435 config
.readEntry( "MailingListHandler", (int)MailingList::KMail
) );
437 mId
= config
.readEntry("MailingListId");
438 mPostURLS
= config
.readEntry( "MailingListPostingAddress", QStringList() );
439 mSubscribeURLS
= config
.readEntry( "MailingListSubscribeAddress", QStringList() );
440 mUnsubscribeURLS
= config
.readEntry( "MailingListUnsubscribeAddress", QStringList() );
441 mArchiveURLS
= config
.readEntry( "MailingListArchiveAddress", QStringList() );
442 mOwnerURLS
= config
.readEntry( "MailingListOwnerddress", QStringList() );
443 mHelpURLS
= config
.readEntry( "MailingListHelpAddress", QStringList() );