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