Skip to content

Commit

Permalink
Merge branch 'zero' into 'master'
Browse files Browse the repository at this point in the history
[mkcal] Ensure that start date time is valid for VEVENTS. Fixes TJC#215299

See merge request mer-core/mkcal!40
  • Loading branch information
chriadam committed Jun 10, 2020
2 parents c2944bb + 2605747 commit 0ad6b25
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 21 deletions.
11 changes: 9 additions & 2 deletions src/sqliteformat.cpp
Expand Up @@ -1142,7 +1142,9 @@ static KDateTime getDateTime(SqliteStorage *storage, sqlite3_stmt *stmt, int ind
if (timezone.isEmpty()) {
// consider empty timezone as clock time
date = sqlite3_column_int64(stmt, index + 1);
dateTime = storage->fromOriginTime(date);
if (date || sqlite3_column_int64(stmt, index)) {
dateTime = storage->fromOriginTime(date);
}
dateTime.setTimeSpec(KDateTime::ClockTime);
if (isDate) {
// This is a workaround, for wrongly stored date
Expand Down Expand Up @@ -1201,7 +1203,12 @@ Incidence::Ptr SqliteFormat::selectComponents(sqlite3_stmt *stmt1, sqlite3_stmt

bool startIsDate;
KDateTime start = getDateTime(d->mStorage, stmt1, 5, &startIsDate);
event->setDtStart(start);
if (start.isValid()) {
event->setDtStart(start);
} else {
// start date time is mandatory in RFC5545 for VEVENTS.
event->setDtStart(d->mStorage->fromOriginTime(0));
}

bool endIsDate;
KDateTime end = getDateTime(d->mStorage, stmt1, 9, &endIsDate);
Expand Down
36 changes: 17 additions & 19 deletions src/sqlitestorage.cpp
Expand Up @@ -3231,34 +3231,32 @@ KDateTime SqliteStorage::fromLocalOriginTime(sqlite3_int64 seconds)
KDateTime SqliteStorage::fromOriginTime(sqlite3_int64 seconds)
{
//qCDebug(lcMkcal) << "fromOriginTime" << seconds << d->mOriginTime.addSecs( seconds ).toUtc();
return seconds ? d->mOriginTime.addSecs(seconds).toUtc() : KDateTime();
return d->mOriginTime.addSecs(seconds).toUtc();
}

KDateTime SqliteStorage::fromOriginTime(sqlite3_int64 seconds, QString zonename)
{
KDateTime dt;

if (seconds != 0) {
if (!zonename.isEmpty()) {
// First try system zones.
KTimeZone ktimezone = KSystemTimeZones::zone(zonename);
if (ktimezone.isValid()) {
if (!zonename.isEmpty()) {
// First try system zones.
KTimeZone ktimezone = KSystemTimeZones::zone(zonename);
if (ktimezone.isValid()) {
dt =
d->mOriginTime.addSecs(seconds).toUtc().toTimeSpec(KDateTime::Spec(ktimezone));
} else {
// Then try calendar specific zones.
ICalTimeZones::ZoneMap zones = d->mCalendar->timeZones()->zones();
ICalTimeZone icaltimezone = zones.value(zonename);
const QByteArray emptyTz = "BEGIN:VTIMEZONE\r\nTZID:" + zonename.toUtf8() + "\r\nEND:VTIMEZONE\r\n";
if (icaltimezone.isValid() && icaltimezone.vtimezone() != emptyTz) {
dt =
d->mOriginTime.addSecs(seconds).toUtc().toTimeSpec(KDateTime::Spec(ktimezone));
} else {
// Then try calendar specific zones.
ICalTimeZones::ZoneMap zones = d->mCalendar->timeZones()->zones();
ICalTimeZone icaltimezone = zones.value(zonename);
const QByteArray emptyTz = "BEGIN:VTIMEZONE\r\nTZID:" + zonename.toUtf8() + "\r\nEND:VTIMEZONE\r\n";
if (icaltimezone.isValid() && icaltimezone.vtimezone() != emptyTz) {
dt =
d->mOriginTime.addSecs(seconds).toUtc().toTimeSpec(KDateTime::Spec(icaltimezone));
}
d->mOriginTime.addSecs(seconds).toUtc().toTimeSpec(KDateTime::Spec(icaltimezone));
}
} else {
// Empty zonename, use floating time.
dt = d->mOriginTime.addSecs(seconds).toClockTime();
}
} else {
// Empty zonename, use floating time.
dt = d->mOriginTime.addSecs(seconds).toClockTime();
}
// qCDebug(lcMkcal) << "fromOriginTime" << seconds << zonename << dt;
return dt;
Expand Down
38 changes: 38 additions & 0 deletions tests/tst_storage.cpp
Expand Up @@ -257,6 +257,44 @@ void tst_storage::tst_vtimezone()
}
}

Q_DECLARE_METATYPE(KDateTime)
void tst_storage::tst_veventdtstart_data()
{
QTest::addColumn<KDateTime>("startDateTime");

QTest::newRow("clock time") << KDateTime(QDate(2020, 5, 29), QTime(10, 15), KDateTime::ClockTime);
QTest::newRow("UTC") << KDateTime(QDate(2020, 5, 29), QTime(10, 15), KDateTime::UTC);
QTest::newRow("time zone") << KDateTime(QDate(2020, 5, 29), QTime(10, 15), KDateTime::Spec(KSystemTimeZones::zone("Europe/Paris")));
QTest::newRow("date only") << KDateTime(QDate(2020, 5, 29));
QTest::newRow("origin date time") << m_storage.staticCast<SqliteStorage>()->fromOriginTime(0);
// Not allowed by RFC, will be converted to origin of time after save.
QTest::newRow("bogus KDateTime") << KDateTime();
}

void tst_storage::tst_veventdtstart()
{
QFETCH(KDateTime, startDateTime);

KCalCore::Event::Ptr event = KCalCore::Event::Ptr(new KCalCore::Event);
event->setDtStart(startDateTime);

m_calendar->addEvent(event, NotebookId);
m_storage->save();
QString uid = event->uid();
reloadDb();

KCalCore::Event::Ptr fetchedEvent = m_calendar->event(uid);
QVERIFY(fetchedEvent.data());
QVERIFY(fetchedEvent->dtStart().isValid());
if (startDateTime.isValid()) {
QCOMPARE(fetchedEvent->dtStart(), startDateTime);
} else {
// KDateTime is bogus, invalid date time == January 1st 1970.
QCOMPARE(fetchedEvent->dtStart(), m_storage.staticCast<SqliteStorage>()->fromOriginTime(0));
}
QVERIFY(!fetchedEvent->hasEndDate());
}

void tst_storage::tst_allday_data()
{
QTest::addColumn<QDate>("startDate");
Expand Down
2 changes: 2 additions & 0 deletions tests/tst_storage.h
Expand Up @@ -44,6 +44,8 @@ private slots:
void tst_timezone();
void tst_vtimezone_data();
void tst_vtimezone();
void tst_veventdtstart_data();
void tst_veventdtstart();
void tst_allday_data();
void tst_allday();
void tst_alldayUtc();
Expand Down

0 comments on commit 0ad6b25

Please sign in to comment.