libkmime

kmime_util.cpp
1 /*
2  kmime_util.cpp
3 
4  KMime, the KDE internet mail/usenet news message library.
5  Copyright (c) 2001 the KMime authors.
6  See file AUTHORS for details
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
15 */
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20 
21 #include "kmime_util.h"
22 
23 #include <kmdcodec.h> // for KCodec::{quotedPrintableDe,base64{En,De}}code
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>
30 #endif
31 
32 #include <tqtextcodec.h>
33 #include <tqstrlist.h> // for TQStrIList
34 #include <tqregexp.h>
35 #include <tqdatetime.h>
36 
37 #include <stdlib.h>
38 #include <ctype.h>
39 #include <time.h> // for time()
40 #include <unistd.h> // for getpid()
41 
42 using namespace KMime;
43 
44 namespace KMime {
45 
46 TQStrIList c_harsetCache;
47 TQStrIList l_anguageCache;
48 
49 const char* cachedCharset(const TQCString &name)
50 {
51  int idx=c_harsetCache.find(name.data());
52  if(idx>-1)
53  return c_harsetCache.at(idx);
54 
55  c_harsetCache.append(name.upper().data());
56  //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl;
57  return c_harsetCache.last();
58 }
59 
60 const char* cachedLanguage(const TQCString &name)
61 {
62  int idx=l_anguageCache.find(name.data());
63  if(idx>-1)
64  return l_anguageCache.at(idx);
65 
66  l_anguageCache.append(name.upper().data());
67  //kdDebug() << "KNMimeBase::cachedCharset() number of cs " << c_harsetCache.count() << endl;
68  return l_anguageCache.last();
69 }
70 
71 bool isUsAscii(const TQString &s)
72 {
73  uint sLength = s.length();
74  for (uint i=0; i<sLength; i++)
75  if (s.at(i).latin1()<=0) // c==0: non-latin1, c<0: non-us-ascii
76  return false;
77 
78  return true;
79 }
80 
81 // "(),.:;<>@[\]
82 const uchar specialsMap[16] = {
83  0x00, 0x00, 0x00, 0x00, // CTLs
84  0x20, 0xCA, 0x00, 0x3A, // SPACE ... '?'
85  0x80, 0x00, 0x00, 0x1C, // '@' ... '_'
86  0x00, 0x00, 0x00, 0x00 // '`' ... DEL
87 };
88 
89 // "(),:;<>@[\]/=?
90 const uchar tSpecialsMap[16] = {
91  0x00, 0x00, 0x00, 0x00, // CTLs
92  0x20, 0xC9, 0x00, 0x3F, // SPACE ... '?'
93  0x80, 0x00, 0x00, 0x1C, // '@' ... '_'
94  0x00, 0x00, 0x00, 0x00 // '`' ... DEL
95 };
96 
97 // all except specials, CTLs, SPACE.
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
103 };
104 
105 // all except tspecials, CTLs, SPACE.
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
111 };
112 
113 // none except a-zA-Z0-9!*+-/
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
119 };
120 
121 #if defined(_AIX) && defined(truncate)
122 #undef truncate
123 #endif
124 
125 TQString decodeRFC2047String(const TQCString &src, const char **usedCS,
126  const TQCString &defaultCS, bool forceCS)
127 {
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;
135  int i;
136 
137  if(src.find("=?") < 0)
138  result = src.copy();
139  else {
140  result.truncate(src.length());
141  for (pos=src.data(), dest=result.data(); *pos; pos++)
142  {
143  if (pos[0]!='=' || pos[1]!='?')
144  {
145  *dest++ = *pos;
146  if (onlySpacesSinceLastWord)
147  onlySpacesSinceLastWord = (pos[0]==' ' || pos[1]=='\t');
148  continue;
149  }
150  beg = pos+2;
151  end = beg;
152  valid = TRUE;
153  // parse charset name
154  declaredCS="";
155  for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(ispunct(*pos)||isalnum(*pos))); i++) {
156  declaredCS+=(*pos);
157  pos++;
158  }
159  if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE;
160  else
161  {
162  // get encoding and check delimiting question marks
163  encoding = toupper(pos[1]);
164  if (pos[2]!='?' || (encoding!='Q' && encoding!='B'))
165  valid = FALSE;
166  pos+=3;
167  i+=3;
168  }
169  if (valid)
170  {
171  mid = pos;
172  // search for end of encoded part
173  while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='='))
174  {
175  i++;
176  pos++;
177  }
178  end = pos+2;//end now points to the first char after the encoded string
179  if (i>=maxLen || !*pos) valid = FALSE;
180  }
181 
182  if (valid) {
183  // cut all linear-white space between two encoded words
184  if (onlySpacesSinceLastWord)
185  dest=endOfLastEncWord;
186 
187  if (mid < pos) {
188  str = TQCString(mid, (int)(pos - mid + 1));
189  if (encoding == 'Q')
190  {
191  // decode quoted printable text
192  for (i=str.length()-1; i>=0; i--)
193  if (str[i]=='_') str[i]=' ';
194  str = KCodecs::quotedPrintableDecode(str);
195  }
196  else
197  {
198  str = KCodecs::base64Decode(str);
199  }
200  if (!str.isNull()) {
201  for (i=0; str[i]; i++) {
202  *dest++ = str[i];
203  }
204  }
205  }
206 
207  endOfLastEncWord=dest;
208  onlySpacesSinceLastWord=true;
209 
210  pos = end -1;
211  }
212  else
213  {
214  pos = beg - 2;
215  *dest++ = *pos++;
216  *dest++ = *pos;
217  }
218  }
219  *dest = '\0';
220  }
221 
222  //find suitable TQTextCodec
223  TQTextCodec *codec=0;
224  bool ok=true;
225  if (forceCS || declaredCS.isEmpty()) {
226  codec=TDEGlobal::charsets()->codecForName(defaultCS);
227  (*usedCS)=cachedCharset(defaultCS);
228  }
229  else {
230  codec=TDEGlobal::charsets()->codecForName(declaredCS, ok);
231  if(!ok) { //no suitable codec found => use default charset
232  codec=TDEGlobal::charsets()->codecForName(defaultCS);
233  (*usedCS)=cachedCharset(defaultCS);
234  }
235  else
236  (*usedCS)=cachedCharset(declaredCS);
237  }
238 
239  return codec->toUnicode(result.data(), result.length());
240 }
241 
242 TQString decodeRFC2047String(const TQCString &src)
243 {
244  const char *usedCS;
245  return decodeRFC2047String(src, &usedCS, "utf-8", false);
246 }
247 
248 TQCString encodeRFC2047String(const TQString &src, const char *charset,
249  bool addressHeader, bool allow8BitHeaders)
250 {
251  TQCString encoded8Bit, result, usedCS;
252  unsigned int start=0,end=0;
253  bool nonAscii=false, ok=true, useTQEncoding=false;
254  TQTextCodec *codec=0;
255 
256  usedCS=charset;
257  codec=TDEGlobal::charsets()->codecForName(usedCS, ok);
258 
259  if(!ok) {
260  //no codec available => try local8Bit and hope the best ;-)
261  usedCS=TDEGlobal::locale()->encoding();
262  codec=TDEGlobal::charsets()->codecForName(usedCS, ok);
263  }
264 
265  if (usedCS.find("8859-")>=0) // use "B"-Encoding for non iso-8859-x charsets
266  useTQEncoding=true;
267 
268  encoded8Bit=codec->fromUnicode(src);
269 
270  if(allow8BitHeaders)
271  return encoded8Bit;
272 
273  uint encoded8BitLength = encoded8Bit.length();
274  for (unsigned int i=0; i<encoded8BitLength; i++) {
275  if (encoded8Bit[i]==' ') // encoding starts at word boundaries
276  start = i+1;
277 
278  // encode escape character, for japanese encodings...
279  if (((signed char)encoded8Bit[i]<0) || (encoded8Bit[i] == '\033') ||
280  (addressHeader && (strchr("\"()<>@,.;:\\[]=",encoded8Bit[i])!=0))) {
281  end = start; // non us-ascii char found, now we determine where to stop encoding
282  nonAscii=true;
283  break;
284  }
285  }
286 
287  if (nonAscii) {
288  while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words
289  end++;
290 
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(); // we found another non-ascii word
295 
296  while ((end<encoded8Bit.length())&&(encoded8Bit[end]!=' ')) // we encode complete words
297  end++;
298  }
299 
300  result = encoded8Bit.left(start)+"=?"+usedCS;
301 
302  if (useTQEncoding) {
303  result += "?Q?";
304 
305  char c,hexcode; // implementation of the "Q"-encoding described in RFC 2047
306  for (unsigned int i=start;i<end;i++) {
307  c = encoded8Bit[i];
308  if (c == ' ') // make the result readable with not MIME-capable readers
309  result+='_';
310  else
311  if (((c>='a')&&(c<='z'))|| // paranoid mode, we encode *all* special characters to avoid problems
312  ((c>='A')&&(c<='Z'))|| // with "From" & "To" headers
313  ((c>='0')&&(c<='9')))
314  result+=c;
315  else {
316  result += "="; // "stolen" from KMail ;-)
317  hexcode = ((c & 0xF0) >> 4) + 48;
318  if (hexcode >= 58) hexcode += 7;
319  result += hexcode;
320  hexcode = (c & 0x0F) + 48;
321  if (hexcode >= 58) hexcode += 7;
322  result += hexcode;
323  }
324  }
325  } else {
326  result += "?B?"+KCodecs::base64Encode(encoded8Bit.mid(start,end-start), false);
327  }
328 
329  result +="?=";
330  result += encoded8Bit.right(encoded8Bit.length()-end);
331  }
332  else
333  result = encoded8Bit;
334 
335  return result;
336 }
337 
338 TQCString uniqueString()
339 {
340  static char chars[] = "0123456789abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
341  time_t now;
342  TQCString ret;
343  char p[11];
344  int pos, ran;
345  unsigned int timeval;
346 
347  p[10]='\0';
348  now=time(0);
349  ran=1+(int) (1000.0*rand()/(RAND_MAX+1.0));
350  timeval=(now/ran)+getpid();
351 
352  for(int i=0; i<10; i++){
353  pos=(int) (61.0*rand()/(RAND_MAX+1.0));
354  //kdDebug(5003) << pos << endl;
355  p[i]=chars[pos];
356  }
357  ret.sprintf("%d.%s", timeval, p);
358 
359  return ret;
360 }
361 
362 
363 TQCString multiPartBoundary()
364 {
365  TQCString ret;
366  ret="nextPart"+uniqueString();
367  return ret;
368 }
369 
370 TQCString extractHeader(const TQCString &src, const char *name)
371 {
372  TQCString n=TQCString(name)+":";
373  int pos1=-1, pos2=0, len=src.length()-1;
374  bool folded(false);
375 
376  if (n.lower() == src.left(n.length()).lower()) {
377  pos1 = 0;
378  } else {
379  n.prepend("\n");
380  pos1 = src.find(n.data(),0,false);
381  }
382 
383  if (pos1>-1) { //there is a header with the given name
384  pos1+=n.length(); //skip the name
385  // skip the usual space after the colon
386  if ( src.at( pos1 ) == ' ' )
387  ++pos1;
388  pos2=pos1;
389 
390  if (src[pos2]!='\n') { // check if the header is not empty
391  while(1) {
392  pos2=src.find("\n", pos2+1);
393  if(pos2==-1 || pos2==len || ( src[pos2+1]!=' ' && src[pos2+1]!='\t') ) //break if we reach the end of the string, honor folded lines
394  break;
395  else
396  folded = true;
397  }
398  }
399 
400  if(pos2<0) pos2=len+1; //take the rest of the string
401 
402  if (!folded)
403  return src.mid(pos1, pos2-pos1);
404  else
405  return (src.mid(pos1, pos2-pos1).replace(TQRegExp("\\s*\\n\\s*")," "));
406  }
407  else {
408  return TQCString(0); //header not found
409  }
410 }
411 
412 
413 TQCString CRLFtoLF(const TQCString &s)
414 {
415  TQCString ret=s.copy();
416  ret.replace(TQRegExp("\\r\\n"), "\n");
417  return ret;
418 }
419 
420 
421 TQCString CRLFtoLF(const char *s)
422 {
423  TQCString ret=s;
424  ret.replace(TQRegExp("\\r\\n"), "\n");
425  return ret;
426 }
427 
428 
429 TQCString LFtoCRLF(const TQCString &s)
430 {
431  TQCString ret=s.copy();
432  ret.replace(TQRegExp("\\n"), "\r\n");
433  return ret;
434 }
435 
436 
437 void removeQuots(TQCString &str)
438 {
439  // Removes any quote or backslash caracter
440  str.replace(TQRegExp("[\\\"]"), "");
441 }
442 
443 
444 void removeQuots(TQString &str)
445 {
446  // Removes any quote or backslash caracter
447  str.replace(TQRegExp("[\\\"]"), "");
448 }
449 
450 
451 void addQuotes(TQCString &str, bool forceQuotes)
452 {
453  if ( forceQuotes || TQString(str).contains( TQRegExp( TQString( "\"|\\\\|=|\\]|\\[|:|;|,|\\.|,|@|<|>|\\)|\\(" ) ) ) ) {
454  // Adds a backslash in front of any existing quote or backslash caracter
455  str.replace(TQRegExp("([\\\"])"), "\\\\1");
456  // Adds quote at beginning and end of thestring
457  str.insert(0,'"');
458  str.append("\"");
459  }
460 }
461 
462 int DateFormatter::mDaylight = -1;
464  : mFormat( fType ), mCurrentTime( 0 )
465 {
466 
467 }
468 
469 DateFormatter::~DateFormatter()
470 {/*empty*/}
471 
472 DateFormatter::FormatType
474 {
475  return mFormat;
476 }
477 
478 void
480 {
481  mFormat = t;
482 }
483 
484 TQString
485 DateFormatter::dateString( time_t otime , const TQString& lang ,
486  bool shortFormat, bool includeSecs ) const
487 {
488  switch ( mFormat ) {
489  case Fancy:
490  return fancy( otime );
491  break;
492  case Localized:
493  return localized( otime, shortFormat, includeSecs, lang );
494  break;
495  case CTime:
496  return cTime( otime );
497  break;
498  case Iso:
499  return isoDate( otime );
500  break;
501  case Custom:
502  return custom( otime );
503  break;
504  }
505  return TQString();
506 }
507 
508 TQString
509 DateFormatter::dateString(const TQDateTime& dtime, const TQString& lang,
510  bool shortFormat, bool includeSecs ) const
511 {
512  return DateFormatter::dateString( qdateToTimeT(dtime), lang, shortFormat, includeSecs );
513 }
514 
515 TQCString
516 DateFormatter::rfc2822(time_t otime) const
517 {
518  TQDateTime tmp;
519  TQCString ret;
520 
521  tmp.setTime_t(otime);
522 
523  ret = tmp.toString("ddd, dd MMM yyyy hh:mm:ss ").latin1();
524  ret += zone(otime);
525 
526  return ret;
527 }
528 
529 TQString
530 DateFormatter::custom(time_t t) const
531 {
532  if ( mCustomFormat.isEmpty() )
533  return TQString();
534 
535  int z = mCustomFormat.find("Z");
536  TQDateTime d;
537  TQString ret = mCustomFormat;
538 
539  d.setTime_t(t);
540  if ( z != -1 ) {
541  ret.replace(z,1,zone(t));
542  }
543 
544  ret = d.toString(ret);
545 
546  return ret;
547 }
548 
549 void
550 DateFormatter::setCustomFormat(const TQString& format)
551 {
552  mCustomFormat = format;
553  mFormat = Custom;
554 }
555 
556 TQString
557 DateFormatter::getCustomFormat() const
558 {
559  return mCustomFormat;
560 }
561 
562 
563 TQCString
564 DateFormatter::zone(time_t otime) const
565 {
566  TQCString ret;
567 #if defined(HAVE_TIMEZONE) || defined(HAVE_TM_GMTOFF)
568  struct tm *local = localtime( &otime );
569 #endif
570 
571 #if defined(HAVE_TIMEZONE)
572 
573  //hmm, could make hours & mins static
574  int secs = abs(timezone);
575  int neg = (timezone>0)?1:0;
576  int hours = secs/3600;
577  int mins = (secs - hours*3600)/60;
578 
579  // adjust to daylight
580  if ( local->tm_isdst > 0 ) {
581  mDaylight = 1;
582  if ( neg )
583  --hours;
584  else
585  ++hours;
586  } else
587  mDaylight = 0;
588 
589  ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
590 
591 #elif defined(HAVE_TM_GMTOFF)
592 
593  int secs = abs( local->tm_gmtoff );
594  int neg = (local->tm_gmtoff<0)?1:0; //no, I don't know why it's backwards :o
595  int hours = secs/3600;
596  int mins = (secs - hours*3600)/60;
597 
598  if ( local->tm_isdst > 0 )
599  mDaylight = 1;
600  else
601  mDaylight = 0;
602 
603  ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
604 
605 #else
606 
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;
611  secs = abs(secs);
612  int hours = secs/3600;
613  int mins = (secs - hours*3600)/60;
614  // daylight should be already taken care of here
615  ret.sprintf("%c%.2d%.2d",(neg)?'-':'+', hours, mins);
616 
617 #endif /* HAVE_TIMEZONE */
618 
619  return ret;
620 }
621 
622 time_t
623 DateFormatter::qdateToTimeT(const TQDateTime& dt) const
624 {
625  TQDateTime epoch( TQDate(1970, 1,1), TQTime(00,00,00) );
626  time_t otime;
627  time( &otime );
628 
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 );
632 
633  return drf;
634 }
635 
636 TQString
637 DateFormatter::fancy(time_t otime) const
638 {
639  TDELocale *locale = TDEGlobal::locale();
640 
641  if ( otime <= 0 )
642  return i18n( "unknown" );
643 
644  if ( !mCurrentTime ) {
645  time( &mCurrentTime );
646  mDate.setTime_t( mCurrentTime );
647  }
648 
649  TQDateTime old;
650  old.setTime_t( otime );
651 
652  // not more than an hour in the future
653  if ( mCurrentTime + 60 * 60 >= otime ) {
654  time_t diff = mCurrentTime - otime;
655 
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 ) );
661  }
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) );
668  }
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() ) ).
677 #else
678  arg( locale->weekDayName( old.date().dayOfWeek() ) ).
679 #endif
680  arg( locale->formatTime( old.time(), true) );
681  }
682  }
683 
684  return locale->formatDateTime( old );
685 
686 }
687 
688 TQString
689 DateFormatter::localized(time_t otime, bool shortFormat, bool includeSecs,
690  const TQString& localeLanguage ) const
691 {
692  TQDateTime tmp;
693  TQString ret;
694  TDELocale *locale = TDEGlobal::locale();
695 
696  tmp.setTime_t( otime );
697 
698 
699  if ( !localeLanguage.isEmpty() ) {
700  locale=new TDELocale(localeLanguage);
701  locale->setLanguage(localeLanguage);
702  locale->setCountry(localeLanguage);
703  ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
704  delete locale;
705  } else {
706  ret = locale->formatDateTime( tmp, shortFormat, includeSecs );
707  }
708 
709  return ret;
710 }
711 
712 TQString
713 DateFormatter::cTime(time_t otime) const
714 {
715  return TQString::fromLatin1( ctime( &otime ) ).stripWhiteSpace() ;
716 }
717 
718 TQString
719 DateFormatter::isoDate(time_t otime) const
720 {
721  char cstr[64];
722  strftime( cstr, 63, "%Y-%m-%d %H:%M:%S", localtime(&otime) );
723  return TQString( cstr );
724 }
725 
726 
727 void
729 {
730  mCurrentTime = 0;
731 }
732 
733 TQString
734 DateFormatter::formatDate(DateFormatter::FormatType t, time_t otime,
735  const TQString& data, bool shortFormat, bool includeSecs )
736 {
737  DateFormatter f( t );
738  if ( t == DateFormatter::Custom ) {
739  f.setCustomFormat( data );
740  }
741  return f.dateString( otime, data, shortFormat, includeSecs );
742 }
743 
744 TQString
745 DateFormatter::formatCurrentDate( DateFormatter::FormatType t, const TQString& data,
746  bool shortFormat, bool includeSecs )
747 {
748  DateFormatter f( t );
749  if ( t == DateFormatter::Custom ) {
750  f.setCustomFormat( data );
751  }
752  return f.dateString( time(0), data, shortFormat, includeSecs );
753 }
754 
755 TQCString
757 {
758  DateFormatter f;
759  return f.rfc2822( t );
760 }
761 
762 bool
763 DateFormatter::isDaylight()
764 {
765  if ( mDaylight == -1 ) {
766  time_t ntime = time( 0 );
767  struct tm *local = localtime( &ntime );
768  if ( local->tm_isdst > 0 ) {
769  mDaylight = 1;
770  return true;
771  } else {
772  mDaylight = 0;
773  return false;
774  }
775  } else if ( mDaylight != 0 )
776  return true;
777  else
778  return false;
779 }
780 
781 } // namespace KMime
class abstracting date formatting
Definition: kmime_util.h:194
void setFormat(FormatType t)
sets the currently used format
Definition: kmime_util.cpp:479
void reset()
resets the internal clock
Definition: kmime_util.cpp:728
TQCString rfc2822(time_t otime) const
returns rfc2822 formatted string
Definition: kmime_util.cpp:516
FormatType getFormat() const
returns the currently set format
Definition: kmime_util.cpp:473
TQString custom(time_t t) const
returns date formatted with the earlier given custom format
Definition: kmime_util.cpp:530
TQString dateString(time_t otime, const TQString &lang=TQString(), bool shortFormat=true, bool includeSecs=false) const
returns formatted date string in a currently set format.
Definition: kmime_util.cpp:485
static TQString formatCurrentDate(DateFormatter::FormatType t, const TQString &data=TQString(), bool shortFormat=true, bool includeSecs=false)
convenience function, same as formatDate but returns the current time formatted
Definition: kmime_util.cpp:745
TQCString zone(time_t otime) const
returns a string identifying the timezone (eg.
Definition: kmime_util.cpp:564
DateFormatter(FormatType fType=DateFormatter::Fancy)
constructor
Definition: kmime_util.cpp:463
static TQCString rfc2822FormatDate(time_t time)
convenience function, same as rfc2822
Definition: kmime_util.cpp:756
TQString isoDate(time_t otime) const
returns a string in the "%Y-%m-%d %H:%M:%S" format
Definition: kmime_util.cpp:719
static TQString formatDate(DateFormatter::FormatType t, time_t time, const TQString &data=TQString(), bool shortFormat=true, bool includeSecs=false)
convenience function dateString
Definition: kmime_util.cpp:734
void setCustomFormat(const TQString &format)
makes the class use the custom format for date to string conversions.
Definition: kmime_util.cpp:550
TQString fancy(time_t otime) const
returns fancy formatted date string
Definition: kmime_util.cpp:637
TQString cTime(time_t otime) const
returns string as formatted with ctime function
Definition: kmime_util.cpp:713
TQString localized(time_t otime, bool shortFormat=true, bool includeSecs=false, const TQString &localeLanguage=TQString()) const
returns localized formatted date string
Definition: kmime_util.cpp:689