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