00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "email.h"
00022
00023 #include <kdebug.h>
00024 #include <klocale.h>
00025 #include <kidna.h>
00026
00027 #include <qregexp.h>
00028
00029
00030 QStringList KPIM::splitEmailAddrList(const QString& aStr)
00031 {
00032
00033
00034
00035
00036
00037
00038
00039
00040 QStringList list;
00041
00042 if (aStr.isEmpty())
00043 return list;
00044
00045 QString addr;
00046 uint addrstart = 0;
00047 int commentlevel = 0;
00048 bool insidequote = false;
00049
00050 for (uint index=0; index<aStr.length(); index++) {
00051
00052
00053 switch (aStr[index].latin1()) {
00054 case '"' :
00055 if (commentlevel == 0)
00056 insidequote = !insidequote;
00057 break;
00058 case '(' :
00059 if (!insidequote)
00060 commentlevel++;
00061 break;
00062 case ')' :
00063 if (!insidequote) {
00064 if (commentlevel > 0)
00065 commentlevel--;
00066 else {
00067 kdDebug(5300) << "Error in address splitting: Unmatched ')'"
00068 << endl;
00069 return list;
00070 }
00071 }
00072 break;
00073 case '\\' :
00074 index++;
00075 break;
00076 case ',' :
00077 if (!insidequote && (commentlevel == 0)) {
00078 addr = aStr.mid(addrstart, index-addrstart);
00079 if (!addr.isEmpty())
00080 list += addr.simplifyWhiteSpace();
00081 addrstart = index+1;
00082 }
00083 break;
00084 }
00085 }
00086
00087 if (!insidequote && (commentlevel == 0)) {
00088 addr = aStr.mid(addrstart, aStr.length()-addrstart);
00089 if (!addr.isEmpty())
00090 list += addr.simplifyWhiteSpace();
00091 }
00092 else
00093 kdDebug(5300) << "Error in address splitting: "
00094 << "Unexpected end of address list"
00095 << endl;
00096
00097 return list;
00098 }
00099
00100
00101
00102 KPIM::EmailParseResult splitAddressInternal( const QCString& address,
00103 QCString & displayName,
00104 QCString & addrSpec,
00105 QCString & comment,
00106 bool allowMultipleAddresses )
00107 {
00108
00109
00110 displayName = "";
00111 addrSpec = "";
00112 comment = "";
00113
00114 if ( address.isEmpty() )
00115 return KPIM::AddressEmpty;
00116
00117
00118
00119
00120
00121 enum { TopLevel, InComment, InAngleAddress } context = TopLevel;
00122 bool inQuotedString = false;
00123 int commentLevel = 0;
00124 bool stop = false;
00125
00126 for ( char* p = address.data(); *p && !stop; ++p ) {
00127 switch ( context ) {
00128 case TopLevel : {
00129 switch ( *p ) {
00130 case '"' : inQuotedString = !inQuotedString;
00131 displayName += *p;
00132 break;
00133 case '(' : if ( !inQuotedString ) {
00134 context = InComment;
00135 commentLevel = 1;
00136 }
00137 else
00138 displayName += *p;
00139 break;
00140 case '<' : if ( !inQuotedString ) {
00141 context = InAngleAddress;
00142 }
00143 else
00144 displayName += *p;
00145 break;
00146 case '\\' :
00147 displayName += *p;
00148 ++p;
00149 if ( *p )
00150 displayName += *p;
00151 else
00152 return KPIM::UnexpectedEnd;
00153 break;
00154 case ',' : if ( !inQuotedString ) {
00155 if ( allowMultipleAddresses )
00156 stop = true;
00157 else
00158 return KPIM::UnexpectedComma;
00159 }
00160 else
00161 displayName += *p;
00162 break;
00163 default : displayName += *p;
00164 }
00165 break;
00166 }
00167 case InComment : {
00168 switch ( *p ) {
00169 case '(' : ++commentLevel;
00170 comment += *p;
00171 break;
00172 case ')' : --commentLevel;
00173 if ( commentLevel == 0 ) {
00174 context = TopLevel;
00175 comment += ' ';
00176 }
00177 else
00178 comment += *p;
00179 break;
00180 case '\\' :
00181 comment += *p;
00182 ++p;
00183 if ( *p )
00184 comment += *p;
00185 else
00186 return KPIM::UnexpectedEnd;
00187 break;
00188 default : comment += *p;
00189 }
00190 break;
00191 }
00192 case InAngleAddress : {
00193 switch ( *p ) {
00194 case '"' : inQuotedString = !inQuotedString;
00195 addrSpec += *p;
00196 break;
00197 case '>' : if ( !inQuotedString ) {
00198 context = TopLevel;
00199 }
00200 else
00201 addrSpec += *p;
00202 break;
00203 case '\\' :
00204 addrSpec += *p;
00205 ++p;
00206 if ( *p )
00207 addrSpec += *p;
00208 else
00209 return KPIM::UnexpectedEnd;
00210 break;
00211 default : addrSpec += *p;
00212 }
00213 break;
00214 }
00215 }
00216 }
00217
00218 if ( inQuotedString )
00219 return KPIM::UnbalancedQuote;
00220 if ( context == InComment )
00221 return KPIM::UnbalancedParens;
00222 if ( context == InAngleAddress )
00223 return KPIM::UnclosedAngleAddr;
00224
00225 displayName = displayName.stripWhiteSpace();
00226 comment = comment.stripWhiteSpace();
00227 addrSpec = addrSpec.stripWhiteSpace();
00228
00229 if ( addrSpec.isEmpty() ) {
00230 if ( displayName.isEmpty() )
00231 return KPIM::NoAddressSpec;
00232 else {
00233 addrSpec = displayName;
00234 displayName.truncate( 0 );
00235 }
00236 }
00237
00238
00239
00240
00241
00242 return KPIM::AddressOk;
00243 }
00244
00245
00246
00247 KPIM::EmailParseResult KPIM::splitAddress( const QCString& address,
00248 QCString & displayName,
00249 QCString & addrSpec,
00250 QCString & comment )
00251 {
00252 return splitAddressInternal( address, displayName, addrSpec, comment,
00253 false );
00254 }
00255
00256
00257
00258 KPIM::EmailParseResult KPIM::splitAddress( const QString & address,
00259 QString & displayName,
00260 QString & addrSpec,
00261 QString & comment )
00262 {
00263 QCString d, a, c;
00264 KPIM::EmailParseResult result = splitAddress( address.utf8(), d, a, c );
00265 if ( result == AddressOk ) {
00266 displayName = QString::fromUtf8( d );
00267 addrSpec = QString::fromUtf8( a );
00268 comment = QString::fromUtf8( c );
00269 }
00270 return result;
00271 }
00272
00273
00274
00275 KPIM::EmailParseResult KPIM::isValidEmailAddress( const QString& aStr )
00276 {
00277
00278
00279 if ( aStr.isEmpty() ) {
00280 return AddressEmpty;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290 bool tooManyAtsFlag = false;
00291
00292 int atCount = aStr.contains('@');
00293 if ( atCount > 1 ) {
00294 tooManyAtsFlag = true;;
00295 } else if ( atCount == 0 ) {
00296 return TooFewAts;
00297 }
00298
00299
00300
00301
00302 enum { TopLevel, InComment, InAngleAddress } context = TopLevel;
00303 bool inQuotedString = false;
00304 int commentLevel = 0;
00305
00306 unsigned int strlen = aStr.length();
00307
00308 for ( unsigned int index=0; index < strlen; index++ ) {
00309 switch ( context ) {
00310 case TopLevel : {
00311 switch ( aStr[index].latin1() ) {
00312 case '"' : inQuotedString = !inQuotedString;
00313 break;
00314 case '(' :
00315 if ( !inQuotedString ) {
00316 context = InComment;
00317 commentLevel = 1;
00318 }
00319 break;
00320 case '[' :
00321 if ( !inQuotedString ) {
00322 return InvalidDisplayName;
00323 }
00324 break;
00325 case ']' :
00326 if ( !inQuotedString ) {
00327 return InvalidDisplayName;
00328 }
00329 break;
00330 case ':' :
00331 if ( !inQuotedString ) {
00332 return DisallowedChar;
00333 }
00334 break;
00335 case '<' :
00336 if ( !inQuotedString ) {
00337 context = InAngleAddress;
00338 }
00339 break;
00340 case '\\' :
00341 ++index;
00342 if (( index + 1 )> strlen ) {
00343 return UnexpectedEnd;
00344 }
00345 break;
00346 case ',' :
00347 if ( !inQuotedString )
00348 return UnexpectedComma;
00349 break;
00350 case ')' :
00351 if ( !inQuotedString )
00352 return UnbalancedParens;
00353 break;
00354 case '>' :
00355 if ( !inQuotedString )
00356 return UnopenedAngleAddr;
00357 break;
00358 case '@' :
00359 if ( !inQuotedString ) {
00360 if ( index == 0 ) {
00361 return MissingLocalPart;
00362 } else if( index == strlen-1 ) {
00363 return MissingDomainPart;
00364 }
00365 } else if ( inQuotedString ) {
00366 --atCount;
00367 if ( atCount == 1 ) {
00368 tooManyAtsFlag = false;
00369 }
00370 }
00371 break;
00372 }
00373 break;
00374 }
00375 case InComment : {
00376 switch ( aStr[index] ) {
00377 case '(' : ++commentLevel;
00378 break;
00379 case ')' : --commentLevel;
00380 if ( commentLevel == 0 ) {
00381 context = TopLevel;
00382 }
00383 break;
00384 case '\\' :
00385 ++index;
00386 if (( index + 1 )> strlen ) {
00387 return UnexpectedEnd;
00388 }
00389 break;
00390 }
00391 break;
00392 }
00393
00394 case InAngleAddress : {
00395 switch ( aStr[index] ) {
00396 case ',' :
00397 if ( !inQuotedString ) {
00398 return UnexpectedComma;
00399 }
00400 break;
00401 case '"' : inQuotedString = !inQuotedString;
00402 break;
00403 case '@' :
00404 if ( inQuotedString ) {
00405 --atCount;
00406 if ( atCount == 1 ) {
00407 tooManyAtsFlag = false;
00408 }
00409 }
00410 break;
00411 case '>' :
00412 if ( !inQuotedString ) {
00413 context = TopLevel;
00414 break;
00415 }
00416 break;
00417 case '\\' :
00418 ++index;
00419 if (( index + 1 )> strlen ) {
00420 return UnexpectedEnd;
00421 }
00422 break;
00423 }
00424 break;
00425 }
00426 }
00427 }
00428
00429 if ( atCount == 0 && !inQuotedString )
00430 return TooFewAts;
00431
00432 if ( inQuotedString )
00433 return UnbalancedQuote;
00434
00435 if ( context == InComment )
00436 return UnbalancedParens;
00437
00438 if ( context == InAngleAddress )
00439 return UnclosedAngleAddr;
00440
00441 if ( tooManyAtsFlag ) {
00442 return TooManyAts;
00443 }
00444 return AddressOk;
00445 }
00446
00447
00448 QString KPIM::emailParseResultToString( EmailParseResult errorCode )
00449 {
00450 switch ( errorCode ) {
00451 case TooManyAts :
00452 return i18n("The email address you entered is not valid because it "
00453 "contains more than one @. "
00454 "You will not create valid messages if you do not "
00455 "change your address.");
00456 case TooFewAts :
00457 return i18n("The email address you entered is not valid because it "
00458 "does not contain a @."
00459 "You will not create valid messages if you do not "
00460 "change your address.");
00461 case AddressEmpty :
00462 return i18n("You have to enter something in the email address field.");
00463 case MissingLocalPart :
00464 return i18n("The email address you entered is not valid because it "
00465 "does not contain a local part.");
00466 case MissingDomainPart :
00467 return i18n("The email address you entered is not valid because it "
00468 "does not contain a domain part.");
00469 case UnbalancedParens :
00470 return i18n("The email address you entered is not valid because it "
00471 "contains unclosed comments/brackets.");
00472 case AddressOk :
00473 return i18n("The email address you entered is valid.");
00474 case UnclosedAngleAddr :
00475 return i18n("The email address you entered is not valid because it "
00476 "contains an unclosed anglebracket.");
00477 case UnopenedAngleAddr :
00478 return i18n("The email address you entered is not valid because it "
00479 "contains an unopened anglebracket.");
00480 case UnexpectedComma :
00481 return i18n("The email address you have entered is not valid because it "
00482 "contains an unexpected comma.");
00483 case UnexpectedEnd :
00484 return i18n("The email address you entered is not valid because it ended "
00485 "unexpectedly, this probably means you have used an escaping type "
00486 "character like an \\ as the last character in your email "
00487 "address.");
00488 case UnbalancedQuote :
00489 return i18n("The email address you entered is not valid because it "
00490 "contains quoted text which does not end.");
00491 case NoAddressSpec :
00492 return i18n("The email address you entered is not valid because it "
00493 "does not seem to contain an actual email address, i.e. "
00494 "something of the form joe@kde.org.");
00495 case DisallowedChar :
00496 return i18n("The email address you entered is not valid because it "
00497 "contains an illegal character.");
00498 case InvalidDisplayName :
00499 return i18n("The email address you have entered is not valid because it "
00500 "contains an invalid displayname.");
00501 }
00502 return i18n("Unknown problem with email address");
00503 }
00504
00505
00506 bool KPIM::isValidSimpleEmailAddress( const QString& aStr )
00507 {
00508
00509
00510 if ( aStr.isEmpty() ) {
00511 return false;
00512 }
00513
00514 int atChar = aStr.findRev( '@' );
00515 QString domainPart = aStr.mid( atChar + 1);
00516 QString localPart = aStr.left( atChar );
00517 bool tooManyAtsFlag = false;
00518 bool inQuotedString = false;
00519 int atCount = localPart.contains( '@' );
00520
00521 unsigned int strlen = localPart.length();
00522 for ( unsigned int index=0; index < strlen; index++ ) {
00523 switch( localPart[ index ].latin1() ) {
00524 case '"' : inQuotedString = !inQuotedString;
00525 break;
00526 case '@' :
00527 if ( inQuotedString ) {
00528 --atCount;
00529 if ( atCount == 0 ) {
00530 tooManyAtsFlag = false;
00531 }
00532 }
00533 break;
00534 }
00535 }
00536
00537 QString addrRx = "[a-zA-Z]*[~|{}`\\^?=/+*'&%$#!_\\w.-]*[~|{}`\\^?=/+*'&%$#!_a-zA-Z0-9-]@";
00538 if ( localPart[ 0 ] == '\"' || localPart[ localPart.length()-1 ] == '\"' ) {
00539 addrRx = "\"[a-zA-Z@]*[\\w.@-]*[a-zA-Z0-9@]\"@";
00540 }
00541 if ( domainPart[ 0 ] == '[' || domainPart[ domainPart.length()-1 ] == ']' ) {
00542 addrRx += "\\[[0-9]{,3}(\\.[0-9]{,3}){3}\\]";
00543 } else {
00544 addrRx += "[\\w-]+(\\.[\\w-]+)*";
00545 }
00546 QRegExp rx( addrRx );
00547 return rx.exactMatch( aStr ) && !tooManyAtsFlag;
00548 }
00549
00550
00551 QString KPIM::simpleEmailAddressErrorMsg()
00552 {
00553 return i18n("The email address you entered is not valid because it "
00554 "does not seem to contain an actual email address, i.e. "
00555 "something of the form joe@kde.org.");
00556 }
00557
00558 QCString KPIM::getEmailAddress( const QCString & address )
00559 {
00560 QCString dummy1, dummy2, addrSpec;
00561 KPIM::EmailParseResult result =
00562 splitAddressInternal( address, dummy1, addrSpec, dummy2,
00563 false );
00564 if ( result != AddressOk ) {
00565 addrSpec = QCString();
00566 kdDebug()
00567 << "Input: aStr\nError:"
00568 << emailParseResultToString( result ) << endl;
00569 }
00570
00571 return addrSpec;
00572 }
00573
00574
00575
00576 QString KPIM::getEmailAddress( const QString & address )
00577 {
00578 return QString::fromUtf8( getEmailAddress( address.utf8() ) );
00579 }
00580
00581
00582
00583 QCString KPIM::getFirstEmailAddress( const QCString & addresses )
00584 {
00585 QCString dummy1, dummy2, addrSpec;
00586 KPIM::EmailParseResult result =
00587 splitAddressInternal( addresses, dummy1, addrSpec, dummy2,
00588 true );
00589 if ( result != AddressOk ) {
00590 addrSpec = QCString();
00591 kdDebug()
00592 << "Input: aStr\nError:"
00593 << emailParseResultToString( result ) << endl;
00594 }
00595
00596 return addrSpec;
00597 }
00598
00599
00600
00601 QString KPIM::getFirstEmailAddress( const QString & addresses )
00602 {
00603 return QString::fromUtf8( getFirstEmailAddress( addresses.utf8() ) );
00604 }
00605
00606
00607
00608 bool KPIM::getNameAndMail(const QString& aStr, QString& name, QString& mail)
00609 {
00610 name = QString::null;
00611 mail = QString::null;
00612
00613 const int len=aStr.length();
00614 const char cQuotes = '"';
00615
00616 bool bInComment = false;
00617 bool bInQuotesOutsideOfEmail = false;
00618 int i=0, iAd=0, iMailStart=0, iMailEnd=0;
00619 QChar c;
00620 unsigned int commentstack = 0;
00621
00622
00623
00624 while( i < len ){
00625 c = aStr[i];
00626 if( '(' == c ) commentstack++;
00627 if( ')' == c ) commentstack--;
00628 bInComment = commentstack != 0;
00629 if( '"' == c && !bInComment )
00630 bInQuotesOutsideOfEmail = !bInQuotesOutsideOfEmail;
00631
00632 if( !bInComment && !bInQuotesOutsideOfEmail ){
00633 if( '@' == c ){
00634 iAd = i;
00635 break;
00636 }
00637 }
00638 ++i;
00639 }
00640
00641 if ( !iAd ) {
00642
00643
00644
00645 for( i = 0; len > i; ++i ) {
00646 c = aStr[i];
00647 if( '<' != c )
00648 name.append( c );
00649 else
00650 break;
00651 }
00652 mail = aStr.mid( i+1 );
00653 if ( mail.endsWith( ">" ) )
00654 mail.truncate( mail.length() - 1 );
00655
00656 } else {
00657
00658
00659
00660 bInComment = false;
00661 bInQuotesOutsideOfEmail = false;
00662 for( i = iAd-1; 0 <= i; --i ) {
00663 c = aStr[i];
00664 if( bInComment ) {
00665 if( '(' == c ) {
00666 if( !name.isEmpty() )
00667 name.prepend( ' ' );
00668 bInComment = false;
00669 } else {
00670 name.prepend( c );
00671 }
00672 }else if( bInQuotesOutsideOfEmail ){
00673 if( cQuotes == c )
00674 bInQuotesOutsideOfEmail = false;
00675 else
00676 name.prepend( c );
00677 }else{
00678
00679 if( ',' == c )
00680 break;
00681
00682 if( iMailStart ){
00683 if( cQuotes == c )
00684 bInQuotesOutsideOfEmail = true;
00685 else
00686 name.prepend( c );
00687 }else{
00688 switch( c ){
00689 case '<':
00690 iMailStart = i;
00691 break;
00692 case ')':
00693 if( !name.isEmpty() )
00694 name.prepend( ' ' );
00695 bInComment = true;
00696 break;
00697 default:
00698 if( ' ' != c )
00699 mail.prepend( c );
00700 }
00701 }
00702 }
00703 }
00704
00705 name = name.simplifyWhiteSpace();
00706 mail = mail.simplifyWhiteSpace();
00707
00708 if( mail.isEmpty() )
00709 return false;
00710
00711 mail.append('@');
00712
00713
00714
00715
00716 bInComment = false;
00717 bInQuotesOutsideOfEmail = false;
00718 int parenthesesNesting = 0;
00719 for( i = iAd+1; len > i; ++i ) {
00720 c = aStr[i];
00721 if( bInComment ){
00722 if( ')' == c ){
00723 if ( --parenthesesNesting == 0 ) {
00724 bInComment = false;
00725 if( !name.isEmpty() )
00726 name.append( ' ' );
00727 } else {
00728
00729 name.append( ')' );
00730 }
00731 } else {
00732 if( '(' == c ) {
00733
00734 ++parenthesesNesting;
00735 }
00736 name.append( c );
00737 }
00738 }else if( bInQuotesOutsideOfEmail ){
00739 if( cQuotes == c )
00740 bInQuotesOutsideOfEmail = false;
00741 else
00742 name.append( c );
00743 }else{
00744
00745 if( ',' == c )
00746 break;
00747
00748 if( iMailEnd ){
00749 if( cQuotes == c )
00750 bInQuotesOutsideOfEmail = true;
00751 else
00752 name.append( c );
00753 }else{
00754 switch( c ){
00755 case '>':
00756 iMailEnd = i;
00757 break;
00758 case '(':
00759 if( !name.isEmpty() )
00760 name.append( ' ' );
00761 if ( ++parenthesesNesting > 0 )
00762 bInComment = true;
00763 break;
00764 default:
00765 if( ' ' != c )
00766 mail.append( c );
00767 }
00768 }
00769 }
00770 }
00771 }
00772
00773 name = name.simplifyWhiteSpace();
00774 mail = mail.simplifyWhiteSpace();
00775
00776 return ! (name.isEmpty() || mail.isEmpty());
00777 }
00778
00779
00780
00781 bool KPIM::compareEmail( const QString& email1, const QString& email2,
00782 bool matchName )
00783 {
00784 QString e1Name, e1Email, e2Name, e2Email;
00785
00786 getNameAndMail( email1, e1Name, e1Email );
00787 getNameAndMail( email2, e2Name, e2Email );
00788
00789 return e1Email == e2Email &&
00790 ( !matchName || ( e1Name == e2Name ) );
00791 }
00792
00793
00794
00795 QString KPIM::normalizedAddress( const QString & displayName,
00796 const QString & addrSpec,
00797 const QString & comment )
00798 {
00799 if ( displayName.isEmpty() && comment.isEmpty() )
00800 return addrSpec;
00801 else if ( comment.isEmpty() )
00802 return displayName + " <" + addrSpec + ">";
00803 else if ( displayName.isEmpty() ) {
00804 QString commentStr = comment;
00805 return quoteNameIfNecessary( commentStr ) + " <" + addrSpec + ">";
00806 }
00807 else
00808 return displayName + " (" + comment + ") <" + addrSpec + ">";
00809 }
00810
00811
00812
00813 QString KPIM::decodeIDN( const QString & addrSpec )
00814 {
00815 const int atPos = addrSpec.findRev( '@' );
00816 if ( atPos == -1 )
00817 return addrSpec;
00818
00819 QString idn = KIDNA::toUnicode( addrSpec.mid( atPos + 1 ) );
00820 if ( idn.isEmpty() )
00821 return QString::null;
00822
00823 return addrSpec.left( atPos + 1 ) + idn;
00824 }
00825
00826
00827
00828 QString KPIM::encodeIDN( const QString & addrSpec )
00829 {
00830 const int atPos = addrSpec.findRev( '@' );
00831 if ( atPos == -1 )
00832 return addrSpec;
00833
00834 QString idn = KIDNA::toAscii( addrSpec.mid( atPos + 1 ) );
00835 if ( idn.isEmpty() )
00836 return addrSpec;
00837
00838 return addrSpec.left( atPos + 1 ) + idn;
00839 }
00840
00841
00842
00843 QString KPIM::normalizeAddressesAndDecodeIDNs( const QString & str )
00844 {
00845
00846
00847 if( str.isEmpty() )
00848 return str;
00849
00850 const QStringList addressList = KPIM::splitEmailAddrList( str );
00851 QStringList normalizedAddressList;
00852
00853 QCString displayName, addrSpec, comment;
00854
00855 for( QStringList::ConstIterator it = addressList.begin();
00856 ( it != addressList.end() );
00857 ++it ) {
00858 if( !(*it).isEmpty() ) {
00859 if ( KPIM::splitAddress( (*it).utf8(), displayName, addrSpec, comment )
00860 == AddressOk ) {
00861
00862 normalizedAddressList <<
00863 normalizedAddress( QString::fromUtf8( displayName ),
00864 decodeIDN( QString::fromUtf8( addrSpec ) ),
00865 QString::fromUtf8( comment ) );
00866 }
00867 else {
00868 kdDebug() << "splitting address failed: " << *it << endl;
00869 }
00870 }
00871 }
00872
00873
00874
00875
00876
00877 return normalizedAddressList.join( ", " );
00878 }
00879
00880
00881 QString KPIM::normalizeAddressesAndEncodeIDNs( const QString & str )
00882 {
00883
00884
00885 if( str.isEmpty() )
00886 return str;
00887
00888 const QStringList addressList = KPIM::splitEmailAddrList( str );
00889 QStringList normalizedAddressList;
00890
00891 QCString displayName, addrSpec, comment;
00892
00893 for( QStringList::ConstIterator it = addressList.begin();
00894 ( it != addressList.end() );
00895 ++it ) {
00896 if( !(*it).isEmpty() ) {
00897 if ( KPIM::splitAddress( (*it).utf8(), displayName, addrSpec, comment )
00898 == AddressOk ) {
00899
00900 normalizedAddressList <<
00901 normalizedAddress( QString::fromUtf8( displayName ),
00902 encodeIDN( QString::fromUtf8( addrSpec ) ),
00903 QString::fromUtf8( comment ) );
00904 }
00905 else {
00906 kdDebug() << "splitting address failed: " << *it << endl;
00907 }
00908 }
00909 }
00910
00911
00912
00913
00914
00915
00916 return normalizedAddressList.join( ", " );
00917 }
00918
00919
00920
00921
00922 static QString escapeQuotes( const QString & str )
00923 {
00924 if ( str.isEmpty() )
00925 return QString();
00926
00927 QString escaped;
00928
00929 escaped.reserve( 2*str.length() );
00930 unsigned int len = 0;
00931 for ( unsigned int i = 0; i < str.length(); ++i, ++len ) {
00932 if ( str[i] == '"' ) {
00933 escaped[len] = '\\';
00934 ++len;
00935 }
00936 else if ( str[i] == '\\' ) {
00937 escaped[len] = '\\';
00938 ++len;
00939 ++i;
00940 if ( i >= str.length() )
00941 break;
00942 }
00943 escaped[len] = str[i];
00944 }
00945 escaped.truncate( len );
00946 return escaped;
00947 }
00948
00949
00950 QString KPIM::quoteNameIfNecessary( const QString &str )
00951 {
00952 QString quoted = str;
00953
00954 QRegExp needQuotes( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" );
00955
00956 if ( ( quoted[0] == '"' ) && ( quoted[quoted.length() - 1] == '"' ) ) {
00957 quoted = "\"" + escapeQuotes( quoted.mid( 1, quoted.length() - 2 ) ) + "\"";
00958 }
00959 else if ( quoted.find( needQuotes ) != -1 ) {
00960 quoted = "\"" + escapeQuotes( quoted ) + "\"";
00961 }
00962
00963 return quoted;
00964 }
00965