From 05bcbddf777f09273c2de00007e690cd9b2bf4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 26 Sep 2022 22:50:40 +0200 Subject: [PATCH] Fixed multiple gx::track parsing issues --- src/data/kmlparser.cpp | 95 +++++++++++++++++++++++++++++------------- src/data/kmlparser.h | 13 +++--- 2 files changed, 73 insertions(+), 35 deletions(-) diff --git a/src/data/kmlparser.cpp b/src/data/kmlparser.cpp index 6fc7d4cb..177c5d8e 100644 --- a/src/data/kmlparser.cpp +++ b/src/data/kmlparser.cpp @@ -32,7 +32,12 @@ static bool isZIP(QFile *file) qreal KMLParser::number() { bool res; - qreal ret = _reader.readElementText().toDouble(&res); + QString str(_reader.readElementText()); + + if (str.isEmpty()) + return NAN; + + qreal ret = str.toDouble(&res); if (!res) _reader.raiseError(QString("Invalid %1").arg( _reader.name().toString())); @@ -59,6 +64,8 @@ bool KMLParser::coord(Trackpoint &trackpoint) qreal val[3]; bool res; + if (data.isEmpty()) + return true; sp = data.constData(); ep = sp + data.size(); @@ -331,9 +338,9 @@ void KMLParser::point(Waypoint &waypoint) _reader.raiseError("Missing Point coordinates"); } -void KMLParser::heartRate(SegmentData &segment, int start) +void KMLParser::heartRate(SegmentData &segment) { - int i = start; + int i = 0; const char error[] = "Heartrate data count mismatch"; while (_reader.readNextStartElement()) { @@ -348,13 +355,13 @@ void KMLParser::heartRate(SegmentData &segment, int start) _reader.skipCurrentElement(); } - if (i != segment.size()) + if (!_reader.error() && i != segment.size()) _reader.raiseError(error); } -void KMLParser::cadence(SegmentData &segment, int start) +void KMLParser::cadence(SegmentData &segment) { - int i = start; + int i = 0; const char error[] = "Cadence data count mismatch"; while (_reader.readNextStartElement()) { @@ -369,13 +376,13 @@ void KMLParser::cadence(SegmentData &segment, int start) _reader.skipCurrentElement(); } - if (i != segment.size()) + if (!_reader.error() && i != segment.size()) _reader.raiseError(error); } -void KMLParser::speed(SegmentData &segment, int start) +void KMLParser::speed(SegmentData &segment) { - int i = start; + int i = 0; const char error[] = "Speed data count mismatch"; while (_reader.readNextStartElement()) { @@ -390,13 +397,13 @@ void KMLParser::speed(SegmentData &segment, int start) _reader.skipCurrentElement(); } - if (i != segment.size()) + if (!_reader.error() && i != segment.size()) _reader.raiseError(error); } -void KMLParser::temperature(SegmentData &segment, int start) +void KMLParser::temperature(SegmentData &segment) { - int i = start; + int i = 0; const char error[] = "Temperature data count mismatch"; while (_reader.readNextStartElement()) { @@ -411,25 +418,49 @@ void KMLParser::temperature(SegmentData &segment, int start) _reader.skipCurrentElement(); } - if (i != segment.size()) + if (!_reader.error() && i != segment.size()) _reader.raiseError(error); } -void KMLParser::schemaData(SegmentData &segment, int start) +void KMLParser::power(SegmentData &segment) +{ + int i = 0; + const char error[] = "Power data count mismatch"; + + while (_reader.readNextStartElement()) { + if (_reader.name() == QLatin1String("value")) { + if (i < segment.size()) + segment[i++].setPower(number()); + else { + _reader.raiseError(error); + return; + } + } else + _reader.skipCurrentElement(); + } + + if (!_reader.error() && i != segment.size()) + _reader.raiseError(error); +} + +void KMLParser::schemaData(SegmentData &segment) { while (_reader.readNextStartElement()) { if (_reader.name() == QLatin1String("SimpleArrayData")) { QXmlStreamAttributes attr = _reader.attributes(); - QString name(attr.value("name").toString()); + // There are files using capitalized names in the wild! + QString name(attr.value("name").toString().toLower()); - if (name == QLatin1String("Heartrate")) - heartRate(segment, start); - else if (name == QLatin1String("Cadence")) - cadence(segment, start); - else if (name == QLatin1String("Speed")) - speed(segment, start); - else if (name == QLatin1String("Temperature")) - temperature(segment, start); + if (name == QLatin1String("heartrate")) + heartRate(segment); + else if (name == QLatin1String("cadence")) + cadence(segment); + else if (name == QLatin1String("speed")) + speed(segment); + else if (name == QLatin1String("temperature")) + temperature(segment); + else if (name == QLatin1String("power")) + power(segment); else _reader.skipCurrentElement(); } else @@ -437,11 +468,11 @@ void KMLParser::schemaData(SegmentData &segment, int start) } } -void KMLParser::extendedData(SegmentData &segment, int start) +void KMLParser::extendedData(SegmentData &segment) { while (_reader.readNextStartElement()) { if (_reader.name() == QLatin1String("SchemaData")) - schemaData(segment, start); + schemaData(segment); else _reader.skipCurrentElement(); } @@ -450,8 +481,7 @@ void KMLParser::extendedData(SegmentData &segment, int start) void KMLParser::track(SegmentData &segment) { const char error[] = "gx:coord/when element count mismatch"; - int first = segment.size(); - int i = first; + int i = 0; while (_reader.readNextStartElement()) { if (_reader.name() == QLatin1String("when")) { @@ -467,13 +497,20 @@ void KMLParser::track(SegmentData &segment) } i++; } else if (_reader.name() == QLatin1String("ExtendedData")) - extendedData(segment, first); + extendedData(segment); else _reader.skipCurrentElement(); } - if (i != segment.size()) + if (i != segment.size()) { _reader.raiseError(error); + return; + } + + // empty (invalid) coordinates are allowed per KML specification! + for (int i = 0; i < segment.size(); i++) + if (segment.at(i).coordinates().isNull()) + segment.remove(i); } void KMLParser::multiTrack(TrackData &t) diff --git a/src/data/kmlparser.h b/src/data/kmlparser.h index 833205da..8861edb7 100644 --- a/src/data/kmlparser.h +++ b/src/data/kmlparser.h @@ -53,12 +53,13 @@ private: bool lineCoordinates(SegmentData &segment); bool polygonCoordinates(QVector &points); bool coord(Trackpoint &trackpoint); - void extendedData(SegmentData &segment, int start); - void schemaData(SegmentData &segment, int start); - void heartRate(SegmentData &segment, int start); - void cadence(SegmentData &segment, int start); - void speed(SegmentData &segment, int start); - void temperature(SegmentData &segment, int start); + void extendedData(SegmentData &segment); + void schemaData(SegmentData &segment); + void heartRate(SegmentData &segment); + void cadence(SegmentData &segment); + void speed(SegmentData &segment); + void temperature(SegmentData &segment); + void power(SegmentData &segment); QDateTime timeStamp(); qreal number(); QDateTime time();