00001
00002 #ifdef HAVE_CONFIG_H
00003 #include <config.h>
00004 #endif
00005
00006 #include "mailinglist-magic.h"
00007
00008 #include "kmmessage.h"
00009
00010 #include <kconfig.h>
00011 #include <kurl.h>
00012 #include <kdebug.h>
00013
00014 #include <qstringlist.h>
00015
00016 using namespace KMail;
00017
00018 typedef QString (*MagicDetectorFunc) (const KMMessage *, QCString &, QString &);
00019
00020
00021 static QString check_sender(const KMMessage *message,
00022 QCString &header_name,
00023 QString &header_value )
00024 {
00025 QString header = message->headerField( "Sender" );
00026
00027 if ( header.isEmpty() )
00028 return QString::null;
00029
00030 if ( header.left( 6 ) == "owner-" )
00031 {
00032 header_name = "Sender";
00033 header_value = header;
00034 header = header.mid( 6, header.find( '@' ) - 6 );
00035
00036 } else {
00037 int index = header.find( "-owner@ " );
00038 if ( index == -1 )
00039 return QString::null;
00040
00041 header.truncate( index );
00042 header_name = "Sender";
00043 header_value = header;
00044 }
00045
00046 return header;
00047 }
00048
00049
00050 static QString check_x_beenthere(const KMMessage *message,
00051 QCString &header_name,
00052 QString &header_value )
00053 {
00054 QString header = message->headerField( "X-BeenThere" );
00055 if ( header.isNull() || header.find( '@' ) == -1 )
00056 return QString::null;
00057
00058 header_name = "X-BeenThere";
00059 header_value = header;
00060 header.truncate( header.find( '@' ) );
00061 return header;
00062 }
00063
00064
00065 static QString check_delivered_to(const KMMessage *message,
00066 QCString &header_name,
00067 QString &header_value )
00068 {
00069 QString header = message->headerField( "Delivered-To" );
00070 if ( header.isNull() || header.left(13 ) != "mailing list"
00071 || header.find( '@' ) == -1 )
00072 return QString::null;
00073
00074 header_name = "Delivered-To";
00075 header_value = header;
00076
00077 return header.mid( 13, header.find( '@' ) - 13 );
00078 }
00079
00080
00081 static QString check_x_mailing_list(const KMMessage *message,
00082 QCString &header_name,
00083 QString &header_value )
00084 {
00085 QString header = message->headerField( "X-Mailing-List");
00086 if ( header.isEmpty() )
00087 return QString::null;
00088
00089 if ( header.find( '@' ) < 1 )
00090 return QString::null;
00091
00092 header_name = "X-Mailing-List";
00093 header_value = header;
00094 if ( header[0] == '<' )
00095 header = header.mid(1, header.find( '@' ) - 1);
00096 else
00097 header.truncate( header.find( '@' ) );
00098 return header;
00099 }
00100
00101
00102 static QString check_list_id(const KMMessage *message,
00103 QCString &header_name,
00104 QString &header_value )
00105 {
00106 int lAnglePos, firstDotPos;
00107 QString header = message->headerField( "List-Id" );
00108 if ( header.isEmpty() )
00109 return QString::null;
00110
00111 lAnglePos = header.find( '<' );
00112 if ( lAnglePos < 0 )
00113 return QString::null;
00114
00115 firstDotPos = header.find( '.', lAnglePos );
00116 if ( firstDotPos < 0 )
00117 return QString::null;
00118
00119 header_name = "List-Id";
00120 header_value = header.mid( lAnglePos );
00121 header = header.mid( lAnglePos + 1, firstDotPos - lAnglePos - 1 );
00122 return header;
00123 }
00124
00125
00126
00127 static QString check_list_post(const KMMessage *message,
00128 QCString &header_name,
00129 QString &header_value )
00130 {
00131 QString header = message->headerField( "List-Post" );
00132 if ( header.isEmpty() )
00133 return QString::null;
00134
00135 int lAnglePos = header.find( "<mailto:" );
00136 if ( lAnglePos < 0 )
00137 return QString::null;
00138
00139 header_name = "List-Post";
00140 header_value = header;
00141 header = header.mid( lAnglePos + 8, header.length());
00142 header.truncate( header.find('@') );
00143 return header;
00144 }
00145
00146
00147 static QString check_mailing_list(const KMMessage *message,
00148 QCString &header_name,
00149 QString &header_value )
00150 {
00151 QString header = message->headerField( "Mailing-List");
00152 if ( header.isEmpty() )
00153 return QString::null;
00154
00155 if (header.left( 5 ) != "list " || header.find( '@' ) < 5 )
00156 return QString::null;
00157
00158 header_name = "Mailing-List";
00159 header_value = header;
00160 header = header.mid(5, header.find( '@' ) - 5);
00161 return header;
00162 }
00163
00164
00165
00166 static QString check_x_loop(const KMMessage *message,
00167 QCString &header_name,
00168 QString &header_value ){
00169 QString header = message->headerField( "X-Loop");
00170 if ( header.isEmpty() )
00171 return QString::null;
00172
00173 if (header.find( '@' ) < 2 )
00174 return QString::null;
00175
00176 header_name = "X-Loop";
00177 header_value = header;
00178 header.truncate(header.find( '@' ));
00179 return header;
00180 }
00181
00182
00183 static QString check_x_ml_name(const KMMessage *message,
00184 QCString &header_name,
00185 QString &header_value ){
00186 QString header = message->headerField( "X-ML-Name");
00187 if ( header.isEmpty() )
00188 return QString::null;
00189
00190 header_name = "X-ML-Name";
00191 header_value = header;
00192 header.truncate(header.find( '@' ));
00193 return header;
00194 }
00195
00196 MagicDetectorFunc magic_detector[] =
00197 {
00198 check_list_id,
00199 check_list_post,
00200 check_sender,
00201 check_x_mailing_list,
00202 check_mailing_list,
00203 check_delivered_to,
00204 check_x_beenthere,
00205 check_x_loop,
00206 check_x_ml_name
00207 };
00208
00209 static const int num_detectors = sizeof (magic_detector) / sizeof (magic_detector[0]);
00210
00211 static QStringList
00212 headerToAddress( const QString& header )
00213 {
00214 QStringList addr;
00215 int start = 0;
00216 int end = 0;
00217
00218 if ( header.isEmpty() )
00219 return addr;
00220
00221 while ( (start = header.find( "<", start )) != -1 ) {
00222 if ( (end = header.find( ">", ++start ) ) == -1 ) {
00223 kdDebug(5006)<<k_funcinfo<<"Serious mailing list header parsing error !"<<endl;
00224 return addr;
00225 }
00226 kdDebug(5006)<<"Mailing list = "<<header.mid( start, end - start )<<endl;
00227 addr.append( header.mid( start, end - start ) );
00228 }
00229 return addr;
00230 }
00231
00232 MailingList
00233 MailingList::detect( const KMMessage *message )
00234 {
00235 MailingList mlist;
00236
00237 mlist.setPostURLS( headerToAddress(
00238 message->headerField( "List-Post" ) ) );
00239 mlist.setHelpURLS( headerToAddress(
00240 message->headerField( "List-Help" ) ) );
00241 mlist.setSubscribeURLS( headerToAddress(
00242 message->headerField( "List-Subscribe" ) ) );
00243 mlist.setUnsubscribeURLS( headerToAddress(
00244 message->headerField( "List-Unsubscribe" ) ) );
00245 mlist.setArchiveURLS( headerToAddress(
00246 message->headerField( "List-Archive" ) ) );
00247 mlist.setId( message->headerField( "List-Id" ) );
00248
00249 return mlist;
00250 }
00251
00252 QString
00253 MailingList::name( const KMMessage *message, QCString &header_name,
00254 QString &header_value )
00255 {
00256 QString mlist;
00257 header_name = QCString();
00258 header_value = QString::null;
00259
00260 if ( !message )
00261 return QString::null;
00262
00263 for (int i = 0; i < num_detectors; i++) {
00264 mlist = magic_detector[i] (message, header_name, header_value);
00265 if ( !mlist.isNull() )
00266 return mlist;
00267 }
00268
00269 return QString::null;
00270 }
00271
00272 MailingList::MailingList()
00273 : mFeatures( None ), mHandler( KMail )
00274 {
00275 }
00276
00277 int
00278 MailingList::features() const
00279 {
00280 return mFeatures;
00281 }
00282
00283 void
00284 MailingList::setHandler( MailingList::Handler han )
00285 {
00286 mHandler = han;
00287 }
00288 MailingList::Handler
00289 MailingList::handler() const
00290 {
00291 return mHandler;
00292 }
00293
00294 void
00295 MailingList::setPostURLS ( const KURL::List& lst )
00296 {
00297 mFeatures |= Post;
00298 if ( lst.empty() ) {
00299 mFeatures ^= Post;
00300 }
00301 mPostURLS = lst;
00302 }
00303 KURL::List
00304 MailingList::postURLS() const
00305 {
00306 return mPostURLS;
00307 }
00308
00309 void
00310 MailingList::setSubscribeURLS( const KURL::List& lst )
00311 {
00312 mFeatures |= Subscribe;
00313 if ( lst.empty() ) {
00314 mFeatures ^= Subscribe;
00315 }
00316
00317 mSubscribeURLS = lst;
00318 }
00319 KURL::List
00320 MailingList::subscribeURLS() const
00321 {
00322 return mSubscribeURLS;
00323 }
00324
00325 void
00326 MailingList::setUnsubscribeURLS( const KURL::List& lst )
00327 {
00328 mFeatures |= Unsubscribe;
00329 if ( lst.empty() ) {
00330 mFeatures ^= Unsubscribe;
00331 }
00332
00333 mUnsubscribeURLS = lst;
00334 }
00335 KURL::List MailingList::unsubscribeURLS() const
00336 {
00337 return mUnsubscribeURLS;
00338 }
00339
00340 void
00341 MailingList::setHelpURLS( const KURL::List& lst )
00342 {
00343 mFeatures |= Help;
00344 if ( lst.empty() ) {
00345 mFeatures ^= Help;
00346 }
00347
00348 mHelpURLS = lst;
00349 }
00350 KURL::List
00351 MailingList::helpURLS() const
00352 {
00353 return mHelpURLS;
00354 }
00355
00356 void
00357 MailingList::setArchiveURLS( const KURL::List& lst )
00358 {
00359 mFeatures |= Archive;
00360 if ( lst.empty() ) {
00361 mFeatures ^= Archive;
00362 }
00363
00364 mArchiveURLS = lst;
00365 }
00366 KURL::List
00367 MailingList::archiveURLS() const
00368 {
00369 return mArchiveURLS;
00370 }
00371
00372 void
00373 MailingList::setId( const QString& str )
00374 {
00375 mFeatures |= Id;
00376 if ( str.isEmpty() ) {
00377 mFeatures ^= Id;
00378 }
00379
00380 mId = str;
00381 }
00382 QString
00383 MailingList::id() const
00384 {
00385 return mId;
00386 }
00387
00388 void
00389 MailingList::writeConfig( KConfig* config ) const
00390 {
00391 config->writeEntry( "MailingListFeatures", mFeatures );
00392 config->writeEntry( "MailingListHandler", mHandler );
00393 config->writeEntry( "MailingListId", mId );
00394 config->writeEntry( "MailingListPostingAddress", mPostURLS.toStringList() );
00395 config->writeEntry( "MailingListSubscribeAddress", mSubscribeURLS.toStringList() );
00396 config->writeEntry( "MailingListUnsubscribeAddress", mUnsubscribeURLS.toStringList() );
00397 config->writeEntry( "MailingListArchiveAddress", mArchiveURLS.toStringList() );
00398 config->writeEntry( "MailingListHelpAddress", mHelpURLS.toStringList() );
00399 }
00400
00401 void
00402 MailingList::readConfig( KConfig* config )
00403 {
00404 mFeatures = config->readNumEntry( "MailingListFeatures", 0 );
00405 mHandler = static_cast<MailingList::Handler>(
00406 config->readNumEntry( "MailingListHandler", MailingList::KMail ) );
00407
00408 mId = config->readEntry("MailingListId");
00409 mPostURLS = config->readListEntry( "MailingListPostingAddress" );
00410 mSubscribeURLS = config->readListEntry( "MailingListSubscribeAddress" );
00411 mUnsubscribeURLS = config->readListEntry( "MailingListUnsubscribeAddress" );
00412 mArchiveURLS = config->readListEntry( "MailingListArchiveAddress" );
00413 mHelpURLS = config->readListEntry( "MailingListHelpAddress" );
00414 }