kmail

mailinglist-magic.cpp

Go to the documentation of this file.
00001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
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 /* Sender: (owner-([^@]+)|([^@+]-owner)@ */
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 /* X-BeenThere: ([^@]+) */
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 /* Delivered-To:: <([^@]+) */
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 /* X-Mailing-List: <?([^@]+) */
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 /* List-Id: [^<]* <([^.]+) */
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 /* List-Post: <mailto:[^< ]*>) */
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 /* Mailing-List: list ([^@]+) */
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 /* X-Loop: ([^@]+) */
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 /* X-ML-Name: (.+) */
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 }