21 #include "kmime_util.h"
24 #include <tdeglobal.h>
25 #include <tdelocale.h>
26 #include <kcharsets.h>
27 #include <tdeversion.h>
28 #if KDE_IS_VERSION( 3, 1, 90 )
29 #include <kcalendarsystem.h>
32 #include <tqtextcodec.h>
33 #include <tqstrlist.h>
35 #include <tqdatetime.h>
42 using namespace KMime;
46 TQStrIList c_harsetCache;
47 TQStrIList l_anguageCache;
49 const char* cachedCharset(
const TQCString &name)
51 int idx=c_harsetCache.find(name.data());
53 return c_harsetCache.at(idx);
55 c_harsetCache.append(name.upper().data());
57 return c_harsetCache.last();
60 const char* cachedLanguage(
const TQCString &name)
62 int idx=l_anguageCache.find(name.data());
64 return l_anguageCache.at(idx);
66 l_anguageCache.append(name.upper().data());
68 return l_anguageCache.last();
71 bool isUsAscii(
const TQString &s)
73 uint sLength = s.length();
74 for (uint i=0; i<sLength; i++)
75 if (s.at(i).latin1()<=0)
82 const uchar specialsMap[16] = {
83 0x00, 0x00, 0x00, 0x00,
84 0x20, 0xCA, 0x00, 0x3A,
85 0x80, 0x00, 0x00, 0x1C,
86 0x00, 0x00, 0x00, 0x00
90 const uchar tSpecialsMap[16] = {
91 0x00, 0x00, 0x00, 0x00,
92 0x20, 0xC9, 0x00, 0x3F,
93 0x80, 0x00, 0x00, 0x1C,
94 0x00, 0x00, 0x00, 0x00
98 const uchar aTextMap[16] = {
99 0x00, 0x00, 0x00, 0x00,
100 0x5F, 0x35, 0xFF, 0xC5,
101 0x7F, 0xFF, 0xFF, 0xE3,
102 0xFF, 0xFF, 0xFF, 0xFE
106 const uchar tTextMap[16] = {
107 0x00, 0x00, 0x00, 0x00,
108 0x5F, 0x36, 0xFF, 0xC0,
109 0x7F, 0xFF, 0xFF, 0xE3,
110 0xFF, 0xFF, 0xFF, 0xFE
114 const uchar eTextMap[16] = {
115 0x00, 0x00, 0x00, 0x00,
116 0x40, 0x35, 0xFF, 0xC0,
117 0x7F, 0xFF, 0xFF, 0xE0,
118 0x7F, 0xFF, 0xFF, 0xE0
121 #if defined(_AIX) && defined(truncate)
125 TQString decodeRFC2047String(
const TQCString &src,
const char **usedCS,
126 const TQCString &defaultCS,
bool forceCS)
128 TQCString result, str;
129 TQCString declaredCS;
130 const char *beg, *end, *mid, *pos=0;
131 char *dest, *endOfLastEncWord=0;
132 char encoding =
'\0';
133 bool valid, onlySpacesSinceLastWord=
false;
134 const int maxLen=400;
137 if(src.find(
"=?") < 0)
140 result.truncate(src.length());
141 for (pos=src.data(), dest=result.data(); *pos; pos++)
143 if (pos[0]!=
'=' || pos[1]!=
'?')
146 if (onlySpacesSinceLastWord)
147 onlySpacesSinceLastWord = (pos[0]==
' ' || pos[1]==
'\t');
155 for (i=2,pos+=2; i<maxLen && (*pos!=
'?'&&(ispunct(*pos)||isalnum(*pos))); i++) {
159 if (*pos!=
'?' || i<4 || i>=maxLen) valid = FALSE;
163 encoding = toupper(pos[1]);
164 if (pos[2]!=
'?' || (encoding!=
'Q' && encoding!=
'B'))
173 while (i<maxLen && *pos && !(*pos==
'?' && *(pos+1)==
'='))
179 if (i>=maxLen || !*pos) valid = FALSE;
184 if (onlySpacesSinceLastWord)
185 dest=endOfLastEncWord;
188 str = TQCString(mid, (
int)(pos - mid + 1));
192 for (i=str.length()-1; i>=0; i--)
193 if (str[i]==
'_') str[i]=
' ';
194 str = KCodecs::quotedPrintableDecode(str);
198 str = KCodecs::base64Decode(str);
201 for (i=0; str[i]; i++) {
207 endOfLastEncWord=dest;
208 onlySpacesSinceLastWord=
true;
223 TQTextCodec *codec=0;
225 if (forceCS || declaredCS.isEmpty()) {
226 codec=TDEGlobal::charsets()->codecForName(defaultCS);
227 (*usedCS)=cachedCharset(defaultCS);
230 codec=TDEGlobal::charsets()->codecForName(declaredCS, ok);
232 codec=TDEGlobal::charsets()->codecForName(defaultCS);
233 (*usedCS)=cachedCharset(defaultCS);
236 (*usedCS)=cachedCharset(declaredCS);
239 return codec->toUnicode(result.data(), result.length());
242 TQString decodeRFC2047String(
const TQCString &src)
245 return decodeRFC2047String(src, &usedCS,
"utf-8",
false);
248 TQCString encodeRFC2047String(
const TQString &src,
const char *charset,
249 bool addressHeader,
bool allow8BitHeaders)
251 TQCString encoded8Bit, result, usedCS;
252 unsigned int start=0,end=0;
253 bool nonAscii=
false, ok=
true, useTQEncoding=
false;
254 TQTextCodec *codec=0;
257 codec=TDEGlobal::charsets()->codecForName(usedCS, ok);
261 usedCS=TDEGlobal::locale()->encoding();
262 codec=TDEGlobal::charsets()->codecForName(usedCS, ok);
265 if (usedCS.find(
"8859-")>=0)
268 encoded8Bit=codec->fromUnicode(src);
273 uint encoded8BitLength = encoded8Bit.length();
274 for (
unsigned int i=0; i<encoded8BitLength; i++) {
275 if (encoded8Bit[i]==
' ')
279 if (((
signed char)encoded8Bit[i]<0) || (encoded8Bit[i] ==
'\033') ||
280 (addressHeader && (strchr(
"\"()<>@,.;:\\[]=",encoded8Bit[i])!=0))) {
288 while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=
' '))
291 for (
unsigned int x=end;x<encoded8Bit.length();x++)
292 if (((
signed char)encoded8Bit[x]<0) || (encoded8Bit[x] ==
'\033') ||
293 (addressHeader && (strchr(
"\"()<>@,.;:\\[]=",encoded8Bit[x])!=0))) {
294 end = encoded8Bit.length();
296 while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=
' '))
300 result = encoded8Bit.left(start)+
"=?"+usedCS;
306 for (
unsigned int i=start;i<end;i++) {
311 if (((c>=
'a')&&(c<=
'z'))||
312 ((c>=
'A')&&(c<=
'Z'))||
313 ((c>=
'0')&&(c<=
'9')))
317 hexcode = ((c & 0xF0) >> 4) + 48;
318 if (hexcode >= 58) hexcode += 7;
320 hexcode = (c & 0x0F) + 48;
321 if (hexcode >= 58) hexcode += 7;
326 result +=
"?B?"+KCodecs::base64Encode(encoded8Bit.mid(start,end-start),
false);
330 result += encoded8Bit.right(encoded8Bit.length()-end);
333 result = encoded8Bit;
338 TQCString uniqueString()
340 static char chars[] =
"0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
345 unsigned int timeval;
349 ran=1+(int) (1000.0*rand()/(RAND_MAX+1.0));
350 timeval=(now/ran)+getpid();
352 for(
int i=0; i<10; i++){
353 pos=(int) (61.0*rand()/(RAND_MAX+1.0));
357 ret.sprintf(
"%d.%s", timeval, p);
363 TQCString multiPartBoundary()
366 ret=
"nextPart"+uniqueString();
370 TQCString extractHeader(
const TQCString &src,
const char *name)
372 TQCString n=TQCString(name)+
":";
373 int pos1=-1, pos2=0, len=src.length()-1;
376 if (n.lower() == src.left(n.length()).lower()) {
380 pos1 = src.find(n.data(),0,
false);
386 if ( src.at( pos1 ) ==
' ' )
390 if (src[pos2]!=
'\n') {
392 pos2=src.find(
"\n", pos2+1);
393 if(pos2==-1 || pos2==len || ( src[pos2+1]!=
' ' && src[pos2+1]!=
'\t') )
400 if(pos2<0) pos2=len+1;
403 return src.mid(pos1, pos2-pos1);
405 return (src.mid(pos1, pos2-pos1).replace(TQRegExp(
"\\s*\\n\\s*"),
" "));
413 TQCString CRLFtoLF(
const TQCString &s)
415 TQCString ret=s.copy();
416 ret.replace(TQRegExp(
"\\r\\n"),
"\n");
421 TQCString CRLFtoLF(
const char *s)
424 ret.replace(TQRegExp(
"\\r\\n"),
"\n");
429 TQCString LFtoCRLF(
const TQCString &s)
431 TQCString ret=s.copy();
432 ret.replace(TQRegExp(
"\\n"),
"\r\n");
437 void removeQuots(TQCString &str)
440 str.replace(TQRegExp(
"[\\\"]"),
"");
444 void removeQuots(TQString &str)
447 str.replace(TQRegExp(
"[\\\"]"),
"");
451 void addQuotes(TQCString &str,
bool forceQuotes)
453 if ( forceQuotes || TQString(str).contains( TQRegExp( TQString(
"\"|\\\\|=|\\]|\\[|:|;|,|\\.|,|@|<|>|\\)|\\(" ) ) ) ) {
455 str.replace(TQRegExp(
"([\\\"])"),
"\\\\1");
462 int DateFormatter::mDaylight = -1;
464 : mFormat( fType ), mCurrentTime( 0 )
469 DateFormatter::~DateFormatter()
472 DateFormatter::FormatType
486 bool shortFormat,
bool includeSecs )
const
490 return fancy( otime );
493 return localized( otime, shortFormat, includeSecs, lang );
496 return cTime( otime );
510 bool shortFormat,
bool includeSecs )
const
521 tmp.setTime_t(otime);
523 ret = tmp.toString(
"ddd, dd MMM yyyy hh:mm:ss ").latin1();
532 if ( mCustomFormat.isEmpty() )
535 int z = mCustomFormat.find(
"Z");
537 TQString ret = mCustomFormat;
541 ret.replace(z,1,
zone(t));
544 ret = d.toString(ret);
552 mCustomFormat = format;
557 DateFormatter::getCustomFormat()
const
559 return mCustomFormat;
567 #if defined(HAVE_TIMEZONE) || defined(HAVE_TM_GMTOFF)
568 struct tm *local = localtime( &otime );
571 #if defined(HAVE_TIMEZONE)
574 int secs = abs(timezone);
575 int neg = (timezone>0)?1:0;
576 int hours = secs/3600;
577 int mins = (secs - hours*3600)/60;
580 if ( local->tm_isdst > 0 ) {
589 ret.sprintf(
"%c%.2d%.2d",(neg)?
'-':
'+', hours, mins);
591 #elif defined(HAVE_TM_GMTOFF)
593 int secs = abs( local->tm_gmtoff );
594 int neg = (local->tm_gmtoff<0)?1:0;
595 int hours = secs/3600;
596 int mins = (secs - hours*3600)/60;
598 if ( local->tm_isdst > 0 )
603 ret.sprintf(
"%c%.2d%.2d",(neg)?
'-':
'+', hours, mins);
607 TQDateTime d1 = TQDateTime::fromString( asctime(gmtime(&otime)) );
608 TQDateTime d2 = TQDateTime::fromString( asctime(localtime(&otime)) );
609 int secs = d1.secsTo(d2);
610 int neg = (secs<0)?1:0;
612 int hours = secs/3600;
613 int mins = (secs - hours*3600)/60;
615 ret.sprintf(
"%c%.2d%.2d",(neg)?
'-':
'+', hours, mins);
623 DateFormatter::qdateToTimeT(
const TQDateTime& dt)
const
625 TQDateTime epoch( TQDate(1970, 1,1), TQTime(00,00,00) );
629 TQDateTime d1 = TQDateTime::fromString( asctime(gmtime(&otime)) );
630 TQDateTime d2 = TQDateTime::fromString( asctime(localtime(&otime)) );
631 time_t drf = epoch.secsTo( dt ) - d1.secsTo( d2 );
639 TDELocale *locale = TDEGlobal::locale();
642 return i18n(
"unknown" );
644 if ( !mCurrentTime ) {
645 time( &mCurrentTime );
646 mDate.setTime_t( mCurrentTime );
650 old.setTime_t( otime );
653 if ( mCurrentTime + 60 * 60 >= otime ) {
654 time_t diff = mCurrentTime - otime;
656 if ( diff < 24 * 60 * 60 ) {
657 if ( old.date().year() == mDate.date().year() &&
658 old.date().dayOfYear() == mDate.date().dayOfYear() )
659 return i18n(
"Today %1" ).arg( locale->
660 formatTime( old.time(),
true ) );
662 if ( diff < 2 * 24 * 60 * 60 ) {
663 TQDateTime yesterday( mDate.addDays( -1 ) );
664 if ( old.date().year() == yesterday.date().year() &&
665 old.date().dayOfYear() == yesterday.date().dayOfYear() )
666 return i18n(
"Yesterday %1" ).arg( locale->
667 formatTime( old.time(),
true) );
669 for (
int i = 3; i < 7; i++ )
670 if ( diff < i * 24 * 60 * 60 ) {
671 TQDateTime weekday( mDate.addDays( -i + 1 ) );
672 if ( old.date().year() == weekday.date().year() &&
673 old.date().dayOfYear() == weekday.date().dayOfYear() )
674 return i18n(
"1. weekday, 2. time",
"%1 %2" ).
675 #
if KDE_IS_VERSION( 3, 1, 90 )
676 arg( locale->calendar()->weekDayName( old.date() ) ).
678 arg( locale->weekDayName( old.date().dayOfWeek() ) ).
680 arg( locale->formatTime( old.time(),
true) );
684 return locale->formatDateTime( old );
690 const TQString& localeLanguage )
const
694 TDELocale *locale = TDEGlobal::locale();
696 tmp.setTime_t( otime );
699 if ( !localeLanguage.isEmpty() ) {
700 locale=
new TDELocale(localeLanguage);
701 locale->setLanguage(localeLanguage);
702 locale->setCountry(localeLanguage);
703 ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
706 ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
715 return TQString::fromLatin1( ctime( &otime ) ).stripWhiteSpace() ;
722 strftime( cstr, 63,
"%Y-%m-%d %H:%M:%S", localtime(&otime) );
723 return TQString( cstr );
735 const TQString& data,
bool shortFormat,
bool includeSecs )
738 if ( t == DateFormatter::Custom ) {
741 return f.
dateString( otime, data, shortFormat, includeSecs );
746 bool shortFormat,
bool includeSecs )
749 if ( t == DateFormatter::Custom ) {
752 return f.
dateString( time(0), data, shortFormat, includeSecs );
763 DateFormatter::isDaylight()
765 if ( mDaylight == -1 ) {
766 time_t ntime = time( 0 );
767 struct tm *local = localtime( &ntime );
768 if ( local->tm_isdst > 0 ) {
775 }
else if ( mDaylight != 0 )