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