libkmime

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