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