Make it possible to use a distinct selection model in the foldertreewidget.
[kdepim.git] / messagecore / mailinglist-magic.cpp
blob411954a5ae3cdb863168f3c31fab956f0b41e0e8
1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3 #include "mailinglist-magic.h"
5 #include <kconfig.h>
6 #include <kconfiggroup.h>
7 #include <kurl.h>
8 #include <kdebug.h>
10 #include <QStringList>
11 #include <QByteArray>
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() )
27 return QString();
29 if ( header.left( 6 ) == "owner-" )
31 header_name = "Sender";
32 header_value = header;
33 header = header.mid( 6, header.indexOf( '@' ) - 6 );
35 } else {
36 int index = header.indexOf( "-owner@ " );
37 if ( index == -1 )
38 return QString();
40 header.truncate( index );
41 header_name = "Sender";
42 header_value = header;
45 return 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 )
55 return QString();
57 header_name = "X-BeenThere";
58 header_value = header;
59 header.truncate( header.indexOf( '@' ) );
60 return header;
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 )
71 return QString();
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() )
86 return QString();
88 if ( header.indexOf( '@' ) < 1 )
89 return QString();
91 header_name = "X-Mailing-List";
92 header_value = header;
93 if ( header[0] == '<' )
94 header = header.mid(1, header.indexOf( '@' ) - 1);
95 else
96 header.truncate( header.indexOf( '@' ) );
97 return header;
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() )
108 return QString();
110 lAnglePos = header.indexOf( '<' );
111 if ( lAnglePos < 0 )
112 return QString();
114 firstDotPos = header.indexOf( '.', lAnglePos );
115 if ( firstDotPos < 0 )
116 return QString();
118 header_name = "List-Id";
119 header_value = header.mid( lAnglePos );
120 header = header.mid( lAnglePos + 1, firstDotPos - lAnglePos - 1 );
121 return header;
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() )
132 return QString();
134 int lAnglePos = header.indexOf( "<mailto:" );
135 if ( lAnglePos < 0 )
136 return QString();
138 header_name = "List-Post";
139 header_value = header;
140 header = header.mid( lAnglePos + 8, header.length());
141 header.truncate( header.indexOf('@') );
142 return header;
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() )
152 return QString();
154 if (header.left( 5 ) != "list " || header.indexOf( '@' ) < 5 )
155 return QString();
157 header_name = "Mailing-List";
158 header_value = header;
159 header = header.mid(5, header.indexOf( '@' ) - 5);
160 return header;
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() )
171 return QString();
173 if (header.indexOf( '@' ) < 2 )
174 return QString();
176 header_name = "X-Loop";
177 header_value = header;
178 header.truncate(header.indexOf( '@' ));
179 return header;
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() )
189 return QString();
191 header_name = "X-ML-Name";
192 header_value = header;
193 header.truncate(header.indexOf( '@' ));
194 return header;
197 MagicDetectorFunc magic_detector[] =
199 check_list_id,
200 check_list_post,
201 check_sender,
202 check_x_mailing_list,
203 check_mailing_list,
204 check_delivered_to,
205 check_x_beenthere,
206 check_x_loop,
207 check_x_ml_name
210 static const int num_detectors = sizeof (magic_detector) / sizeof (magic_detector[0]);
212 static QStringList
213 headerToAddress( const QString& header )
215 QStringList addr;
216 int start = 0;
217 int end = 0;
219 if ( header.isEmpty() )
220 return addr;
222 while ( (start = header.indexOf( "<", start )) != -1 ) {
223 if ( (end = header.indexOf( ">", ++start ) ) == -1 ) {
224 kDebug()<<"Serious mailing list header parsing error !";
225 return addr;
227 //kDebug()<<"Mailing list ="<<header.mid( start, end - start );
228 addr.append( header.mid( start, end - start ) );
230 return addr;
233 MailingList
234 MailingList::detect( const KMime::Message::Ptr &message )
236 MailingList mlist;
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() : "" );
253 return mlist;
256 QString
257 MailingList::name( const KMime::Message::Ptr &message, QByteArray &header_name,
258 QString &header_value )
260 QString mlist;
261 header_name = QByteArray();
262 header_value.clear();
264 if ( !message )
265 return QString();
267 for (int i = 0; i < num_detectors; i++) {
268 mlist = magic_detector[i] (message, header_name, header_value);
269 if ( !mlist.isNull() )
270 return mlist;
273 return QString();
276 MailingList::MailingList()
277 : mFeatures( None ), mHandler( KMail )
281 int MailingList::features() const
283 return mFeatures;
286 void MailingList::setHandler( MailingList::Handler han )
288 mHandler = han;
291 MailingList::Handler MailingList::handler() const
293 return mHandler;
296 void MailingList::setPostURLS ( const KUrl::List& lst )
298 mFeatures |= Post;
299 if ( lst.empty() ) {
300 mFeatures ^= Post;
302 mPostURLS = lst;
305 KUrl::List MailingList::postURLS() const
307 return mPostURLS;
310 void MailingList::setSubscribeURLS( const KUrl::List& lst )
312 mFeatures |= Subscribe;
313 if ( lst.empty() ) {
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;
328 if ( lst.empty() ) {
329 mFeatures ^= Unsubscribe;
332 mUnsubscribeURLS = lst;
335 KUrl::List MailingList::unsubscribeURLS() const
337 return mUnsubscribeURLS;
340 void MailingList::setHelpURLS( const KUrl::List& lst )
342 mFeatures |= Help;
343 if ( lst.empty() ) {
344 mFeatures ^= Help;
347 mHelpURLS = lst;
350 KUrl::List MailingList::helpURLS() const
352 return mHelpURLS;
355 void MailingList::setArchiveURLS( const KUrl::List& lst )
357 mFeatures |= Archive;
358 if ( lst.empty() ) {
359 mFeatures ^= Archive;
362 mArchiveURLS = lst;
365 KUrl::List MailingList::archiveURLS() const
367 return mArchiveURLS;
370 void MailingList::setOwnerURLS( const KUrl::List& lst )
372 mFeatures |= Owner;
373 if ( lst.empty() ) {
374 mFeatures ^= Owner;
377 mOwnerURLS = lst;
380 KUrl::List MailingList::ownerURLS() const
382 return mOwnerURLS;
385 void MailingList::setArchivedAt( const QString& str )
387 mFeatures |= ArchivedAt;
388 if ( str.isEmpty() ) {
389 mFeatures ^= ArchivedAt;
392 mArchivedAt = str;
394 QString MailingList::archivedAt() const
396 return mArchivedAt;
399 void MailingList::setId( const QString& str )
401 mFeatures |= Id;
402 if ( str.isEmpty() ) {
403 mFeatures ^= Id;
406 mId = str;
409 QString MailingList::id() const
411 return mId;
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() );