kmime_util.cpp
00001 /* 00002 kmime_util.cpp 00003 00004 KMime, the KDE internet mail/usenet news message library. 00005 Copyright (c) 2001 the KMime authors. 00006 See file AUTHORS for details 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software Foundation, 00014 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US 00015 */ 00016 00017 #ifdef HAVE_CONFIG_H 00018 #include <config.h> 00019 #endif 00020 00021 #include "kmime_util.h" 00022 00023 #include <kmdcodec.h> // for KCodec::{quotedPrintableDe,base64{En,De}}code 00024 #include <kglobal.h> 00025 #include <klocale.h> 00026 #include <kcharsets.h> 00027 #include <kdeversion.h> 00028 #if KDE_IS_VERSION( 3, 1, 90 ) 00029 #include <kcalendarsystem.h> 00030 #endif 00031 00032 #include <tqtextcodec.h> 00033 #include <tqstrlist.h> // for TQStrIList 00034 #include <tqregexp.h> 00035 #include <tqdatetime.h> 00036 00037 #include <stdlib.h> 00038 #include <ctype.h> 00039 #include <time.h> // for time() 00040 #include <unistd.h> // for getpid() 00041 00042 using namespace KMime; 00043 00044 namespace KMime { 00045 00046 TQStrIList c_harsetCache; 00047 TQStrIList l_anguageCache; 00048 00049 const char* cachedCharset(const TQCString &name) 00050 { 00051 int idx=c_harsetCache.find(name.data()); 00052 if(idx>-1) 00053 return c_harsetCache.at(idx); 00054 00055 c_harsetCache.append(name.upper().data()); 00056 //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl; 00057 return c_harsetCache.last(); 00058 } 00059 00060 const char* cachedLanguage(const TQCString &name) 00061 { 00062 int idx=l_anguageCache.find(name.data()); 00063 if(idx>-1) 00064 return l_anguageCache.at(idx); 00065 00066 l_anguageCache.append(name.upper().data()); 00067 //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl; 00068 return l_anguageCache.last(); 00069 } 00070 00071 bool isUsAscii(const TQString &s) 00072 { 00073 uint sLength = s.length(); 00074 for (uint i=0; i<sLength; i++) 00075 if (s.at(i).latin1()<=0) // c==0: non-latin1, c<0: non-us-ascii 00076 return false; 00077 00078 return true; 00079 } 00080 00081 // "(),.:;<>@[\] 00082 const uchar specialsMap[16] = { 00083 0x00, 0x00, 0x00, 0x00, // CTLs 00084 0x20, 0xCA, 0x00, 0x3A, // SPACE ... '?' 00085 0x80, 0x00, 0x00, 0x1C, // '@' ... '_' 00086 0x00, 0x00, 0x00, 0x00 // '`' ... DEL 00087 }; 00088 00089 // "(),:;<>@[\]/=? 00090 const uchar tSpecialsMap[16] = { 00091 0x00, 0x00, 0x00, 0x00, // CTLs 00092 0x20, 0xC9, 0x00, 0x3F, // SPACE ... '?' 00093 0x80, 0x00, 0x00, 0x1C, // '@' ... '_' 00094 0x00, 0x00, 0x00, 0x00 // '`' ... DEL 00095 }; 00096 00097 // all except specials, CTLs, SPACE. 00098 const uchar aTextMap[16] = { 00099 0x00, 0x00, 0x00, 0x00, 00100 0x5F, 0x35, 0xFF, 0xC5, 00101 0x7F, 0xFF, 0xFF, 0xE3, 00102 0xFF, 0xFF, 0xFF, 0xFE 00103 }; 00104 00105 // all except tspecials, CTLs, SPACE. 00106 const uchar tTextMap[16] = { 00107 0x00, 0x00, 0x00, 0x00, 00108 0x5F, 0x36, 0xFF, 0xC0, 00109 0x7F, 0xFF, 0xFF, 0xE3, 00110 0xFF, 0xFF, 0xFF, 0xFE 00111 }; 00112 00113 // none except a-zA-Z0-9!*+-/ 00114 const uchar eTextMap[16] = { 00115 0x00, 0x00, 0x00, 0x00, 00116 0x40, 0x35, 0xFF, 0xC0, 00117 0x7F, 0xFF, 0xFF, 0xE0, 00118 0x7F, 0xFF, 0xFF, 0xE0 00119 }; 00120 00121 #if defined(_AIX) && defined(truncate) 00122 #undef truncate 00123 #endif 00124 00125 TQString decodeRFC2047String(const TQCString &src, const char **usedCS, 00126 const TQCString &defaultCS, bool forceCS) 00127 { 00128 TQCString result, str; 00129 TQCString declaredCS; 00130 const char *beg, *end, *mid, *pos=0; 00131 char *dest, *endOfLastEncWord=0; 00132 char encoding = '\0'; 00133 bool valid, onlySpacesSinceLastWord=false; 00134 const int maxLen=400; 00135 int i; 00136 00137 if(src.find("=?") < 0) 00138 result = src.copy(); 00139 else { 00140 result.truncate(src.length()); 00141 for (pos=src.data(), dest=result.data(); *pos; pos++) 00142 { 00143 if (pos[0]!='=' || pos[1]!='?') 00144 { 00145 *dest++ = *pos; 00146 if (onlySpacesSinceLastWord) 00147 onlySpacesSinceLastWord = (pos[0]==' ' || pos[1]=='\t'); 00148 continue; 00149 } 00150 beg = pos+2; 00151 end = beg; 00152 valid = TRUE; 00153 // parse charset name 00154 declaredCS=""; 00155 for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(ispunct(*pos)||isalnum(*pos))); i++) { 00156 declaredCS+=(*pos); 00157 pos++; 00158 } 00159 if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE; 00160 else 00161 { 00162 // get encoding and check delimiting question marks 00163 encoding = toupper(pos[1]); 00164 if (pos[2]!='?' || (encoding!='Q' && encoding!='B')) 00165 valid = FALSE; 00166 pos+=3; 00167 i+=3; 00168 } 00169 if (valid) 00170 { 00171 mid = pos; 00172 // search for end of encoded part 00173 while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='=')) 00174 { 00175 i++; 00176 pos++; 00177 } 00178 end = pos+2;//end now points to the first char after the encoded string 00179 if (i>=maxLen || !*pos) valid = FALSE; 00180 } 00181 00182 if (valid) { 00183 // cut all linear-white space between two encoded words 00184 if (onlySpacesSinceLastWord) 00185 dest=endOfLastEncWord; 00186 00187 if (mid < pos) { 00188 str = TQCString(mid, (int)(pos - mid + 1)); 00189 if (encoding == 'Q') 00190 { 00191 // decode quoted printable text 00192 for (i=str.length()-1; i>=0; i--) 00193 if (str[i]=='_') str[i]=' '; 00194 str = KCodecs::quotedPrintableDecode(str); 00195 } 00196 else 00197 { 00198 str = KCodecs::base64Decode(str); 00199 } 00200 if (!str.isNull()) { 00201 for (i=0; str[i]; i++) { 00202 *dest++ = str[i]; 00203 } 00204 } 00205 } 00206 00207 endOfLastEncWord=dest; 00208 onlySpacesSinceLastWord=true; 00209 00210 pos = end -1; 00211 } 00212 else 00213 { 00214 pos = beg - 2; 00215 *dest++ = *pos++; 00216 *dest++ = *pos; 00217 } 00218 } 00219 *dest = '\0'; 00220 } 00221 00222 //find suitable TQTextCodec 00223 TQTextCodec *codec=0; 00224 bool ok=true; 00225 if (forceCS || declaredCS.isEmpty()) { 00226 codec=KGlobal::charsets()->codecForName(defaultCS); 00227 (*usedCS)=cachedCharset(defaultCS); 00228 } 00229 else { 00230 codec=KGlobal::charsets()->codecForName(declaredCS, ok); 00231 if(!ok) { //no suitable codec found => use default charset 00232 codec=KGlobal::charsets()->codecForName(defaultCS); 00233 (*usedCS)=cachedCharset(defaultCS); 00234 } 00235 else 00236 (*usedCS)=cachedCharset(declaredCS); 00237 } 00238 00239 return codec->toUnicode(result.data(), result.length()); 00240 } 00241 00242 TQString decodeRFC2047String(const TQCString &src) 00243 { 00244 const char *usedCS; 00245 return decodeRFC2047String(src, &usedCS, "utf-8", false); 00246 } 00247 00248 TQCString encodeRFC2047String(const TQString &src, const char *charset, 00249 bool addressHeader, bool allow8BitHeaders) 00250 { 00251 TQCString encoded8Bit, result, usedCS; 00252 unsigned int start=0,end=0; 00253 bool nonAscii=false, ok=true, useTQEncoding=false; 00254 TQTextCodec *codec=0; 00255 00256 usedCS=charset; 00257 codec=KGlobal::charsets()->codecForName(usedCS, ok); 00258 00259 if(!ok) { 00260 //no codec available => try local8Bit and hope the best ;-) 00261 usedCS=KGlobal::locale()->encoding(); 00262 codec=KGlobal::charsets()->codecForName(usedCS, ok); 00263 } 00264 00265 if (usedCS.find("8859-")>=0) // use "B"-Encoding for non iso-8859-x charsets 00266 useTQEncoding=true; 00267 00268 encoded8Bit=codec->fromUnicode(src); 00269 00270 if(allow8BitHeaders) 00271 return encoded8Bit; 00272 00273 uint encoded8BitLength = encoded8Bit.length(); 00274 for (unsigned int i=0; i<encoded8BitLength; i++) { 00275 if (encoded8Bit[i]==' ') // encoding starts at word boundaries 00276 start = i+1; 00277 00278 // encode escape character, for japanese encodings... 00279 if (((signed char)encoded8Bit[i]<0) || (encoded8Bit[i] == '\033') || 00280 (addressHeader && (strchr("\"()<>@,.;:\\[]=",encoded8Bit[i])!=0))) { 00281 end = start; // non us-ascii char found, now we determine where to stop encoding 00282 nonAscii=true; 00283 break; 00284 } 00285 } 00286 00287 if (nonAscii) { 00288 while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words 00289 end++; 00290 00291 for (unsigned int x=end;x<encoded8Bit.length();x++) 00292 if (((signed char)encoded8Bit[x]<0) || (encoded8Bit[x] == '\033') || 00293 (addressHeader && (strchr("\"()<>@,.;:\\[]=",encoded8Bit[x])!=0))) { 00294 end = encoded8Bit.length(); // we found another non-ascii word 00295 00296 while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words 00297 end++; 00298 } 00299 00300 result = encoded8Bit.left(start)+"=?"+usedCS; 00301 00302 if (useTQEncoding) { 00303 result += "?Q?"; 00304 00305 char c,hexcode; // implementation of the "Q"-encoding described in RFC 2047 00306 for (unsigned int i=start;i<end;i++) { 00307 c = encoded8Bit[i]; 00308 if (c == ' ') // make the result readable with not MIME-capable readers 00309 result+='_'; 00310 else 00311 if (((c>='a')&&(c<='z'))|| // paranoid mode, we encode *all* special characters to avoid problems 00312 ((c>='A')&&(c<='Z'))|| // with "From" & "To" headers 00313 ((c>='0')&&(c<='9'))) 00314 result+=c; 00315 else { 00316 result += "="; // "stolen" from KMail ;-) 00317 hexcode = ((c & 0xF0) >> 4) + 48; 00318 if (hexcode >= 58) hexcode += 7; 00319 result += hexcode; 00320 hexcode = (c & 0x0F) + 48; 00321 if (hexcode >= 58) hexcode += 7; 00322 result += hexcode; 00323 } 00324 } 00325 } else { 00326 result += "?B?"+KCodecs::base64Encode(encoded8Bit.mid(start,end-start), false); 00327 } 00328 00329 result +="?="; 00330 result += encoded8Bit.right(encoded8Bit.length()-end); 00331 } 00332 else 00333 result = encoded8Bit; 00334 00335 return result; 00336 } 00337 00338 TQCString uniqueString() 00339 { 00340 static char chars[] = "0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 00341 time_t now; 00342 TQCString ret; 00343 char p[11]; 00344 int pos, ran; 00345 unsigned int timeval; 00346 00347 p[10]='\0'; 00348 now=time(0); 00349 ran=1+(int) (1000.0*rand()/(RAND_MAX+1.0)); 00350 timeval=(now/ran)+getpid(); 00351 00352 for(int i=0; i<10; i++){ 00353 pos=(int) (61.0*rand()/(RAND_MAX+1.0)); 00354 //kdDebug(5003) << pos << endl; 00355 p[i]=chars[pos]; 00356 } 00357 ret.sprintf("%d.%s", timeval, p); 00358 00359 return ret; 00360 } 00361 00362 00363 TQCString multiPartBoundary() 00364 { 00365 TQCString ret; 00366 ret="nextPart"+uniqueString(); 00367 return ret; 00368 } 00369 00370 TQCString extractHeader(const TQCString &src, const char *name) 00371 { 00372 TQCString n=TQCString(name)+":"; 00373 int pos1=-1, pos2=0, len=src.length()-1; 00374 bool folded(false); 00375 00376 if (n.lower() == src.left(n.length()).lower()) { 00377 pos1 = 0; 00378 } else { 00379 n.prepend("\n"); 00380 pos1 = src.find(n.data(),0,false); 00381 } 00382 00383 if (pos1>-1) { //there is a header with the given name 00384 pos1+=n.length(); //skip the name 00385 // skip the usual space after the colon 00386 if ( src.at( pos1 ) == ' ' ) 00387 ++pos1; 00388 pos2=pos1; 00389 00390 if (src[pos2]!='\n') { // check if the header is not empty 00391 while(1) { 00392 pos2=src.find("\n", pos2+1); 00393 if(pos2==-1 || pos2==len || ( src[pos2+1]!=' ' && src[pos2+1]!='\t') ) //break if we reach the end of the string, honor folded lines 00394 break; 00395 else 00396 folded = true; 00397 } 00398 } 00399 00400 if(pos2<0) pos2=len+1; //take the rest of the string 00401 00402 if (!folded) 00403 return src.mid(pos1, pos2-pos1); 00404 else 00405 return (src.mid(pos1, pos2-pos1).replace(TQRegExp("\\s*\\n\\s*")," ")); 00406 } 00407 else { 00408 return TQCString(0); //header not found 00409 } 00410 } 00411 00412 00413 TQCString CRLFtoLF(const TQCString &s) 00414 { 00415 TQCString ret=s.copy(); 00416 ret.replace(TQRegExp("\\r\\n"), "\n"); 00417 return ret; 00418 } 00419 00420 00421 TQCString CRLFtoLF(const char *s) 00422 { 00423 TQCString ret=s; 00424 ret.replace(TQRegExp("\\r\\n"), "\n"); 00425 return ret; 00426 } 00427 00428 00429 TQCString LFtoCRLF(const TQCString &s) 00430 { 00431 TQCString ret=s.copy(); 00432 ret.replace(TQRegExp("\\n"), "\r\n"); 00433 return ret; 00434 } 00435 00436 00437 void removeQuots(TQCString &str) 00438 { 00439 // Removes any quote or backslash caracter 00440 str.replace(TQRegExp("[\\\"]"), ""); 00441 } 00442 00443 00444 void removeQuots(TQString &str) 00445 { 00446 // Removes any quote or backslash caracter 00447 str.replace(TQRegExp("[\\\"]"), ""); 00448 } 00449 00450 00451 void addQuotes(TQCString &str, bool forceQuotes) 00452 { 00453 if ( forceQuotes || TQString(str).contains( TQRegExp( TQString( "\"|\\\\|=|\\]|\\[|:|;|,|\\.|,|@|<|>|\\)|\\(" ) ) ) ) { 00454 // Adds a backslash in front of any existing quote or backslash caracter 00455 str.replace(TQRegExp("([\\\"])"), "\\\\1"); 00456 // Adds quote at beginning and end of thestring 00457 str.insert(0,'"'); 00458 str.append("\""); 00459 } 00460 } 00461 00462 int DateFormatter::mDaylight = -1; 00463 DateFormatter::DateFormatter(FormatType fType) 00464 : mFormat( fType ), mCurrentTime( 0 ) 00465 { 00466 00467 } 00468 00469 DateFormatter::~DateFormatter() 00470 {/*empty*/} 00471 00472 DateFormatter::FormatType 00473 DateFormatter::getFormat() const 00474 { 00475 return mFormat; 00476 } 00477 00478 void 00479 DateFormatter::setFormat( FormatType t ) 00480 { 00481 mFormat = t; 00482 } 00483 00484 TQString 00485 DateFormatter::dateString( time_t otime , const TQString& lang , 00486 bool shortFormat, bool includeSecs ) const 00487 { 00488 switch ( mFormat ) { 00489 case Fancy: 00490 return fancy( otime ); 00491 break; 00492 case Localized: 00493 return localized( otime, shortFormat, includeSecs, lang ); 00494 break; 00495 case CTime: 00496 return cTime( otime ); 00497 break; 00498 case Iso: 00499 return isoDate( otime ); 00500 break; 00501 case Custom: 00502 return custom( otime ); 00503 break; 00504 } 00505 return TQString(); 00506 } 00507 00508 TQString 00509 DateFormatter::dateString(const TQDateTime& dtime, const TQString& lang, 00510 bool shortFormat, bool includeSecs ) const 00511 { 00512 return DateFormatter::dateString( qdateToTimeT(dtime), lang, shortFormat, includeSecs ); 00513 } 00514 00515 TQCString 00516 DateFormatter::rfc2822(time_t otime) const 00517 { 00518 TQDateTime tmp; 00519 TQCString ret; 00520 00521 tmp.setTime_t(otime); 00522 00523 ret = tmp.toString("ddd, dd MMM yyyy hh:mm:ss ").latin1(); 00524 ret += zone(otime); 00525 00526 return ret; 00527 } 00528 00529 TQString 00530 DateFormatter::custom(time_t t) const 00531 { 00532 if ( mCustomFormat.isEmpty() ) 00533 return TQString(); 00534 00535 int z = mCustomFormat.find("Z"); 00536 TQDateTime d; 00537 TQString ret = mCustomFormat; 00538 00539 d.setTime_t(t); 00540 if ( z != -1 ) { 00541 ret.replace(z,1,zone(t)); 00542 } 00543 00544 ret = d.toString(ret); 00545 00546 return ret; 00547 } 00548 00549 void 00550 DateFormatter::setCustomFormat(const TQString& format) 00551 { 00552 mCustomFormat = format; 00553 mFormat = Custom; 00554 } 00555 00556 TQString 00557 DateFormatter::getCustomFormat() const 00558 { 00559 return mCustomFormat; 00560 } 00561 00562 00563 TQCString 00564 DateFormatter::zone(time_t otime) const 00565 { 00566 TQCString ret; 00567 #if defined(HAVE_TIMEZONE) || defined(HAVE_TM_GMTOFF) 00568 struct tm *local = localtime( &otime ); 00569 #endif 00570 00571 #if defined(HAVE_TIMEZONE) 00572 00573 //hmm, could make hours & mins static 00574 int secs = abs(timezone); 00575 int neg = (timezone>0)?1:0; 00576 int hours = secs/3600; 00577 int mins = (secs - hours*3600)/60; 00578 00579 // adjust to daylight 00580 if ( local->tm_isdst > 0 ) { 00581 mDaylight = 1; 00582 if ( neg ) 00583 --hours; 00584 else 00585 ++hours; 00586 } else 00587 mDaylight = 0; 00588 00589 ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins); 00590 00591 #elif defined(HAVE_TM_GMTOFF) 00592 00593 int secs = abs( local->tm_gmtoff ); 00594 int neg = (local->tm_gmtoff<0)?1:0; //no, I don't know why it's backwards :o 00595 int hours = secs/3600; 00596 int mins = (secs - hours*3600)/60; 00597 00598 if ( local->tm_isdst > 0 ) 00599 mDaylight = 1; 00600 else 00601 mDaylight = 0; 00602 00603 ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins); 00604 00605 #else 00606 00607 TQDateTime d1 = TQDateTime::fromString( asctime(gmtime(&otime)) ); 00608 TQDateTime d2 = TQDateTime::fromString( asctime(localtime(&otime)) ); 00609 int secs = d1.secsTo(d2); 00610 int neg = (secs<0)?1:0; 00611 secs = abs(secs); 00612 int hours = secs/3600; 00613 int mins = (secs - hours*3600)/60; 00614 // daylight should be already taken care of here 00615 ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins); 00616 00617 #endif /* HAVE_TIMEZONE */ 00618 00619 return ret; 00620 } 00621 00622 time_t 00623 DateFormatter::qdateToTimeT(const TQDateTime& dt) const 00624 { 00625 TQDateTime epoch( TQDate(1970, 1,1), TQTime(00,00,00) ); 00626 time_t otime; 00627 time( &otime ); 00628 00629 TQDateTime d1 = TQDateTime::fromString( asctime(gmtime(&otime)) ); 00630 TQDateTime d2 = TQDateTime::fromString( asctime(localtime(&otime)) ); 00631 time_t drf = epoch.secsTo( dt ) - d1.secsTo( d2 ); 00632 00633 return drf; 00634 } 00635 00636 TQString 00637 DateFormatter::fancy(time_t otime) const 00638 { 00639 KLocale *locale = KGlobal::locale(); 00640 00641 if ( otime <= 0 ) 00642 return i18n( "unknown" ); 00643 00644 if ( !mCurrentTime ) { 00645 time( &mCurrentTime ); 00646 mDate.setTime_t( mCurrentTime ); 00647 } 00648 00649 TQDateTime old; 00650 old.setTime_t( otime ); 00651 00652 // not more than an hour in the future 00653 if ( mCurrentTime + 60 * 60 >= otime ) { 00654 time_t diff = mCurrentTime - otime; 00655 00656 if ( diff < 24 * 60 * 60 ) { 00657 if ( old.date().year() == mDate.date().year() && 00658 old.date().dayOfYear() == mDate.date().dayOfYear() ) 00659 return i18n( "Today %1" ).arg( locale-> 00660 formatTime( old.time(), true ) ); 00661 } 00662 if ( diff < 2 * 24 * 60 * 60 ) { 00663 TQDateTime yesterday( mDate.addDays( -1 ) ); 00664 if ( old.date().year() == yesterday.date().year() && 00665 old.date().dayOfYear() == yesterday.date().dayOfYear() ) 00666 return i18n( "Yesterday %1" ).arg( locale-> 00667 formatTime( old.time(), true) ); 00668 } 00669 for ( int i = 3; i < 7; i++ ) 00670 if ( diff < i * 24 * 60 * 60 ) { 00671 TQDateTime weekday( mDate.addDays( -i + 1 ) ); 00672 if ( old.date().year() == weekday.date().year() && 00673 old.date().dayOfYear() == weekday.date().dayOfYear() ) 00674 return i18n( "1. weekday, 2. time", "%1 %2" ). 00675 #if KDE_IS_VERSION( 3, 1, 90 ) 00676 arg( locale->calendar()->weekDayName( old.date() ) ). 00677 #else 00678 arg( locale->weekDayName( old.date().dayOfWeek() ) ). 00679 #endif 00680 arg( locale->formatTime( old.time(), true) ); 00681 } 00682 } 00683 00684 return locale->formatDateTime( old ); 00685 00686 } 00687 00688 TQString 00689 DateFormatter::localized(time_t otime, bool shortFormat, bool includeSecs, 00690 const TQString& localeLanguage ) const 00691 { 00692 TQDateTime tmp; 00693 TQString ret; 00694 KLocale *locale = KGlobal::locale(); 00695 00696 tmp.setTime_t( otime ); 00697 00698 00699 if ( !localeLanguage.isEmpty() ) { 00700 locale=new KLocale(localeLanguage); 00701 locale->setLanguage(localeLanguage); 00702 locale->setCountry(localeLanguage); 00703 ret = locale->formatDateTime( tmp, shortFormat, includeSecs ); 00704 delete locale; 00705 } else { 00706 ret = locale->formatDateTime( tmp, shortFormat, includeSecs ); 00707 } 00708 00709 return ret; 00710 } 00711 00712 TQString 00713 DateFormatter::cTime(time_t otime) const 00714 { 00715 return TQString::fromLatin1( ctime( &otime ) ).stripWhiteSpace() ; 00716 } 00717 00718 TQString 00719 DateFormatter::isoDate(time_t otime) const 00720 { 00721 char cstr[64]; 00722 strftime( cstr, 63, "%Y-%m-%d %H:%M:%S", localtime(&otime) ); 00723 return TQString( cstr ); 00724 } 00725 00726 00727 void 00728 DateFormatter::reset() 00729 { 00730 mCurrentTime = 0; 00731 } 00732 00733 TQString 00734 DateFormatter::formatDate(DateFormatter::FormatType t, time_t otime, 00735 const TQString& data, bool shortFormat, bool includeSecs ) 00736 { 00737 DateFormatter f( t ); 00738 if ( t == DateFormatter::Custom ) { 00739 f.setCustomFormat( data ); 00740 } 00741 return f.dateString( otime, data, shortFormat, includeSecs ); 00742 } 00743 00744 TQString 00745 DateFormatter::formatCurrentDate( DateFormatter::FormatType t, const TQString& data, 00746 bool shortFormat, bool includeSecs ) 00747 { 00748 DateFormatter f( t ); 00749 if ( t == DateFormatter::Custom ) { 00750 f.setCustomFormat( data ); 00751 } 00752 return f.dateString( time(0), data, shortFormat, includeSecs ); 00753 } 00754 00755 TQCString 00756 DateFormatter::rfc2822FormatDate( time_t t ) 00757 { 00758 DateFormatter f; 00759 return f.rfc2822( t ); 00760 } 00761 00762 bool 00763 DateFormatter::isDaylight() 00764 { 00765 if ( mDaylight == -1 ) { 00766 time_t ntime = time( 0 ); 00767 struct tm *local = localtime( &ntime ); 00768 if ( local->tm_isdst > 0 ) { 00769 mDaylight = 1; 00770 return true; 00771 } else { 00772 mDaylight = 0; 00773 return false; 00774 } 00775 } else if ( mDaylight != 0 ) 00776 return true; 00777 else 00778 return false; 00779 } 00780 00781 } // namespace KMime