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