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, bool allowSemicolonAsSeparator)
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 ';' : // fallthrough, if ; is allowed
00082       if ( !allowSemicolonAsSeparator )
00083           break; 
00084     case ',' :
00085       if (!insidequote && (commentlevel == 0)) {
00086         addr = aStr.mid(addrstart, index-addrstart);
00087         kdDebug() << endl << "Adding: " << addr.simplifyWhiteSpace() << endl;
00088         if (!addr.isEmpty())
00089           list += addr.simplifyWhiteSpace();
00090         addrstart = index+1;
00091       }
00092       break;
00093     }
00094   }
00095   // append the last address to the list
00096   if (!insidequote && (commentlevel == 0)) {
00097     addr = aStr.mid(addrstart, aStr.length()-addrstart);
00098     if (!addr.isEmpty())
00099       list += addr.simplifyWhiteSpace();
00100   }
00101   else
00102     kdDebug(5300) << "Error in address splitting: "
00103                   << "Unexpected end of address list"
00104                   << endl;
00105 
00106   return list;
00107 }
00108 
00109 //-----------------------------------------------------------------------------
00110 QCString KPIM::getEmailAddr(const QString& aStr)
00111 {
00112   int a, i, j, len, found = 0;
00113   QChar c;
00114   // Find the '@' in the email address:
00115   a = aStr.find('@');
00116   if (a<0) return aStr.latin1();
00117   // Loop backwards until we find '<', '(', ' ', or beginning of string.
00118   for (i = a - 1; i >= 0; i--) {
00119     c = aStr[i];
00120     if (c == '<' || c == '(' || c == ' ') found = 1;
00121     if (found) break;
00122   }
00123   // Reset found for next loop.
00124   found = 0;
00125   // Loop forwards until we find '>', ')', ' ', or end of string.
00126   for (j = a + 1; j < (int)aStr.length(); j++) {
00127     c = aStr[j];
00128     if (c == '>' || c == ')' || c == ' ') found = 1;
00129     if (found) break;
00130   }
00131   // Calculate the length and return the result.
00132   len = j - (i + 1);
00133   return aStr.mid(i+1,len).latin1();
00134 }
00135 
00136 bool KPIM::getNameAndMail(const QString& aStr, QString& name, QString& mail)
00137 {
00138   name = QString::null;
00139   mail = QString::null;
00140 
00141   const int len=aStr.length();
00142   const char cQuotes = '"';
00143 
00144   bool bInComment, bInQuotesOutsideOfEmail;
00145   int i=0, iAd=0, iMailStart=0, iMailEnd=0;
00146   QChar c;
00147 
00148   // Find the '@' of the email address
00149   // skipping all '@' inside "(...)" comments:
00150   bInComment = false;
00151   while( i < len ){
00152     c = aStr[i];
00153     if( !bInComment ){
00154       if( '(' == c ){
00155         bInComment = true;
00156       }else{
00157         if( '@' == c ){
00158           iAd = i;
00159           break; // found it
00160         }
00161       }
00162     }else{
00163       if( ')' == c ){
00164         bInComment = false;
00165       }
00166     }
00167     ++i;
00168   }
00169 
00170   if( !iAd ){
00171     // We suppose the user is typing the string manually and just
00172     // has not finished typing the mail address part.
00173     // So we take everything that's left of the '<' as name and the rest as mail
00174     for( i = 0; len > i; ++i ) {
00175       c = aStr[i];
00176       if( '<' != c )
00177         name.append( c );
00178       else
00179         break;
00180     }
00181     mail = aStr.mid( i+1 );
00182     if ( mail.endsWith( ">" ) )
00183        mail.truncate( mail.length() - 1 );
00184 
00185   }else{
00186 
00187     // Loop backwards until we find the start of the string
00188     // or a ',' that is outside of a comment
00189     //          and outside of quoted text before the leading '<'.
00190     bInComment = false;
00191     bInQuotesOutsideOfEmail = false;
00192     for( i = iAd-1; 0 <= i; --i ) {
00193       c = aStr[i];
00194       if( bInComment ){
00195         if( '(' == c ){
00196           if( !name.isEmpty() )
00197             name.prepend( ' ' );
00198           bInComment = false;
00199         }else{
00200           name.prepend( c ); // all comment stuff is part of the name
00201         }
00202       }else if( bInQuotesOutsideOfEmail ){
00203         if( cQuotes == c )
00204           bInQuotesOutsideOfEmail = false;
00205         else
00206           name.prepend( c );
00207       }else{
00208         // found the start of this addressee ?
00209         if( ',' == c )
00210           break;
00211         // stuff is before the leading '<' ?
00212         if( iMailStart ){
00213           if( cQuotes == c )
00214             bInQuotesOutsideOfEmail = true; // end of quoted text found
00215           else
00216             name.prepend( c );
00217         }else{
00218           switch( c ){
00219             case '<':
00220               iMailStart = i;
00221               break;
00222             case ')':
00223               if( !name.isEmpty() )
00224                 name.prepend( ' ' );
00225               bInComment = true;
00226               break;
00227             default:
00228               if( ' ' != c )
00229                 mail.prepend( c );
00230           }
00231         }
00232       }
00233     }
00234 
00235     name = name.simplifyWhiteSpace();
00236     mail = mail.simplifyWhiteSpace();
00237 
00238     if( mail.isEmpty() )
00239       return false;
00240 
00241     mail.append('@');
00242 
00243     // Loop forward until we find the end of the string
00244     // or a ',' that is outside of a comment
00245     //          and outside of quoted text behind the trailing '>'.
00246     bInComment = false;
00247     bInQuotesOutsideOfEmail = false;
00248     int parenthesesNesting = 0;
00249     for( i = iAd+1; len > i; ++i ) {
00250       c = aStr[i];
00251       if( bInComment ){
00252         if( ')' == c ){
00253           if ( --parenthesesNesting == 0 ) {
00254             bInComment = false;
00255             if( !name.isEmpty() )
00256               name.append( ' ' );
00257           } else {
00258             // nested ")", add it
00259             name.append( ')' ); // name can't be empty here
00260           }
00261         } else {
00262           if( '(' == c ) {
00263             // nested "("
00264             ++parenthesesNesting;
00265           }
00266           name.append( c ); // all comment stuff is part of the name
00267         }
00268       }else if( bInQuotesOutsideOfEmail ){
00269         if( cQuotes == c )
00270           bInQuotesOutsideOfEmail = false;
00271         else
00272           name.append( c );
00273       }else{
00274         // found the end of this addressee ?
00275         if( ',' == c )
00276           break;
00277         // stuff is behind the trailing '>' ?
00278         if( iMailEnd ){
00279           if( cQuotes == c )
00280             bInQuotesOutsideOfEmail = true; // start of quoted text found
00281           else
00282             name.append( c );
00283         }else{
00284           switch( c ){
00285             case '>':
00286               iMailEnd = i;
00287               break;
00288             case '(':
00289               if( !name.isEmpty() )
00290                 name.append( ' ' );
00291               if ( ++parenthesesNesting > 0 )
00292                 bInComment = true;
00293               break;
00294             default:
00295               if( ' ' != c )
00296                 mail.append( c );
00297           }
00298         }
00299       }
00300     }
00301   }
00302 
00303   name = name.simplifyWhiteSpace();
00304   mail = mail.simplifyWhiteSpace();
00305 
00306   return ! (name.isEmpty() || mail.isEmpty());
00307 }
00308 
00309 bool KPIM::compareEmail( const QString& email1, const QString& email2,
00310                          bool matchName )
00311 {
00312   QString e1Name, e1Email, e2Name, e2Email;
00313 
00314   getNameAndMail( email1, e1Name, e1Email );
00315   getNameAndMail( email2, e2Name, e2Email );
00316 
00317   return e1Email == e2Email &&
00318     ( !matchName || ( e1Name == e2Name ) );
00319 }
00320 
00321 
00322 QStringList KPIM::splitEmailAddrList(const QString& aStr)
00323 {
00324     return splitEmailAddrList( aStr, false ); // don't allow ; by default
00325 }
00326 
00327 QString KPIM::quotedName( const QString& fullName )
00328 {
00329   static const QString specials("()<>@,.;:[]");
00330   // add DQUOTE's if necessary:
00331   bool needsQuotes=false;
00332   if ( fullName[0] == '"' && fullName[fullName.length()-1] == '"' ) return fullName;
00333   QString result;
00334   for (unsigned int i=0; i < fullName.length(); i++) {
00335     if ( specials.contains( fullName[i] ) )
00336       needsQuotes = true;
00337     else if ( fullName[i] == '\\' || fullName[i] == '"' ) {
00338       needsQuotes = true;
00339       result += '\\';
00340     }
00341     result += fullName[i];
00342   }
00343 
00344   if (needsQuotes) {
00345     result.insert(0,'"');
00346     result += '"';
00347   }
00348   return result;
00349 
00350 }
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 Wed Jan 31 15:53:22 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003