if (mZoneinfoDir.length() > 1 && mZoneinfoDir.endsWith('/'))
mZoneinfoDir.truncate(mZoneinfoDir.length() - 1); // strip trailing '/'
- // For Unix, read zone.tab.
-
- QString oldZoneinfoDir = mZoneinfoDir;
- QString oldZoneTab = mZoneTab;
-
// Open zone.tab if we already know where it is
QFile f;
- if (!mZoneTab.isEmpty() && !mZoneinfoDir.isEmpty())
- {
- f.setFileName(mZoneTab);
- if (!f.open(QIODevice::ReadOnly)) {
- mZoneTab.clear();
- }
- }
-
- if (mZoneTab.isEmpty() || mZoneinfoDir.isEmpty())
- {
- // Search for zone.tab
- if (!findZoneTab(f))
- return;
- mZoneTab = f.fileName();
-
- if (mZoneinfoDir != oldZoneinfoDir
- || mZoneTab != oldZoneTab)
- {
- // Update config file and notify interested applications
- group.writeEntry(ZONEINFO_DIR, mZoneinfoDir);
- group.writeEntry(ZONE_TAB, mZoneTab);
- group.sync();
- QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
- QDBusConnection::sessionBus().send(message);
- }
- }
+ // Search for zone.tab
+ if (!findZoneTab(f))
+ return;
+ mZoneTab = f.fileName();
// Read zone.tab and create a collection of KTimeZone instances
readZoneTab(f);
mZonetabWatch->addFile(mZoneTab);
connect(mZonetabWatch, SIGNAL(dirty(const QString&)), SLOT(zonetab_Changed(const QString&)));
+ // Respect the config above all
+ if (!mConfigLocalZone.isEmpty()) {
+ // We know the local zone from last time.
+ // Check whether the file still matches it.
+ KTimeZone local = mZones.zone(mConfigLocalZone);
+ if (local.isValid())
+ {
+ mLocalZone = mConfigLocalZone;
+ mLocalZoneDataFile = mZoneinfoDir + "/" + mConfigLocalZone;
+ }
+ }
+
// Find the local system time zone and set up file monitors to detect changes
findLocalZone();
}
-// Check if the local zone has been updated, and if so, write the new
-// zone to the config file and notify interested parties.
+// Check if the local zone has been updated, and if so, notify interested parties.
void KTimeZoned::updateLocalZone()
{
- if (mConfigLocalZone != mLocalZone)
- {
- KConfig config(QLatin1String("ktimezonedrc"));
- KConfigGroup group(&config, "TimeZones");
- mConfigLocalZone = mLocalZone;
- group.writeEntry(LOCAL_ZONE, mConfigLocalZone);
- group.sync();
-
- QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
- QDBusConnection::sessionBus().send(message);
- }
+ qDebug() << "updating timezone" << mLocalZone;
+ KConfig config(QLatin1String("ktimezonedrc"));
+ KConfigGroup group(&config, "TimeZones");
+ mConfigLocalZone = mLocalZone;
+ group.writeEntry(LOCAL_ZONE, mConfigLocalZone);
+ group.sync();
+
+ QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "configChanged");
+ QDBusConnection::sessionBus().send(message);
}
/*
mZoneinfoDir = zoneinfoDir;
f.setFileName(zoneinfoDir + ZONE_TAB_FILE);
if (f.open(QIODevice::ReadOnly))
+ mZoneTab = zoneinfoDir + ZONE_TAB_FILE;
return true;
kDebug(1221) << "Can't open " << f.fileName();
}
mZoneinfoDir = zoneinfoDir;
f.setFileName(zoneinfoDir + ZONE_TAB_FILE);
if (f.open(QIODevice::ReadOnly))
+ mZoneTab = zoneinfoDir + ZONE_TAB_FILE;
return true;
kDebug(1221) << "Can't open " << f.fileName();
}
// Note that only data needed by this module is specified to KSystemTimeZone.
void KTimeZoned::readZoneTab(QFile &f)
{
+ qDebug() << "reading zone.tab";
// Parse the already open real or fake zone.tab.
QRegExp lineSeparator("[ \t]");
if (!mSource)
delete mDirWatch;
mDirWatch = 0;
mLocalZone.clear();
- mLocalIdFile.clear();
- mLocalIdFile2.clear();
mLocalZoneDataFile.clear();
- // SOLUTION 1: DEFINITIVE.
- // First try the simplest solution of checking for well-formed TZ setting.
+ // First try the checking for TZ envinomental variable.
const char *envtz = ::getenv("TZ");
- if (checkTZ(envtz))
- {
- mSavedTZ = envtz;
- if (!mLocalZone.isEmpty()) kDebug(1221)<<"TZ: "<<mLocalZone;
- }
+ checkEnv(envtz);
- if (mLocalZone.isEmpty())
- {
- // SOLUTION 2: DEFINITIVE.
- // BSD & Linux support: local time zone id in /etc/timezone.
- checkTimezone();
- }
- if (mLocalZone.isEmpty() && !mZoneinfoDir.isEmpty())
- {
- // SOLUTION 3: DEFINITIVE.
- // Try to follow any /etc/localtime symlink to a zoneinfo file.
- // SOLUTION 4: DEFINITIVE.
+ if (mLocalZone.isEmpty() && !mZoneinfoDir.isEmpty()) {
// Try to match /etc/localtime against the list of zoneinfo files.
- matchZoneFile(QLatin1String("/etc/localtime"));
- }
- if (mLocalZone.isEmpty())
- {
- // SOLUTION 5: DEFINITIVE.
- // Look for setting in /etc/rc.conf or /etc/rc.local.
- checkRcFile();
- }
- if (mLocalZone.isEmpty())
- {
- // SOLUTION 6: DEFINITIVE.
- // Solaris support using /etc/default/init.
- checkDefaultInit();
+ // Resolve symlink
+ QFileInfo fi(QFile("/etc/localtime"));
+ if (fi.isSymLink()) {
+ checkLocaltime(fi.canonicalFilePath());
+ } else {
+ checkLocaltime(QLatin1String("/etc/localtime"));
+ }
}
- if (mLocalZone.isEmpty())
- {
- // The local time zone is not defined by a file.
- // Watch for creation of /etc/localtime in case it gets created later.
- // TODO: If under BSD it is possible for /etc/timezone to be missing but
- // created later, we should also watch for its creation.
- mLocalIdFile = QLatin1String("/etc/localtime");
+ // Failsafe, fallback to UTC
+ if (mLocalZone.isEmpty()) {
+ mLocalZone = KTimeZone::utc().name();
+ kDebug(1221) << "Failsafe: " << mLocalZone;
}
- // Watch for changes in the file defining the local time zone so as to be
- // notified of any change in it.
+
+ // Watch for changes in the file defining the local time zone
mDirWatch = new KDirWatch(this);
- mDirWatch->addFile(mLocalIdFile);
- if (!mLocalIdFile2.isEmpty())
- mDirWatch->addFile(mLocalIdFile2);
+ mDirWatch->addFile("/etc/localtime");
if (!mLocalZoneDataFile.isEmpty())
mDirWatch->addFile(mLocalZoneDataFile);
+ qDebug() << "watching" << mLocalZoneDataFile;
connect(mDirWatch, SIGNAL(dirty(const QString&)), SLOT(localChanged(const QString&)));
connect(mDirWatch, SIGNAL(deleted(const QString&)), SLOT(localChanged(const QString&)));
connect(mDirWatch, SIGNAL(created(const QString&)), SLOT(localChanged(const QString&)));
+ mDirWatch->startScan();
- if (mLocalZone.isEmpty() && !mZoneinfoDir.isEmpty())
- {
- // SOLUTION 7: HEURISTIC.
- // None of the deterministic stuff above has worked: try a heuristic. We
- // try to find a pair of matching time zone abbreviations...that way, we'll
- // likely return a value in the user's own country.
- tzset();
- QByteArray tzname0(tzname[0]); // store copies, because zone.parse() will change them
- QByteArray tzname1(tzname[1]);
- int bestOffset = INT_MAX;
- KSystemTimeZoneSource::startParseBlock();
- const KTimeZones::ZoneMap zmap = mZones.zones();
- for (KTimeZones::ZoneMap::ConstIterator it = zmap.constBegin(), end = zmap.constEnd(); it != end; ++it)
- {
- KTimeZone zone = it.value();
- int candidateOffset = qAbs(zone.currentOffset(Qt::LocalTime));
- if (candidateOffset < bestOffset
- && zone.parse())
- {
- QList<QByteArray> abbrs = zone.abbreviations();
- if (abbrs.contains(tzname0) && abbrs.contains(tzname1))
- {
- // kDebug(1221) << "local=" << zone.name();
- mLocalZone = zone.name();
- bestOffset = candidateOffset;
- if (!bestOffset)
- break;
- }
- }
- }
- KSystemTimeZoneSource::endParseBlock();
- if (!mLocalZone.isEmpty())
- {
- mLocalMethod = TzName;
- kDebug(1221)<<"tzname: "<<mLocalZone;
- }
- }
- if (mLocalZone.isEmpty())
- {
- // SOLUTION 8: FAILSAFE.
- mLocalZone = KTimeZone::utc().name();
- mLocalMethod = Utc;
- if (!mLocalZone.isEmpty()) kDebug(1221)<<"Failsafe: "<<mLocalZone;
- }
-
- // Finally, if the local zone identity has changed, store
- // the new one in the config file.
+ // Finally, if the local zone identity has changed, let the world know
updateLocalZone();
}
// Called when KDirWatch detects a change in zone.tab
void KTimeZoned::zonetab_Changed(const QString& path)
{
- kDebug(1221) << "zone.tab changed";
- if (path != mZoneTab)
- {
+ qDebug() << "zone.tab changed";
+ if (path != mZoneTab) {
kError(1221) << "Wrong path (" << path << ") for zone.tab";
return;
}
// subsequently becomes the local zone.
QFile f;
f.setFileName(mZoneTab);
- if (!f.open(QIODevice::ReadOnly))
+ if (!f.open(QIODevice::ReadOnly)) {
kError(1221) << "Could not open zone.tab (" << mZoneTab << ") to reread";
- else
+ } else {
readZoneTab(f);
+ }
}
// Called when KDirWatch detects a change
void KTimeZoned::localChanged(const QString& path)
{
- if (path == mLocalZoneDataFile)
- {
- // Only need to update the definition of the local zone,
- // not its identity.
- QDBusMessage message = QDBusMessage::createSignal("/Daemon", "org.kde.KTimeZoned", "zoneDefinitionChanged");
- QList<QVariant> args;
- args += mLocalZone;
- message.setArguments(args);
- QDBusConnection::sessionBus().send(message);
- return;
- }
- QString oldDataFile = mLocalZoneDataFile;
- switch (mLocalMethod)
- {
- case EnvTzLink:
- case EnvTzFile:
- {
- const char *envtz = ::getenv("TZ");
- if (mSavedTZ != envtz)
- {
- // TZ has changed - start from scratch again
- findLocalZone();
- return;
- }
- // The contents of the file pointed to by TZ has changed.
- }
- // Fall through to LocaltimeLink
- case LocaltimeLink:
- case LocaltimeCopy:
- // The fallback methods below also set a watch for /etc/localtime in
- // case it gets created.
- case TzName:
- case Utc:
- matchZoneFile(mLocalIdFile);
- break;
- case Timezone:
- checkTimezone();
- break;
- case RcFile:
- checkRcFile();
- break;
- case DefaultInit:
- checkDefaultInit();
- break;
- default:
- return;
- }
- if (oldDataFile != mLocalZoneDataFile)
- {
- if (!oldDataFile.isEmpty())
- mDirWatch->removeFile(oldDataFile);
- if (!mLocalZoneDataFile.isEmpty())
- mDirWatch->addFile(mLocalZoneDataFile);
- }
- updateLocalZone();
-}
-
-bool KTimeZoned::checkTZ(const char *envZone)
-{
- // SOLUTION 1: DEFINITIVE.
- // First try the simplest solution of checking for well-formed TZ setting.
- if (envZone)
- {
- if (envZone[0] == '\0')
- {
- mLocalMethod = EnvTz;
- mLocalZone = KTimeZone::utc().name();
- mLocalIdFile.clear();
- mLocalZoneDataFile.clear();
- return true;
- }
- if (envZone[0] == ':')
- {
- // TZ specifies a file name, either relative to zoneinfo/ or absolute.
- QString TZfile = QFile::decodeName(envZone + 1);
- if (TZfile.startsWith(mZoneinfoDir))
- {
- // It's an absolute file name in the zoneinfo directory.
- // Convert it to a file name relative to zoneinfo/.
- TZfile = TZfile.mid(mZoneinfoDir.length());
- }
- if (TZfile.startsWith(QLatin1Char('/')))
- {
- // It's an absolute file name.
- QString symlink;
- if (matchZoneFile(TZfile))
- {
- mLocalMethod = static_cast<LocalMethod>(EnvTz | (mLocalMethod & TypeMask));
- return true;
- }
- }
- else if (!TZfile.isEmpty())
- {
- // It's a file name relative to zoneinfo/
- mLocalZone = TZfile;
- if (!mLocalZone.isEmpty())
- {
- mLocalMethod = EnvTz;
- mLocalZoneDataFile = mZoneinfoDir + '/' + TZfile;
- mLocalIdFile.clear();
- return true;
- }
- }
- }
- }
- return false;
-}
-
-bool KTimeZoned::checkTimezone()
-{
- // SOLUTION 2: DEFINITIVE.
- // BSD support.
- QFile f;
- f.setFileName(QLatin1String("/etc/timezone"));
- if (!f.open(QIODevice::ReadOnly))
- return false;
- // Read the first line of the file.
- QTextStream ts(&f);
- ts.setCodec("ISO-8859-1");
- QString zoneName;
- if (!ts.atEnd())
- zoneName = ts.readLine();
- f.close();
- if (zoneName.isEmpty())
- return false;
- if (!setLocalZone(zoneName))
- return false;
- mLocalMethod = Timezone;
- mLocalIdFile = f.fileName();
- kDebug(1221)<<"/etc/timezone: "<<mLocalZone;
- return true;
+ kDebug(1221) << path << "changed";
+ findLocalZone();
}
-bool KTimeZoned::matchZoneFile(const QString &path)
+bool KTimeZoned::checkEnv(const char *envZone)
{
- // SOLUTION 3: DEFINITIVE.
- // Try to follow any symlink to a zoneinfo file.
- // Get the path of the file which the symlink points to.
- QFile f;
- f.setFileName(path);
- QFileInfo fi(f);
- if (fi.isSymLink())
- {
- // The file is a symlink.
- QString zoneInfoFileName = fi.canonicalFilePath();
- QFileInfo fiz(zoneInfoFileName);
- if (fiz.exists() && fiz.isReadable())
- {
- if (zoneInfoFileName.startsWith(mZoneinfoDir))
- {
- // We've got the zoneinfo file path.
- // The time zone name is the part of the path after the zoneinfo directory.
- // Note that some systems (e.g. Gentoo) have zones under zoneinfo which
- // are not in zone.tab, so don't validate against mZones.
- mLocalZone = zoneInfoFileName.mid(mZoneinfoDir.length() + 1);
- // kDebug(1221) << "local=" << mLocalZone;
- }
- else
- {
- // It isn't a zoneinfo file or a copy thereof.
- // Use the absolute path as the time zone name.
- mLocalZone = f.fileName();
- }
- mLocalMethod = LocaltimeLink;
- mLocalIdFile = f.fileName();
- mLocalZoneDataFile = zoneInfoFileName;
- kDebug(1221)<<mLocalIdFile<<": "<<mLocalZone;
- return true;
- }
+ if (!mLocalZone.isEmpty()) {
+ // It has most likely already been set by preferences in the config
+ return true;
}
- else if (f.open(QIODevice::ReadOnly))
- {
- // SOLUTION 4: DEFINITIVE.
- // Try to match the file against the list of zoneinfo files.
-
- // Compute the file's MD5 sum.
- KMD5 context("");
- context.reset();
- context.update(f);
- qlonglong referenceSize = f.size();
- QString referenceMd5Sum = context.hexDigest();
- MD5Map::ConstIterator it5, end5;
- KTimeZone local;
- QString zoneName;
-
- if (!mConfigLocalZone.isEmpty())
- {
- // We know the local zone from last time.
- // Check whether the file still matches it.
- KTimeZone tzone = mZones.zone(mConfigLocalZone);
- if (tzone.isValid())
- {
- local = compareChecksum(tzone, referenceMd5Sum, referenceSize);
- if (local.isValid())
- zoneName = local.name();
+ if (envZone) {
+ if (envZone[0] == ':') {
+ // TZ specified, either relative to zoneinfo/ or absolute.
+ QString tz = QFile::decodeName(envZone + 1);
+ KTimeZone local = mZones.zone(tz);
+ if (!local.isValid()) {
+ return false;
}
- }
-
- if (!local.isValid() && mHaveCountryCodes)
- {
- /* Look for time zones with the user's country code.
- * This has two advantages: 1) it shortens the search;
- * 2) it increases the chance of the correctly titled time zone
- * being found, since multiple time zones can have identical
- * definitions. For example, Europe/Guernsey is identical to
- * Europe/London, but the latter is more likely to be the right
- * zone name for a user with 'gb' country code.
- */
- QString country = KGlobal::locale()->country().toUpper();
- const KTimeZones::ZoneMap zmap = mZones.zones();
- for (KTimeZones::ZoneMap::ConstIterator zit = zmap.constBegin(), zend = zmap.constEnd(); zit != zend; ++zit)
- {
- KTimeZone tzone = zit.value();
- if (tzone.countryCode() == country)
- {
- local = compareChecksum(tzone, referenceMd5Sum, referenceSize);
- if (local.isValid())
- {
- zoneName = local.name();
- break;
- }
- }
+ mLocalZone = tz;
+ if (QFile(tz).exists()) {
+ // Full path.
+ mLocalZoneDataFile = tz;
+ } else {
+ // Relative path.
+ mLocalZoneDataFile = mZoneinfoDir + "/" + tz;
}
}
-
- if (!local.isValid())
- {
- // Look for a checksum match with the cached checksum values
- MD5Map oldChecksums = mMd5Sums; // save a copy of the existing checksums
- for (it5 = mMd5Sums.constBegin(), end5 = mMd5Sums.constEnd(); it5 != end5; ++it5)
- {
- if (it5.value() == referenceMd5Sum)
- {
- // The cached checksum matches. Ensure that the file hasn't changed.
- if (compareChecksum(it5, referenceMd5Sum, referenceSize))
- {
- zoneName = it5.key();
- local = mZones.zone(zoneName);
- if (local.isValid())
- break;
- }
- oldChecksums.clear(); // the cache has been cleared
- break;
- }
- }
-
- if (!local.isValid())
- {
- // The checksum didn't match any in the cache.
- // Continue building missing entries in the cache on the assumption that
- // we haven't previously looked at the zoneinfo file which matches.
- const KTimeZones::ZoneMap zmap = mZones.zones();
- for (KTimeZones::ZoneMap::ConstIterator zit = zmap.constBegin(), zend = zmap.constEnd(); zit != zend; ++zit)
- {
- KTimeZone zone = zit.value();
- zoneName = zone.name();
- if (!mMd5Sums.contains(zoneName))
- {
- QString candidateMd5Sum = calcChecksum(zoneName, referenceSize);
- if (candidateMd5Sum == referenceMd5Sum)
- {
- // kDebug(1221) << "local=" << zone.name();
- local = zone;
- break;
- }
- }
- }
- }
-
- if (!local.isValid())
- {
- // Didn't find the file, so presumably a previously cached checksum must
- // have changed. Delete all the old checksums.
- MD5Map::ConstIterator mit;
- MD5Map::ConstIterator mend = oldChecksums.constEnd();
- for (mit = oldChecksums.constBegin(); mit != mend; ++mit)
- mMd5Sums.remove(mit.key());
-
- // And recalculate the old checksums
- for (mit = oldChecksums.constBegin(); mit != mend; ++mit)
- {
- zoneName = mit.key();
- QString candidateMd5Sum = calcChecksum(zoneName, referenceSize);
- if (candidateMd5Sum == referenceMd5Sum)
- {
- // kDebug(1221) << "local=" << zoneName;
- local = mZones.zone(zoneName);
- break;
- }
- }
- }
- }
- bool success = false;
- if (local.isValid())
- {
- // The file matches a zoneinfo file
- mLocalZone = zoneName;
- mLocalZoneDataFile = mZoneinfoDir + '/' + zoneName;
- success = true;
- }
- else
- {
- // The file doesn't match a zoneinfo file. If it's a TZfile, use it directly.
- // Read the file type identifier.
- char buff[4];
- f.reset();
- QDataStream str(&f);
- if (str.readRawData(buff, 4) == 4
- && buff[0] == 'T' && buff[1] == 'Z' && buff[2] == 'i' && buff[3] == 'f')
- {
- // Use its absolute path as the zone name.
- mLocalZone = f.fileName();
- mLocalZoneDataFile.clear();
- success = true;
- }
- }
- f.close();
- if (success)
- {
- mLocalMethod = LocaltimeCopy;
- mLocalIdFile = f.fileName();
- kDebug(1221)<<mLocalIdFile<<": "<<mLocalZone;
- return true;
- }
}
return false;
}
-bool KTimeZoned::checkRcFile()
+bool KTimeZoned::checkLocaltime(const QString &path)
{
- // SOLUTION 5: DEFINITIVE.
- // Look for setting in /etc/rc.conf or /etc/rc.local,
- // with priority to /etc/rc.local.
- if (findKey(QLatin1String("/etc/rc.local"), "TIMEZONE"))
- {
- mLocalIdFile2.clear();
- kDebug(1221)<<"/etc/rc.local: "<<mLocalZone;
- }
- else
- {
- if (!findKey(QLatin1String("/etc/rc.conf"), "TIMEZONE"))
- return false;
- mLocalIdFile2 = mLocalIdFile;
- mLocalIdFile = QLatin1String("/etc/rc.local");
- kDebug(1221)<<"/etc/rc.conf: "<<mLocalZone;
+ if (!mLocalZone.isEmpty()) {
+ // It has most likely already been set by preferences in the config
+ return true;
}
- mLocalMethod = RcFile;
- return true;
-}
-bool KTimeZoned::checkDefaultInit()
-{
- // SOLUTION 6: DEFINITIVE.
- // Solaris support using /etc/default/init.
- if (!findKey(QLatin1String("/etc/default/init"), "TZ"))
+ if (mZoneinfoDir.isEmpty() && !path.indexOf(mZoneinfoDir)) {
+ qDebug() << "relative path passed to checkLocaltime()";
return false;
- mLocalMethod = DefaultInit;
- kDebug(1221)<<"/etc/default/init: "<<mLocalZone;
- return true;
-}
-
-bool KTimeZoned::findKey(const QString &path, const QString &key)
-{
- QFile f;
- f.setFileName(path);
- if (!f.open(QIODevice::ReadOnly))
- return false;
- QString line;
- QString zoneName;
- QRegExp keyexp('^' + key + "\\s*=\\s*");
- QTextStream ts(&f);
- ts.setCodec("ISO-8859-1");
- while (!ts.atEnd())
- {
- line = ts.readLine();
- if (keyexp.indexIn(line) == 0)
- {
- zoneName = line.mid(keyexp.matchedLength());
- break;
- }
}
- f.close();
- if (zoneName.isEmpty())
- return false;
- if (!setLocalZone(zoneName))
- return false;
- kDebug(1221) << "Key:" << key << "->" << zoneName;
- mLocalIdFile = f.fileName();
- return true;
-}
-// Check whether the zone name is valid, either as a zone in zone.tab or
-// as another file in the zoneinfo directory.
-// If valid, set the local zone information.
-bool KTimeZoned::setLocalZone(const QString &zoneName)
-{
- KTimeZone local = mZones.zone(zoneName);
- if (!local.isValid())
- {
- // It isn't a recognised zone in zone.tab.
- // Note that some systems (e.g. Gentoo) have zones under zoneinfo which
- // are not in zone.tab, so check if it points to another zone file.
- if (mZoneinfoDir.isEmpty())
- return false;
- QString path = mZoneinfoDir + '/' + zoneName;
- QFile qf;
- qf.setFileName(path);
- QFileInfo fi(qf);
- if (fi.isSymLink())
- fi.setFile(fi.canonicalFilePath());
- if (!fi.exists() || !fi.isReadable())
- return false;
- }
- mLocalZone = zoneName;
- mLocalZoneDataFile = mZoneinfoDir.isEmpty() ? QString() : mZoneinfoDir + '/' + zoneName;
- return true;
-}
+ // The path could be full path, remove zoneinfo directory reference
+ QString rel = path.mid(mZoneinfoDir.length() + 1);
-// Check whether the checksum for a time zone matches a given saved checksum.
-KTimeZone KTimeZoned::compareChecksum(const KTimeZone &zone, const QString &referenceMd5Sum, qlonglong size)
-{
- MD5Map::ConstIterator it5 = mMd5Sums.constFind(zone.name());
- if (it5 == mMd5Sums.constEnd())
- {
- // No checksum has been computed yet for this zone file.
- // Compute it now.
- QString candidateMd5Sum = calcChecksum(zone.name(), size);
- if (candidateMd5Sum == referenceMd5Sum)
- {
- // kDebug(1221) << "local=" << zone.name();
- return zone;
- }
- return KTimeZone();
- }
- if (it5.value() == referenceMd5Sum)
- {
- // The cached checksum matches. Ensure that the file hasn't changed.
- if (compareChecksum(it5, referenceMd5Sum, size))
- return mZones.zone(it5.key());
+ KTimeZone local = mZones.zone(rel);
+ if (!local.isValid()) {
+ return false;
}
- return KTimeZone();
-}
-
-// Check whether a checksum matches a given saved checksum.
-// Returns false if the file no longer matches and cache was cleared.
-bool KTimeZoned::compareChecksum(MD5Map::ConstIterator it5, const QString &referenceMd5Sum, qlonglong size)
-{
- // The cached checksum matches. Ensure that the file hasn't changed.
- QString zoneName = it5.key();
- QString candidateMd5Sum = calcChecksum(zoneName, size);
- if (candidateMd5Sum.isNull())
- mMd5Sums.remove(zoneName); // no match - wrong file size
- else if (candidateMd5Sum == referenceMd5Sum)
- return true;
- // File(s) have changed, so clear the cache
- mMd5Sums.clear();
- mMd5Sums[zoneName] = candidateMd5Sum; // reinsert the newly calculated checksum
- return false;
-}
-
-// Calculate the MD5 checksum for the given zone file, provided that its size matches.
-// The calculated checksum is cached.
-QString KTimeZoned::calcChecksum(const QString &zoneName, qlonglong size)
-{
- QString path = mZoneinfoDir + '/' + zoneName;
- QFileInfo fi(path);
- if (static_cast<qlonglong>(fi.size()) == size)
- {
- // Only do the heavy lifting for file sizes which match.
- QFile f;
- f.setFileName(path);
- if (f.open(QIODevice::ReadOnly))
- {
- KMD5 context("");
- context.reset();
- context.update(f);
- QString candidateMd5Sum = context.hexDigest();
- f.close();
- mMd5Sums[zoneName] = candidateMd5Sum; // cache the new checksum
- return candidateMd5Sum;
- }
- }
- return QString();
+ mLocalZone = rel;
+ mLocalZoneDataFile = path;
+ kDebug(1221) << mLocalZone;
+ return true;
}