• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

ktimezones.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (c) 2005 S.R.Haque <srhaque@iee.org>.
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <config.h>
00021 
00022 #include <ktimezones.h>
00023 #include <kdebug.h>
00024 #include <kmdcodec.h>
00025 #include <kprocess.h>
00026 #include <kstringhandler.h>
00027 #include <ktempfile.h>
00028 
00029 #include <qdatetime.h>
00030 #include <qfile.h>
00031 #include <qregexp.h>
00032 #include <qstringlist.h>
00033 #include <qtextstream.h>
00034 
00035 #include <cerrno>
00036 #include <climits>
00037 #include <cstdlib>
00038 #include <cstring>
00039 #include <ctime>
00040 
00041 #define UTC_ZONE "UTC"
00042 
00051 class AbbreviationsMatch :
00052     public KTimezoneDetails
00053 {
00054 public:
00055     AbbreviationsMatch(const QString &stdZone, const QString &dstZone = "")
00056     {
00057         m_stdZone = stdZone;
00058         m_dstZone = dstZone;
00059     }
00060 
00061     void parseStarted()
00062     {
00063         m_foundStd = false;
00064         m_foundDst = m_dstZone.isEmpty();
00065     }
00066 
00067     bool test()
00068     {
00069         return (m_foundStd && m_foundDst);
00070     }
00071 
00072 private:
00073     bool m_foundStd;
00074     bool m_foundDst;
00075     QString m_stdZone;
00076     QString m_dstZone;
00077 
00078     virtual void gotAbbreviation(int /*index*/, const QString &value)
00079     {
00080         if (m_stdZone == value)
00081         {
00082             m_foundStd = true;
00083         }
00084         if (m_dstZone == value)
00085         {
00086             m_foundDst = true;
00087         }
00088     }
00089 };
00090 
00094 class DummySource :
00095     public KTimezoneSource
00096 {
00097 public:
00098     DummySource() :
00099         KTimezoneSource("")
00100     {
00101     }
00102 
00103     virtual bool parse(const QString &/*zone*/, KTimezoneDetails &/*dataReceiver*/) const
00104     {
00105         return true;
00106     }
00107 };
00108 
00112 class OffsetFind :
00113     public KTimezoneDetails
00114 {
00115 public:
00116     OffsetFind(unsigned dateTime)
00117     {
00118         m_dateTime = dateTime;
00119     }
00120 
00121     void parseStarted()
00122     {
00123         m_transitionTimeIndex = 0;
00124         m_localTimeIndex = -1;
00125         m_abbrIndex = -1;
00126         m_offset = 0;
00127         m_isDst = false;
00128         m_abbr = UTC_ZONE;
00129     }
00130 
00131     int offset()
00132     {
00133         return m_offset;
00134     }
00135 
00136     bool isDst()
00137     {
00138         return m_isDst;
00139     }
00140 
00141     QString abbreviation()
00142     {
00143         return m_abbr;
00144     }
00145 
00146 private:
00147     unsigned m_dateTime;
00148     int m_transitionTimeIndex;
00149     int m_localTimeIndex;
00150     int m_abbrIndex;
00151     int m_offset;
00152     bool m_isDst;
00153     QString m_abbr;
00154 
00155     virtual void gotTransitionTime(int index, unsigned transitionTime)
00156     {
00157         if (transitionTime <= m_dateTime)
00158         {
00159             // Remember the index of the transition time that relates to dateTime.
00160             m_transitionTimeIndex = index;
00161         }
00162     }
00163 
00164     virtual void gotLocalTimeIndex(int index, unsigned localTimeIndex)
00165     {
00166         if (index == m_transitionTimeIndex)
00167         {
00168             // Remember the index of the local time that relates to dateTime.
00169             m_localTimeIndex = localTimeIndex;
00170         }
00171     }
00172 
00173     virtual void gotLocalTime(int index, int gmtOff, bool isDst, unsigned abbrInd)
00174     {
00175         if (index == m_localTimeIndex)
00176         {
00177             // Remember the results that relate to gmtOffset.
00178             m_offset = gmtOff;
00179             m_isDst = isDst;
00180             m_abbrIndex = abbrInd;
00181         }
00182     }
00183 
00184     virtual void gotAbbreviation(int index, const QString &value)
00185     {
00186         if (index == m_abbrIndex)
00187         {
00188             m_abbr = value;
00189         }
00190     }
00191 };
00192 
00193 const float KTimezone::UNKNOWN = 1000.0;
00194 
00195 bool KTimezone::isValidLatitude(float latitude)
00196 {
00197     return (latitude >= -90.0) && (latitude <= 90.0);
00198 }
00199 
00200 bool KTimezone::isValidLongitude(float longitude)
00201 {
00202     return (longitude >= -180.0) && (longitude <= 180.0);
00203 }
00204 
00205 KTimezone::KTimezone(
00206     KSharedPtr<KTimezoneSource> db, const QString& name,
00207     const QString &countryCode, float latitude, float longitude,
00208     const QString &comment) :
00209     m_db(db),
00210     m_name(name),
00211     m_countryCode(countryCode),
00212     m_latitude(latitude),
00213     m_longitude(longitude),
00214     m_comment(comment),
00215     d(0)
00216 {
00217     // Detect duff values.
00218     if (m_latitude * m_latitude > 90 * 90)
00219         m_latitude = UNKNOWN;
00220     if (m_longitude * m_longitude > 180 * 180)
00221         m_longitude = UNKNOWN;
00222 }
00223 
00224 KTimezone::~KTimezone()
00225 {
00226     // FIXME when needed:
00227     // delete d;
00228 }
00229 
00230 QString KTimezone::comment() const
00231 {
00232     return m_comment;
00233 }
00234 
00235 QDateTime KTimezone::convert(const KTimezone *newZone, const QDateTime &dateTime) const
00236 {
00237     char *originalZone = ::getenv("TZ");
00238 
00239     // Convert the given localtime to UTC.
00240     ::setenv("TZ", m_name.utf8(), 1);
00241     tzset();
00242     unsigned utc = dateTime.toTime_t();
00243 
00244     // Set the timezone and convert UTC to localtime.
00245     ::setenv("TZ", newZone->name().utf8(), 1);
00246     tzset();
00247     QDateTime remoteTime;
00248     remoteTime.setTime_t(utc, Qt::LocalTime);
00249 
00250     // Now restore things
00251     if (!originalZone)
00252     {
00253         ::unsetenv("TZ");
00254     }
00255     else
00256     {
00257         ::setenv("TZ", originalZone, 1);
00258     }
00259     tzset();
00260     return remoteTime;
00261 }
00262 
00263 QString KTimezone::countryCode() const
00264 {
00265     return m_countryCode;
00266 }
00267 
00268 float KTimezone::latitude() const
00269 {
00270     return m_latitude;
00271 }
00272 
00273 float KTimezone::longitude() const
00274 {
00275     return m_longitude;
00276 }
00277 
00278 QString KTimezone::name() const
00279 {
00280     return m_name;
00281 }
00282 
00283 int KTimezone::offset(Qt::TimeSpec basisSpec) const
00284 {
00285     char *originalZone = ::getenv("TZ");
00286 
00287     // Get the time in the current timezone.
00288     QDateTime basisTime = QDateTime::currentDateTime(basisSpec);
00289 
00290     // Set the timezone and find out what time it is there compared to the basis.
00291     ::setenv("TZ", m_name.utf8(), 1);
00292     tzset();
00293     QDateTime remoteTime = QDateTime::currentDateTime(Qt::LocalTime);
00294     int offset = remoteTime.secsTo(basisTime);
00295 
00296     // Now restore things
00297     if (!originalZone)
00298     {
00299         ::unsetenv("TZ");
00300     }
00301     else
00302     {
00303         ::setenv("TZ", originalZone, 1);
00304     }
00305     tzset();
00306     return offset;
00307 }
00308 
00309 int KTimezone::offset(const QDateTime &dateTime) const
00310 {
00311     OffsetFind finder(dateTime.toTime_t());
00312     int result = 0;
00313     if (parse(finder))
00314     {
00315         result = finder.offset();
00316     }
00317     return result;
00318 }
00319 
00320 bool KTimezone::parse(KTimezoneDetails &dataReceiver) const
00321 {
00322     dataReceiver.parseStarted();
00323     bool result = m_db->parse(m_name, dataReceiver);
00324     dataReceiver.parseEnded();
00325     return result;
00326 }
00327 
00328 KTimezones::KTimezones() :
00329     m_zoneinfoDir(),
00330     m_zones(0),
00331     d(0)
00332 {
00333     // Create the database (and resolve m_zoneinfoDir!).
00334     allZones();
00335     m_UTC = new KTimezone(new DummySource(), UTC_ZONE);
00336     add(m_UTC);
00337 }
00338 
00339 KTimezones::~KTimezones()
00340 {
00341     // FIXME when needed:
00342     // delete d;
00343 
00344     // Autodelete behavior.
00345     if (m_zones)
00346     {
00347         for (ZoneMap::ConstIterator it = m_zones->begin(); it != m_zones->end(); ++it)
00348         {
00349             delete it.data();
00350         }
00351     }
00352     delete m_zones;
00353 }
00354 
00355 void KTimezones::add(KTimezone *zone)
00356 {
00357     m_zones->insert(zone->name(), zone);
00358 }
00359 
00360 const KTimezones::ZoneMap KTimezones::allZones()
00361 {
00362     // Have we already done all the hard work? If not, create the cache.
00363     if (m_zones)
00364         return *m_zones;
00365     m_zones = new ZoneMap();
00366 
00367     // Go read the database.
00368     //
00369     // On Windows, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
00370     // is the place to look. The TZI binary value is the TIME_ZONE_INFORMATION structure.
00371     //
00372     // For Unix its all easy except knowing where to look. Try the LSB location first.
00373     QFile f;
00374     m_zoneinfoDir = "/usr/share/zoneinfo";
00375     f.setName(m_zoneinfoDir + "/zone.tab");
00376     if (!f.open(IO_ReadOnly))
00377     {
00378         kdDebug() << "Can't open " << f.name() << endl;
00379         m_zoneinfoDir = "/usr/lib/zoneinfo";
00380         f.setName(m_zoneinfoDir + "/zone.tab");
00381         if (!f.open(IO_ReadOnly))
00382         {
00383             kdDebug() << "Can't open " << f.name() << endl;
00384             m_zoneinfoDir = ::getenv("TZDIR");
00385             f.setName(m_zoneinfoDir + "/zone.tab");
00386             if (m_zoneinfoDir.isEmpty() || !f.open(IO_ReadOnly))
00387             {
00388                 kdDebug() << "Can't open " << f.name() << endl;
00389 
00390                 // Solaris support. Synthesise something that looks like a zone.tab.
00391                 //
00392                 // /bin/grep -h ^Zone /usr/share/lib/zoneinfo/src/* | /bin/awk '{print "??\t+9999+99999\t" $2}'
00393                 //
00394                 // where the country code is set to "??" and the lattitude/longitude
00395                 // values are dummies.
00396                 m_zoneinfoDir = "/usr/share/lib/zoneinfo";
00397                 KTempFile temp;
00398                 KShellProcess reader;
00399                 reader << "/bin/grep" << "-h" << "^Zone" << m_zoneinfoDir << "/src/*" << temp.name() << "|" <<
00400                     "/bin/awk" << "'{print \"??\\t+9999+99999\\t\" $2}'";
00401                 // Note the use of blocking here...it is a trivial amount of data!
00402                 temp.close();
00403                 reader.start(KProcess::Block);
00404                 f.setName(temp.name());
00405                 if (!temp.status() || !f.open(IO_ReadOnly))
00406                 {
00407                     kdDebug() << "Can't open " << f.name() << endl;
00408                     return *m_zones;
00409                 }
00410             }
00411         }
00412     }
00413 
00414     // Parse the zone.tab.
00415     QTextStream str(&f);
00416     QRegExp lineSeparator("[ \t]");
00417     QRegExp ordinateSeparator("[+-]");
00418     KSharedPtr<KTimezoneSource> db(new KTimezoneSource(m_zoneinfoDir));
00419     while (!str.atEnd())
00420     {
00421         QString line = str.readLine();
00422         if (line.isEmpty() || '#' == line[0])
00423             continue;
00424         QStringList tokens = KStringHandler::perlSplit(lineSeparator, line, 4);
00425         if (tokens.count() < 3)
00426         {
00427             kdError() << "invalid record: " << line << endl;
00428             continue;
00429         }
00430 
00431         // Got three tokens. Now check for two ordinates plus first one is "".
00432         QStringList ordinates = KStringHandler::perlSplit(ordinateSeparator, tokens[1], 2);
00433         if (ordinates.count() < 2)
00434         {
00435             kdError() << "invalid coordinates: " << tokens[1] << endl;
00436             continue;
00437         }
00438 
00439         float latitude = convertCoordinate(ordinates[1]);
00440         float longitude = convertCoordinate(ordinates[2]);
00441 
00442         // Add entry to list.
00443         if (tokens[0] == "??")
00444             tokens[0] = "";
00445         KTimezone *timezone = new KTimezone(db, tokens[2], tokens[0], latitude, longitude, tokens[3]);
00446         add(timezone);
00447     }
00448     f.close();
00449     return *m_zones;
00450 }
00451 
00455 float KTimezones::convertCoordinate(const QString &coordinate)
00456 {
00457     int value = coordinate.toInt();
00458     int degrees = 0;
00459     int minutes = 0;
00460     int seconds = 0;
00461 
00462     if (coordinate.length() > 11)
00463     {
00464         degrees = value / 10000;
00465         value -= degrees * 10000;
00466         minutes = value / 100;
00467         value -= minutes * 100;
00468         seconds = value;
00469     }
00470     else
00471     {
00472         degrees = value / 100;
00473         value -= degrees * 100;
00474         minutes = value;
00475     }
00476     value = degrees * 3600 + minutes * 60 + seconds;
00477     return value / 3600.0;
00478 }
00479 
00480 const KTimezone *KTimezones::local()
00481 {
00482     const KTimezone *local = 0;
00483 
00484     // First try the simplest solution of checking for well-formed TZ setting.
00485     char *envZone = ::getenv("TZ");
00486     if (envZone)
00487     {
00488         if (envZone[0] == '\0')
00489         {
00490             return m_UTC;
00491         }
00492         else
00493         if (envZone[0] == ':')
00494         {
00495             envZone++;
00496         }
00497         local = zone(envZone);
00498     }
00499     if (local)
00500         return local;
00501 
00502     // Try to match /etc/localtime against the list of zoneinfo files.
00503     QFile f;
00504     f.setName("/etc/localtime");
00505     if (f.open(IO_ReadOnly))
00506     {
00507         // Compute the MD5 sum of /etc/localtime.
00508         KMD5 context("");
00509         context.reset();
00510         context.update(f);
00511         QIODevice::Offset referenceSize = f.size();
00512         QString referenceMd5Sum = context.hexDigest();
00513         f.close();
00514         if (!m_zoneinfoDir.isEmpty())
00515         {
00516             // Compare it with each zoneinfo file.
00517             for (ZoneMap::Iterator it = m_zones->begin(); it != m_zones->end(); ++it)
00518             {
00519                 KTimezone *zone = it.data();
00520                 f.setName(m_zoneinfoDir + '/' + zone->name());
00521                 if (f.open(IO_ReadOnly))
00522                 {
00523                     QIODevice::Offset candidateSize = f.size();
00524                     QString candidateMd5Sum;
00525                     if (candidateSize == referenceSize)
00526                     {
00527                         // Only do the heavy lifting for file sizes which match.
00528                         context.reset();
00529                         context.update(f);
00530                         candidateMd5Sum = context.hexDigest();
00531                     }
00532                     f.close();
00533                     if (candidateMd5Sum == referenceMd5Sum)
00534                     {
00535                         // kdError() << "local=" << zone->name() << endl;
00536                         local = zone;
00537                         break;
00538                     }
00539                 }
00540             }
00541         }
00542     }
00543     if (local)
00544         return local;
00545 
00546     // BSD support.
00547     QString fileZone;
00548     f.setName("/etc/timezone");
00549     if (!f.open(IO_ReadOnly))
00550     {
00551         kdDebug() << "Can't open " << f.name() << endl;
00552 
00553         // Solaris support using /etc/default/init.
00554         f.setName("/etc/default/init");
00555         if (!f.open(IO_ReadOnly))
00556         {
00557             kdDebug() << "Can't open " << f.name() << endl;
00558         }
00559         else
00560         {
00561             QTextStream ts(&f);
00562             ts.setEncoding(QTextStream::Latin1);
00563 
00564             // Read the last line starting "TZ=".
00565             while (!ts.atEnd())
00566             {
00567                 fileZone = ts.readLine();
00568                 if (fileZone.startsWith("TZ="))
00569                 {
00570                     fileZone = fileZone.mid(3);
00571 
00572                     // kdError() << "local=" << fileZone << endl;
00573                     local = zone(fileZone);
00574                 }
00575             }
00576             f.close();
00577         }
00578     }
00579     else
00580     {
00581         QTextStream ts(&f);
00582         ts.setEncoding(QTextStream::Latin1);
00583 
00584         // Read the first line.
00585         if (!ts.atEnd())
00586         {
00587             fileZone = ts.readLine();
00588 
00589             // kdError() << "local=" << fileZone << endl;
00590             local = zone(fileZone);
00591         }
00592         f.close();
00593     }
00594     if (local)
00595         return local;
00596 
00597     // None of the deterministic stuff above has worked: try a heuristic. We
00598     // try to find a pair of matching timezone abbreviations...that way, we'll
00599     // likely return a value in the user's own country.
00600     if (!m_zoneinfoDir.isEmpty())
00601     {
00602         tzset();
00603         AbbreviationsMatch matcher(tzname[0], tzname[1]);
00604         int bestOffset = INT_MAX;
00605         for (ZoneMap::Iterator it = m_zones->begin(); it != m_zones->end(); ++it)
00606         {
00607             KTimezone *zone = it.data();
00608             int candidateOffset = QABS(zone->offset(Qt::LocalTime));
00609             if (zone->parse(matcher) && matcher.test() && (candidateOffset < bestOffset))
00610             {
00611                 // kdError() << "local=" << zone->name() << endl;
00612                 bestOffset = candidateOffset;
00613                 local = zone;
00614             }
00615         }
00616     }
00617     if (local)
00618         return local;
00619     return m_UTC;
00620 }
00621 
00622 const KTimezone *KTimezones::zone(const QString &name)
00623 {
00624     if (name.isEmpty())
00625         return m_UTC;
00626     ZoneMap::ConstIterator it = m_zones->find(name);
00627     if (it != m_zones->end())
00628         return it.data();
00629 
00630     // Error.
00631     return 0;
00632 }
00633 
00634 KTimezoneDetails::KTimezoneDetails()
00635 {
00636 }
00637 
00638 KTimezoneDetails::~KTimezoneDetails()
00639 {
00640 }
00641 
00642 void KTimezoneDetails::gotAbbreviation(int /*index*/, const QString &)
00643 {}
00644 
00645 void KTimezoneDetails::gotHeader(
00646         unsigned, unsigned, unsigned,
00647         unsigned, unsigned, unsigned)
00648 {}
00649 
00650 void KTimezoneDetails::gotLeapAdjustment(int /*index*/, unsigned, unsigned)
00651 {}
00652 
00653 void KTimezoneDetails::gotLocalTime(int /*index*/, int, bool, unsigned)
00654 {}
00655 
00656 void KTimezoneDetails::gotLocalTimeIndex(int /*index*/, unsigned)
00657 {}
00658 
00659 void KTimezoneDetails::gotIsStandard(int /*index*/, bool)
00660 {}
00661 
00662 void KTimezoneDetails::gotTransitionTime(int /*index*/, unsigned)
00663 {}
00664 
00665 void KTimezoneDetails::gotIsUTC(int /*index*/, bool)
00666 {}
00667 
00668 void KTimezoneDetails::parseEnded()
00669 {}
00670 
00671 void KTimezoneDetails::parseStarted()
00672 {}
00673 
00674 KTimezoneSource::KTimezoneSource(const QString &db) :
00675     m_db(db)
00676 {
00677 }
00678 
00679 KTimezoneSource::~KTimezoneSource()
00680 {
00681 }
00682 
00683 QString KTimezoneSource::db()
00684 {
00685     return m_db;
00686 }
00687 
00688 bool KTimezoneSource::parse(const QString &zone, KTimezoneDetails &dataReceiver) const
00689 {
00690     QFile f(m_db + '/' + zone);
00691     if (!f.open(IO_ReadOnly))
00692     {
00693         kdError() << "Cannot open " << f.name() << endl;
00694         return false;
00695     }
00696 
00697     // Structures that represent the zoneinfo file.
00698     Q_UINT8 T, z, i_, f_;
00699     struct
00700     {
00701         Q_UINT32 ttisgmtcnt;
00702         Q_UINT32 ttisstdcnt;
00703         Q_UINT32 leapcnt;
00704         Q_UINT32 timecnt;
00705         Q_UINT32 typecnt;
00706         Q_UINT32 charcnt;
00707     } tzh;
00708     Q_UINT32 transitionTime;
00709     Q_UINT8 localTimeIndex;
00710     struct
00711     {
00712         Q_INT32 gmtoff;
00713         Q_INT8 isdst;
00714         Q_UINT8 abbrind;
00715     } tt;
00716     Q_UINT32 leapTime;
00717     Q_UINT32 leapSeconds;
00718     Q_UINT8 isStandard;
00719     Q_UINT8 isUTC;
00720 
00721     QDataStream str(&f);
00722     str >> T >> z >> i_ >> f_;
00723     // kdError() << "signature: " << QChar(T) << QChar(z) << QChar(i_) << QChar(f_) << endl;
00724     unsigned i;
00725     for (i = 0; i < 4; i++)
00726         str >> tzh.ttisgmtcnt;
00727     str >> tzh.ttisgmtcnt >> tzh.ttisstdcnt >> tzh.leapcnt >> tzh.timecnt >> tzh.typecnt >> tzh.charcnt;
00728     // kdError() << "header: " << tzh.ttisgmtcnt << ", " << tzh.ttisstdcnt << ", " << tzh.leapcnt << ", " <<
00729     //    tzh.timecnt << ", " << tzh.typecnt << ", " << tzh.charcnt << endl;
00730     dataReceiver.gotHeader(tzh.ttisgmtcnt, tzh.ttisstdcnt, tzh.leapcnt, tzh.timecnt, tzh.typecnt, tzh.charcnt);
00731     for (i = 0; i < tzh.timecnt; i++)
00732     {
00733         str >> transitionTime;
00734         dataReceiver.gotTransitionTime(i, transitionTime);
00735     }
00736     for (i = 0; i < tzh.timecnt; i++)
00737     {
00738         // NB: these appear to be 1-based, not zero-based!
00739         str >> localTimeIndex;
00740         dataReceiver.gotLocalTimeIndex(i, localTimeIndex);
00741     }
00742     for (i = 0; i < tzh.typecnt; i++)
00743     {
00744         str >> tt.gmtoff >> tt.isdst >> tt.abbrind;
00745         // kdError() << "local type: " << tt.gmtoff << ", " << tt.isdst << ", " << tt.abbrind << endl;
00746         dataReceiver.gotLocalTime(i, tt.gmtoff, (tt.isdst != 0), tt.abbrind);
00747     }
00748 
00749     // Make sure we don't run foul of maliciously coded timezone abbreviations.
00750     if (tzh.charcnt > 64)
00751     {
00752         kdError() << "excessive length for timezone abbreviations: " << tzh.charcnt << endl;
00753         return false;
00754     }
00755     QByteArray array(tzh.charcnt);
00756     str.readRawBytes(array.data(), array.size());
00757     char *abbrs = array.data();
00758     if (abbrs[tzh.charcnt - 1] != 0)
00759     {
00760         // These abbrevations are corrupt!
00761         kdError() << "timezone abbreviations not terminated: " << abbrs[tzh.charcnt - 1] << endl;
00762         return false;
00763     }
00764     char *abbr = abbrs;
00765     while (abbr < abbrs + tzh.charcnt)
00766     {
00767         // kdError() << "abbr: " << abbr << endl;
00768         dataReceiver.gotAbbreviation((abbr - abbrs), abbr);
00769         abbr += strlen(abbr) + 1;
00770     }
00771     for (i = 0; i < tzh.leapcnt; i++)
00772     {
00773         str >> leapTime >> leapSeconds;
00774         // kdError() << "leap entry: " << leapTime << ", " << leapSeconds << endl;
00775         dataReceiver.gotLeapAdjustment(i, leapTime, leapSeconds);
00776     }
00777     for (i = 0; i < tzh.ttisstdcnt; i++)
00778     {
00779         str >> isStandard;
00780         // kdError() << "standard: " << isStandard << endl;
00781         dataReceiver.gotIsStandard(i, (isStandard != 0));
00782     }
00783     for (i = 0; i < tzh.ttisgmtcnt; i++)
00784     {
00785         str >> isUTC;
00786         // kdError() << "UTC: " << isUTC << endl;
00787         dataReceiver.gotIsUTC(i, (isUTC != 0));
00788     }
00789     return true;
00790 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal