libkdepim Library API Documentation

email.cpp

00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002 
00003     This file is part of kdepim.
00004     Copyright (c) 2004 KDEPIM developers
00005 
00006     KMail is free software; you can redistribute it and/or modify it
00007     under the terms of the GNU General Public License, version 2, as
00008     published by the Free Software Foundation.
00009 
00010     KMail is distributed in the hope that it will be useful, but
00011     WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019     In addition, as a special exception, the copyright holders give
00020     permission to link the code of this program with any edition of
00021     the Qt library by Trolltech AS, Norway (or with modified versions
00022     of Qt that use the same license as Qt), and distribute linked
00023     combinations including the two.  You must obey the GNU General
00024     Public License in all respects for all of the code used other than
00025     Qt.  If you modify this file, you may extend this exception to
00026     your version of the file, but you are not obligated to do so.  If
00027     you do not wish to do so, delete this exception statement from
00028     your version.
00029 */
00030 
00031 #include "email.h"
00032 #include <kdebug.h>
00033 
00034 //-----------------------------------------------------------------------------
00035 QStringList KPIM::splitEmailAddrList(const QString& aStr)
00036 {
00037   // Features:
00038   // - always ignores quoted characters
00039   // - ignores everything (including parentheses and commas)
00040   //   inside quoted strings
00041   // - supports nested comments
00042   // - ignores everything (including double quotes and commas)
00043   //   inside comments
00044 
00045   QStringList list;
00046 
00047   if (aStr.isEmpty())
00048     return list;
00049 
00050   QString addr;
00051   uint addrstart = 0;
00052   int commentlevel = 0;
00053   bool insidequote = false;
00054 
00055   for (uint index=0; index<aStr.length(); index++) {
00056     // the following conversion to latin1 is o.k. because
00057     // we can safely ignore all non-latin1 characters
00058     switch (aStr[index].latin1()) {
00059     case '"' : // start or end of quoted string
00060       if (commentlevel == 0)
00061         insidequote = !insidequote;
00062       break;
00063     case '(' : // start of comment
00064       if (!insidequote)
00065         commentlevel++;
00066       break;
00067     case ')' : // end of comment
00068       if (!insidequote) {
00069         if (commentlevel > 0)
00070           commentlevel--;
00071         else {
00072           kdDebug(5300) << "Error in address splitting: Unmatched ')'"
00073                         << endl;
00074           return list;
00075         }
00076       }
00077       break;
00078     case '\\' : // quoted character
00079       index++; // ignore the quoted character
00080       break;
00081     case ',' :
00082       if (!insidequote && (commentlevel == 0)) {
00083         addr = aStr.mid(addrstart, index-addrstart);
00084         if (!addr.isEmpty())
00085           list += addr.simplifyWhiteSpace();
00086         addrstart = index+1;
00087       }
00088       break;
00089     }
00090   }
00091   // append the last address to the list
00092   if (!insidequote && (commentlevel == 0)) {
00093     addr = aStr.mid(addrstart, aStr.length()-addrstart);
00094     if (!addr.isEmpty())
00095       list += addr.simplifyWhiteSpace();
00096   }
00097   else
00098     kdDebug(5300) << "Error in address splitting: "
00099                   << "Unexpected end of address list"
00100                   << endl;
00101 
00102   return list;
00103 }
00104 
00105 //-----------------------------------------------------------------------------
00106 QCString KPIM::getEmailAddr(const QString& aStr)
00107 {
00108   int a, i, j, len, found = 0;
00109   QChar c;
00110   // Find the '@' in the email address:
00111   a = aStr.find('@');
00112   if (a<0) return aStr.latin1();
00113   // Loop backwards until we find '<', '(', ' ', or beginning of string.
00114   for (i = a - 1; i >= 0; i--) {
00115     c = aStr[i];
00116     if (c == '<' || c == '(' || c == ' ') found = 1;
00117     if (found) break;
00118   }
00119   // Reset found for next loop.
00120   found = 0;
00121   // Loop forwards until we find '>', ')', ' ', or end of string.
00122   for (j = a + 1; j < (int)aStr.length(); j++) {
00123     c = aStr[j];
00124     if (c == '>' || c == ')' || c == ' ') found = 1;
00125     if (found) break;
00126   }
00127   // Calculate the length and return the result.
00128   len = j - (i + 1);
00129   return aStr.mid(i+1,len).latin1();
00130 }
00131 
00132 bool KPIM::getNameAndMail(const QString& aStr, QString& name, QString& mail)
00133 {
00134   name = QString::null;
00135   mail = QString::null;
00136 
00137   const int len=aStr.length();
00138   const char cQuotes = '"';
00139 
00140   bool bInComment, bInQuotesOutsideOfEmail;
00141   int i=0, iAd=0, iMailStart=0, iMailEnd=0;
00142   QChar c;
00143 
00144   // Find the '@' of the email address
00145   // skipping all '@' inside "(...)" comments:
00146   bInComment = false;
00147   while( i < len ){
00148     c = aStr[i];
00149     if( !bInComment ){
00150       if( '(' == c ){
00151         bInComment = true;
00152       }else{
00153         if( '@' == c ){
00154           iAd = i;
00155           break; // found it
00156         }
00157       }
00158     }else{
00159       if( ')' == c ){
00160         bInComment = false;
00161       }
00162     }
00163     ++i;
00164   }
00165 
00166   if( !iAd ){
00167     // We suppose the user is typing the string manually and just
00168     // has not finished typing the mail address part.
00169     // So we take everything that's left of the '<' as name and the rest as mail
00170     for( i = 0; len > i; ++i ) {
00171       c = aStr[i];
00172       if( '<' != c )
00173         name.append( c );
00174       else
00175         break;
00176     }
00177     mail = aStr.mid( i+1 );
00178     if ( mail.endsWith( ">" ) )
00179        mail.truncate( mail.length() - 1 );
00180 
00181   }else{
00182 
00183     // Loop backwards until we find the start of the string
00184     // or a ',' that is outside of a comment
00185     //          and outside of quoted text before the leading '<'.
00186     bInComment = false;
00187     bInQuotesOutsideOfEmail = false;
00188     for( i = iAd-1; 0 <= i; --i ) {
00189       c = aStr[i];
00190       if( bInComment ){
00191         if( '(' == c ){
00192           if( !name.isEmpty() )
00193             name.prepend( ' ' );
00194           bInComment = false;
00195         }else{
00196           name.prepend( c ); // all comment stuff is part of the name
00197         }
00198       }else if( bInQuotesOutsideOfEmail ){
00199         if( cQuotes == c )
00200           bInQuotesOutsideOfEmail = false;
00201         else
00202           name.prepend( c );
00203       }else{
00204         // found the start of this addressee ?
00205         if( ',' == c )
00206           break;
00207         // stuff is before the leading '<' ?
00208         if( iMailStart ){
00209           if( cQuotes == c )
00210             bInQuotesOutsideOfEmail = true; // end of quoted text found
00211           else
00212             name.prepend( c );
00213         }else{
00214           switch( c ){
00215             case '<':
00216               iMailStart = i;
00217               break;
00218             case ')':
00219               if( !name.isEmpty() )
00220                 name.prepend( ' ' );
00221               bInComment = true;
00222               break;
00223             default:
00224               if( ' ' != c )
00225                 mail.prepend( c );
00226           }
00227         }
00228       }
00229     }
00230 
00231     name = name.simplifyWhiteSpace();
00232     mail = mail.simplifyWhiteSpace();
00233 
00234     if( mail.isEmpty() )
00235       return false;
00236 
00237     mail.append('@');
00238 
00239     // Loop forward until we find the end of the string
00240     // or a ',' that is outside of a comment
00241     //          and outside of quoted text behind the trailing '>'.
00242     bInComment = false;
00243     bInQuotesOutsideOfEmail = false;
00244     for( i = iAd+1; len > i; ++i ) {
00245       c = aStr[i];
00246       if( bInComment ){
00247         if( ')' == c ){
00248           if( !name.isEmpty() )
00249             name.append( ' ' );
00250           bInComment = false;
00251         }else{
00252           name.append( c ); // all comment stuff is part of the name
00253         }
00254       }else if( bInQuotesOutsideOfEmail ){
00255         if( cQuotes == c )
00256           bInQuotesOutsideOfEmail = false;
00257         else
00258           name.append( c );
00259       }else{
00260         // found the end of this addressee ?
00261         if( ',' == c )
00262           break;
00263         // stuff is behind the trailing '>' ?
00264         if( iMailEnd ){
00265           if( cQuotes == c )
00266             bInQuotesOutsideOfEmail = true; // start of quoted text found
00267           else
00268             name.append( c );
00269         }else{
00270           switch( c ){
00271             case '>':
00272               iMailEnd = i;
00273               break;
00274             case '(':
00275               if( !name.isEmpty() )
00276                 name.append( ' ' );
00277               bInComment = true;
00278               break;
00279             default:
00280               if( ' ' != c )
00281                 mail.append( c );
00282           }
00283         }
00284       }
00285     }
00286   }
00287 
00288   name = name.simplifyWhiteSpace();
00289   mail = mail.simplifyWhiteSpace();
00290 
00291   return ! (name.isEmpty() || mail.isEmpty());
00292 }
00293 
00294 bool KPIM::compareEmail( const QString& email1, const QString& email2,
00295                          bool matchName )
00296 {
00297   QString e1Name, e1Email, e2Name, e2Email;
00298 
00299   getNameAndMail( email1, e1Name, e1Email );
00300   getNameAndMail( email2, e2Name, e2Email );
00301 
00302   return e1Email == e2Email &&
00303     ( !matchName || ( e1Name == e2Name ) );
00304 }
KDE Logo
This file is part of the documentation for libkdepim Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Apr 4 04:46:32 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003