summaryrefslogtreecommitdiffstats
path: root/libkmime/kmime_util.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkmime/kmime_util.cpp')
-rw-r--r--libkmime/kmime_util.cpp806
1 files changed, 806 insertions, 0 deletions
diff --git a/libkmime/kmime_util.cpp b/libkmime/kmime_util.cpp
new file mode 100644
index 00000000..8923a5b0
--- /dev/null
+++ b/libkmime/kmime_util.cpp
@@ -0,0 +1,806 @@
+/*
+ kmime_util.cpp
+
+ KMime, the KDE internet mail/usenet news message library.
+ Copyright (c) 2001 the KMime authors.
+ See file AUTHORS for details
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kmime_util.h"
+
+#include <kmdcodec.h> // for KCodec::{quotedPrintableDe,base64{En,De}}code
+#include <kglobal.h>
+#include <klocale.h>
+#include <kcharsets.h>
+#include <kdeversion.h>
+#if KDE_IS_VERSION( 3, 1, 90 )
+#include <kcalendarsystem.h>
+#endif
+
+#include <qtextcodec.h>
+#include <qstrlist.h> // for QStrIList
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h> // for time()
+#include <unistd.h> // for getpid()
+
+using namespace KMime;
+
+namespace KMime {
+
+QStrIList c_harsetCache;
+QStrIList l_anguageCache;
+
+const char* cachedCharset(const QCString &name)
+{
+ int idx=c_harsetCache.find(name.data());
+ if(idx>-1)
+ return c_harsetCache.at(idx);
+
+ c_harsetCache.append(name.upper().data());
+ //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl;
+ return c_harsetCache.last();
+}
+
+const char* cachedLanguage(const QCString &name)
+{
+ int idx=l_anguageCache.find(name.data());
+ if(idx>-1)
+ return l_anguageCache.at(idx);
+
+ l_anguageCache.append(name.upper().data());
+ //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl;
+ return l_anguageCache.last();
+}
+
+bool isUsAscii(const QString &s)
+{
+ uint sLength = s.length();
+ for (uint i=0; i<sLength; i++)
+ if (s.at(i).latin1()<=0) // c==0: non-latin1, c<0: non-us-ascii
+ return false;
+
+ return true;
+}
+
+// "(),.:;<>@[\]
+const uchar specialsMap[16] = {
+ 0x00, 0x00, 0x00, 0x00, // CTLs
+ 0x20, 0xCA, 0x00, 0x3A, // SPACE ... '?'
+ 0x80, 0x00, 0x00, 0x1C, // '@' ... '_'
+ 0x00, 0x00, 0x00, 0x00 // '`' ... DEL
+};
+
+// "(),:;<>@[\]/=?
+const uchar tSpecialsMap[16] = {
+ 0x00, 0x00, 0x00, 0x00, // CTLs
+ 0x20, 0xC9, 0x00, 0x3F, // SPACE ... '?'
+ 0x80, 0x00, 0x00, 0x1C, // '@' ... '_'
+ 0x00, 0x00, 0x00, 0x00 // '`' ... DEL
+};
+
+// all except specials, CTLs, SPACE.
+const uchar aTextMap[16] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x35, 0xFF, 0xC5,
+ 0x7F, 0xFF, 0xFF, 0xE3,
+ 0xFF, 0xFF, 0xFF, 0xFE
+};
+
+// all except tspecials, CTLs, SPACE.
+const uchar tTextMap[16] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x5F, 0x36, 0xFF, 0xC0,
+ 0x7F, 0xFF, 0xFF, 0xE3,
+ 0xFF, 0xFF, 0xFF, 0xFE
+};
+
+// none except a-zA-Z0-9!*+-/
+const uchar eTextMap[16] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x35, 0xFF, 0xC0,
+ 0x7F, 0xFF, 0xFF, 0xE0,
+ 0x7F, 0xFF, 0xFF, 0xE0
+};
+
+#if defined(_AIX) && defined(truncate)
+#undef truncate
+#endif
+
+QString decodeRFC2047String(const QCString &src, const char **usedCS,
+ const QCString &defaultCS, bool forceCS)
+{
+ QCString result, str;
+ QCString declaredCS;
+ char *pos, *dest, *beg, *end, *mid, *endOfLastEncWord=0;
+ char encoding = '\0';
+ bool valid, onlySpacesSinceLastWord=false;
+ const int maxLen=400;
+ int i;
+
+ if(src.find("=?") < 0)
+ result = src.copy();
+ else {
+ result.truncate(src.length());
+ for (pos=src.data(), dest=result.data(); *pos; pos++)
+ {
+ if (pos[0]!='=' || pos[1]!='?')
+ {
+ *dest++ = *pos;
+ if (onlySpacesSinceLastWord)
+ onlySpacesSinceLastWord = (pos[0]==' ' || pos[1]=='\t');
+ continue;
+ }
+ beg = pos+2;
+ end = beg;
+ valid = TRUE;
+ // parse charset name
+ declaredCS="";
+ for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(ispunct(*pos)||isalnum(*pos))); i++) {
+ declaredCS+=(*pos);
+ pos++;
+ }
+ if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE;
+ else
+ {
+ // get encoding and check delimiting question marks
+ encoding = toupper(pos[1]);
+ if (pos[2]!='?' || (encoding!='Q' && encoding!='B'))
+ valid = FALSE;
+ pos+=3;
+ i+=3;
+ }
+ if (valid)
+ {
+ mid = pos;
+ // search for end of encoded part
+ while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='='))
+ {
+ i++;
+ pos++;
+ }
+ end = pos+2;//end now points to the first char after the encoded string
+ if (i>=maxLen || !*pos) valid = FALSE;
+ }
+
+ if (valid) {
+ // cut all linear-white space between two encoded words
+ if (onlySpacesSinceLastWord)
+ dest=endOfLastEncWord;
+
+ if (mid < pos) {
+ str = QCString(mid, (int)(pos - mid + 1));
+ if (encoding == 'Q')
+ {
+ // decode quoted printable text
+ for (i=str.length()-1; i>=0; i--)
+ if (str[i]=='_') str[i]=' ';
+ str = KCodecs::quotedPrintableDecode(str);
+ }
+ else
+ {
+ str = KCodecs::base64Decode(str);
+ }
+ if (!str.isNull()) {
+ for (i=0; str[i]; i++) {
+ *dest++ = str[i];
+ }
+ }
+ }
+
+ endOfLastEncWord=dest;
+ onlySpacesSinceLastWord=true;
+
+ pos = end -1;
+ }
+ else
+ {
+ pos = beg - 2;
+ *dest++ = *pos++;
+ *dest++ = *pos;
+ }
+ }
+ *dest = '\0';
+ }
+
+ //find suitable QTextCodec
+ QTextCodec *codec=0;
+ bool ok=true;
+ if (forceCS || declaredCS.isEmpty()) {
+ codec=KGlobal::charsets()->codecForName(defaultCS);
+ (*usedCS)=cachedCharset(defaultCS);
+ }
+ else {
+ codec=KGlobal::charsets()->codecForName(declaredCS, ok);
+ if(!ok) { //no suitable codec found => use default charset
+ codec=KGlobal::charsets()->codecForName(defaultCS);
+ (*usedCS)=cachedCharset(defaultCS);
+ }
+ else
+ (*usedCS)=cachedCharset(declaredCS);
+ }
+
+ return codec->toUnicode(result.data(), result.length());
+}
+
+QString decodeRFC2047String(const QCString &src)
+{
+ const char *usedCS;
+ return decodeRFC2047String(src, &usedCS, "utf-8", false);
+}
+
+QCString encodeRFC2047String(const QString &src, const char *charset,
+ bool addressHeader, bool allow8BitHeaders)
+{
+ QCString encoded8Bit, result, usedCS;
+ unsigned int start=0,end=0;
+ bool nonAscii=false, ok=true, useQEncoding=false;
+ QTextCodec *codec=0;
+
+ usedCS=charset;
+ codec=KGlobal::charsets()->codecForName(usedCS, ok);
+
+ if(!ok) {
+ //no codec available => try local8Bit and hope the best ;-)
+ usedCS=KGlobal::locale()->encoding();
+ codec=KGlobal::charsets()->codecForName(usedCS, ok);
+ }
+
+ if (usedCS.find("8859-")>=0) // use "B"-Encoding for non iso-8859-x charsets
+ useQEncoding=true;
+
+ encoded8Bit=codec->fromUnicode(src);
+
+ if(allow8BitHeaders)
+ return encoded8Bit;
+
+ uint encoded8BitLength = encoded8Bit.length();
+ for (unsigned int i=0; i<encoded8BitLength; i++) {
+ if (encoded8Bit[i]==' ') // encoding starts at word boundaries
+ start = i+1;
+
+ // encode escape character, for japanese encodings...
+ if (((signed char)encoded8Bit[i]<0) || (encoded8Bit[i] == '\033') ||
+ (addressHeader && (strchr("\"()<>@,.;:\\[]=",encoded8Bit[i])!=0))) {
+ end = start; // non us-ascii char found, now we determine where to stop encoding
+ nonAscii=true;
+ break;
+ }
+ }
+
+ if (nonAscii) {
+ while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words
+ end++;
+
+ for (unsigned int x=end;x<encoded8Bit.length();x++)
+ if (((signed char)encoded8Bit[x]<0) || (encoded8Bit[x] == '\033') ||
+ (addressHeader && (strchr("\"()<>@,.;:\\[]=",encoded8Bit[x])!=0))) {
+ end = encoded8Bit.length(); // we found another non-ascii word
+
+ while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words
+ end++;
+ }
+
+ result = encoded8Bit.left(start)+"=?"+usedCS;
+
+ if (useQEncoding) {
+ result += "?Q?";
+
+ char c,hexcode; // implementation of the "Q"-encoding described in RFC 2047
+ for (unsigned int i=start;i<end;i++) {
+ c = encoded8Bit[i];
+ if (c == ' ') // make the result readable with not MIME-capable readers
+ result+='_';
+ else
+ if (((c>='a')&&(c<='z'))|| // paranoid mode, we encode *all* special characters to avoid problems
+ ((c>='A')&&(c<='Z'))|| // with "From" & "To" headers
+ ((c>='0')&&(c<='9')))
+ result+=c;
+ else {
+ result += "="; // "stolen" from KMail ;-)
+ hexcode = ((c & 0xF0) >> 4) + 48;
+ if (hexcode >= 58) hexcode += 7;
+ result += hexcode;
+ hexcode = (c & 0x0F) + 48;
+ if (hexcode >= 58) hexcode += 7;
+ result += hexcode;
+ }
+ }
+ } else {
+ result += "?B?"+KCodecs::base64Encode(encoded8Bit.mid(start,end-start), false);
+ }
+
+ result +="?=";
+ result += encoded8Bit.right(encoded8Bit.length()-end);
+ }
+ else
+ result = encoded8Bit;
+
+ return result;
+}
+
+QCString uniqueString()
+{
+ static char chars[] = "0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ time_t now;
+ QCString ret;
+ char p[11];
+ int pos, ran;
+ unsigned int timeval;
+
+ p[10]='\0';
+ now=time(0);
+ ran=1+(int) (1000.0*rand()/(RAND_MAX+1.0));
+ timeval=(now/ran)+getpid();
+
+ for(int i=0; i<10; i++){
+ pos=(int) (61.0*rand()/(RAND_MAX+1.0));
+ //kdDebug(5003) << pos << endl;
+ p[i]=chars[pos];
+ }
+ ret.sprintf("%d.%s", timeval, p);
+
+ return ret;
+}
+
+
+QCString multiPartBoundary()
+{
+ QCString ret;
+ ret="nextPart"+uniqueString();
+ return ret;
+}
+
+QCString extractHeader(const QCString &src, const char *name)
+{
+ QCString n=QCString(name)+":";
+ int pos1=-1, pos2=0, len=src.length()-1;
+ bool folded(false);
+
+ if (n.lower() == src.left(n.length()).lower()) {
+ pos1 = 0;
+ } else {
+ n.prepend("\n");
+ pos1 = src.find(n,0,false);
+ }
+
+ if (pos1>-1) { //there is a header with the given name
+ pos1+=n.length(); //skip the name
+ // skip the usual space after the colon
+ if ( src.at( pos1 ) == ' ' )
+ ++pos1;
+ pos2=pos1;
+
+ if (src[pos2]!='\n') { // check if the header is not empty
+ while(1) {
+ pos2=src.find("\n", pos2+1);
+ if(pos2==-1 || pos2==len || ( src[pos2+1]!=' ' && src[pos2+1]!='\t') ) //break if we reach the end of the string, honor folded lines
+ break;
+ else
+ folded = true;
+ }
+ }
+
+ if(pos2<0) pos2=len+1; //take the rest of the string
+
+ if (!folded)
+ return src.mid(pos1, pos2-pos1);
+ else
+ return (src.mid(pos1, pos2-pos1).replace(QRegExp("\\s*\\n\\s*")," "));
+ }
+ else {
+ return QCString(0); //header not found
+ }
+}
+
+
+QCString CRLFtoLF(const QCString &s)
+{
+ QCString ret=s.copy();
+ ret.replace(QRegExp("\\r\\n"), "\n");
+ return ret;
+}
+
+
+QCString CRLFtoLF(const char *s)
+{
+ QCString ret=s;
+ ret.replace(QRegExp("\\r\\n"), "\n");
+ return ret;
+}
+
+
+QCString LFtoCRLF(const QCString &s)
+{
+ QCString ret=s.copy();
+ ret.replace(QRegExp("\\n"), "\r\n");
+ return ret;
+}
+
+
+void removeQuots(QCString &str)
+{
+ bool inQuote=false;
+
+ for (int i=0; i < (int)str.length(); i++) {
+ if (str[i] == '"') {
+ str.remove(i,1);
+ i--;
+ inQuote = !inQuote;
+ } else {
+ if (inQuote && (str[i] == '\\'))
+ str.remove(i,1);
+ }
+ }
+}
+
+
+void removeQuots(QString &str)
+{
+ bool inQuote=false;
+
+ for (int i=0; i < (int)str.length(); i++) {
+ if (str[i] == '"') {
+ str.remove(i,1);
+ i--;
+ inQuote = !inQuote;
+ } else {
+ if (inQuote && (str[i] == '\\'))
+ str.remove(i,1);
+ }
+ }
+}
+
+
+void addQuotes(QCString &str, bool forceQuotes)
+{
+ bool needsQuotes=false;
+ for (unsigned int i=0; i < str.length(); i++) {
+ if (strchr("()<>@,.;:[]=\\\"",str[i])!=0)
+ needsQuotes = true;
+ if (str[i]=='\\' || str[i]=='\"') {
+ str.insert(i, '\\');
+ i++;
+ }
+ }
+
+ if (needsQuotes || forceQuotes) {
+ str.insert(0,'\"');
+ str.append("\"");
+ }
+}
+
+int DateFormatter::mDaylight = -1;
+DateFormatter::DateFormatter(FormatType fType)
+ : mFormat( fType ), mCurrentTime( 0 )
+{
+
+}
+
+DateFormatter::~DateFormatter()
+{/*empty*/}
+
+DateFormatter::FormatType
+DateFormatter::getFormat() const
+{
+ return mFormat;
+}
+
+void
+DateFormatter::setFormat( FormatType t )
+{
+ mFormat = t;
+}
+
+QString
+DateFormatter::dateString( time_t otime , const QString& lang ,
+ bool shortFormat, bool includeSecs ) const
+{
+ switch ( mFormat ) {
+ case Fancy:
+ return fancy( otime );
+ break;
+ case Localized:
+ return localized( otime, shortFormat, includeSecs, lang );
+ break;
+ case CTime:
+ return cTime( otime );
+ break;
+ case Iso:
+ return isoDate( otime );
+ break;
+ case Custom:
+ return custom( otime );
+ break;
+ }
+ return QString::null;
+}
+
+QString
+DateFormatter::dateString(const QDateTime& dtime, const QString& lang,
+ bool shortFormat, bool includeSecs ) const
+{
+ return DateFormatter::dateString( qdateToTimeT(dtime), lang, shortFormat, includeSecs );
+}
+
+QCString
+DateFormatter::rfc2822(time_t otime) const
+{
+ QDateTime tmp;
+ QCString ret;
+
+ tmp.setTime_t(otime);
+
+ ret = tmp.toString("ddd, dd MMM yyyy hh:mm:ss ").latin1();
+ ret += zone(otime);
+
+ return ret;
+}
+
+QString
+DateFormatter::custom(time_t t) const
+{
+ if ( mCustomFormat.isEmpty() )
+ return QString::null;
+
+ int z = mCustomFormat.find("Z");
+ QDateTime d;
+ QString ret = mCustomFormat;
+
+ d.setTime_t(t);
+ if ( z != -1 ) {
+ ret.replace(z,1,zone(t));
+ }
+
+ ret = d.toString(ret);
+
+ return ret;
+}
+
+void
+DateFormatter::setCustomFormat(const QString& format)
+{
+ mCustomFormat = format;
+ mFormat = Custom;
+}
+
+QString
+DateFormatter::getCustomFormat() const
+{
+ return mCustomFormat;
+}
+
+
+QCString
+DateFormatter::zone(time_t otime) const
+{
+ QCString ret;
+#if defined(HAVE_TIMEZONE) || defined(HAVE_TM_GMTOFF)
+ struct tm *local = localtime( &otime );
+#endif
+
+#if defined(HAVE_TIMEZONE)
+
+ //hmm, could make hours & mins static
+ int secs = abs(timezone);
+ int neg = (timezone>0)?1:0;
+ int hours = secs/3600;
+ int mins = (secs - hours*3600)/60;
+
+ // adjust to daylight
+ if ( local->tm_isdst > 0 ) {
+ mDaylight = 1;
+ if ( neg )
+ --hours;
+ else
+ ++hours;
+ } else
+ mDaylight = 0;
+
+ ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
+
+#elif defined(HAVE_TM_GMTOFF)
+
+ int secs = abs( local->tm_gmtoff );
+ int neg = (local->tm_gmtoff<0)?1:0; //no, I don't know why it's backwards :o
+ int hours = secs/3600;
+ int mins = (secs - hours*3600)/60;
+
+ if ( local->tm_isdst > 0 )
+ mDaylight = 1;
+ else
+ mDaylight = 0;
+
+ ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
+
+#else
+
+ QDateTime d1 = QDateTime::fromString( asctime(gmtime(&otime)) );
+ QDateTime d2 = QDateTime::fromString( asctime(localtime(&otime)) );
+ int secs = d1.secsTo(d2);
+ int neg = (secs<0)?1:0;
+ secs = abs(secs);
+ int hours = secs/3600;
+ int mins = (secs - hours*3600)/60;
+ // daylight should be already taken care of here
+ ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
+
+#endif /* HAVE_TIMEZONE */
+
+ return ret;
+}
+
+time_t
+DateFormatter::qdateToTimeT(const QDateTime& dt) const
+{
+ QDateTime epoch( QDate(1970, 1,1), QTime(00,00,00) );
+ time_t otime;
+ time( &otime );
+
+ QDateTime d1 = QDateTime::fromString( asctime(gmtime(&otime)) );
+ QDateTime d2 = QDateTime::fromString( asctime(localtime(&otime)) );
+ time_t drf = epoch.secsTo( dt ) - d1.secsTo( d2 );
+
+ return drf;
+}
+
+QString
+DateFormatter::fancy(time_t otime) const
+{
+ KLocale *locale = KGlobal::locale();
+
+ if ( otime <= 0 )
+ return i18n( "unknown" );
+
+ if ( !mCurrentTime ) {
+ time( &mCurrentTime );
+ mDate.setTime_t( mCurrentTime );
+ }
+
+ QDateTime old;
+ old.setTime_t( otime );
+
+ // not more than an hour in the future
+ if ( mCurrentTime + 60 * 60 >= otime ) {
+ time_t diff = mCurrentTime - otime;
+
+ if ( diff < 24 * 60 * 60 ) {
+ if ( old.date().year() == mDate.date().year() &&
+ old.date().dayOfYear() == mDate.date().dayOfYear() )
+ return i18n( "Today %1" ).arg( locale->
+ formatTime( old.time(), true ) );
+ }
+ if ( diff < 2 * 24 * 60 * 60 ) {
+ QDateTime yesterday( mDate.addDays( -1 ) );
+ if ( old.date().year() == yesterday.date().year() &&
+ old.date().dayOfYear() == yesterday.date().dayOfYear() )
+ return i18n( "Yesterday %1" ).arg( locale->
+ formatTime( old.time(), true) );
+ }
+ for ( int i = 3; i < 7; i++ )
+ if ( diff < i * 24 * 60 * 60 ) {
+ QDateTime weekday( mDate.addDays( -i + 1 ) );
+ if ( old.date().year() == weekday.date().year() &&
+ old.date().dayOfYear() == weekday.date().dayOfYear() )
+ return i18n( "1. weekday, 2. time", "%1 %2" ).
+#if KDE_IS_VERSION( 3, 1, 90 )
+ arg( locale->calendar()->weekDayName( old.date() ) ).
+#else
+ arg( locale->weekDayName( old.date().dayOfWeek() ) ).
+#endif
+ arg( locale->formatTime( old.time(), true) );
+ }
+ }
+
+ return locale->formatDateTime( old );
+
+}
+
+QString
+DateFormatter::localized(time_t otime, bool shortFormat, bool includeSecs,
+ const QString& localeLanguage ) const
+{
+ QDateTime tmp;
+ QString ret;
+ KLocale *locale = KGlobal::locale();
+
+ tmp.setTime_t( otime );
+
+
+ if ( !localeLanguage.isEmpty() ) {
+ locale=new KLocale(localeLanguage);
+ locale->setLanguage(localeLanguage);
+ locale->setCountry(localeLanguage);
+ ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
+ delete locale;
+ } else {
+ ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
+ }
+
+ return ret;
+}
+
+QString
+DateFormatter::cTime(time_t otime) const
+{
+ return QString::fromLatin1( ctime( &otime ) ).stripWhiteSpace() ;
+}
+
+QString
+DateFormatter::isoDate(time_t otime) const
+{
+ char cstr[64];
+ strftime( cstr, 63, "%Y-%m-%d %H:%M:%S", localtime(&otime) );
+ return QString( cstr );
+}
+
+
+void
+DateFormatter::reset()
+{
+ mCurrentTime = 0;
+}
+
+QString
+DateFormatter::formatDate(DateFormatter::FormatType t, time_t otime,
+ const QString& data, bool shortFormat, bool includeSecs )
+{
+ DateFormatter f( t );
+ if ( t == DateFormatter::Custom ) {
+ f.setCustomFormat( data );
+ }
+ return f.dateString( otime, data, shortFormat, includeSecs );
+}
+
+QString
+DateFormatter::formatCurrentDate( DateFormatter::FormatType t, const QString& data,
+ bool shortFormat, bool includeSecs )
+{
+ DateFormatter f( t );
+ if ( t == DateFormatter::Custom ) {
+ f.setCustomFormat( data );
+ }
+ return f.dateString( time(0), data, shortFormat, includeSecs );
+}
+
+QCString
+DateFormatter::rfc2822FormatDate( time_t t )
+{
+ DateFormatter f;
+ return f.rfc2822( t );
+}
+
+bool
+DateFormatter::isDaylight()
+{
+ if ( mDaylight == -1 ) {
+ time_t ntime = time( 0 );
+ struct tm *local = localtime( &ntime );
+ if ( local->tm_isdst > 0 ) {
+ mDaylight = 1;
+ return true;
+ } else {
+ mDaylight = 0;
+ return false;
+ }
+ } else if ( mDaylight != 0 )
+ return true;
+ else
+ return false;
+}
+
+} // namespace KMime