diff --git a/src/publictransport/backends/hafasmgatebackend.cpp b/src/publictransport/backends/hafasmgatebackend.cpp index 8bea357..a6c0e74 100644 --- a/src/publictransport/backends/hafasmgatebackend.cpp +++ b/src/publictransport/backends/hafasmgatebackend.cpp @@ -1,130 +1,158 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "hafasmgatebackend.h" #include "hafasmgateparser.h" #include "logging.h" #include #include #include #include +#include #include #include #include #include #include #include #include #include +#include using namespace KPublicTransport; HafasMgateBackend::HafasMgateBackend() = default; bool HafasMgateBackend::queryJourney(JourneyReply *reply, QNetworkAccessManager *nam) const { return false; } bool HafasMgateBackend::queryDeparture(DepartureReply *reply, QNetworkAccessManager *nam) const { const auto request = reply->request(); const auto id = request.stop().identifier(QLatin1String("hafasId")); // ### temporary, until we have proper name lookup if (id.isEmpty()) { return false; } QJsonObject top; { QJsonObject auth; auth.insert(QLatin1String("aid"), m_aid); auth.insert(QLatin1String("type"), QLatin1String("AID")); top.insert(QLatin1String("auth"), auth); } { QJsonObject client; client.insert(QLatin1String("id"), m_clientId); client.insert(QLatin1String("type"), m_clientType); top.insert(QLatin1String("client"), client); } top.insert(QLatin1String("formatted"), false); top.insert(QLatin1String("lang"), QLatin1String("eng")); { QJsonArray svcReq; { QJsonObject req; req.insert(QLatin1String("getServerDateTime"), true); req.insert(QLatin1String("getTimeTablePeriod"), false); QJsonObject serverInfo; serverInfo.insert(QLatin1String("meth"), QLatin1String("ServerInfo")); serverInfo.insert(QLatin1String("req"), req); svcReq.push_back(serverInfo); } { QJsonObject cfg; cfg.insert(QLatin1String("polyEnc"), QLatin1String("GPA")); QJsonObject req; req.insert(QLatin1String("date"), request.dateTime().toString(QLatin1String("yyyyMMdd"))); req.insert(QLatin1String("maxJny"), 12); req.insert(QLatin1String("stbFltrEquiv"), true); QJsonObject stbLoc; stbLoc.insert(QLatin1String("extId"), id); stbLoc.insert(QLatin1String("state"), QLatin1String("F")); stbLoc.insert(QLatin1String("type"), QLatin1String("S")); req.insert(QLatin1String("stbLoc"), stbLoc); req.insert(QLatin1String("time"), request.dateTime().toString(QLatin1String("hhmmss"))); req.insert(QLatin1String("type"), QLatin1String("DEP")); QJsonObject stationBoard; stationBoard.insert(QLatin1String("cfg"), cfg); stationBoard.insert(QLatin1String("meth"), QLatin1String("StationBoard")); stationBoard.insert(QLatin1String("req"), req); svcReq.push_back(stationBoard); } top.insert(QLatin1String("svcReqL"), svcReq); } top.insert(QLatin1String("ver"), m_version); - auto netReq = QNetworkRequest(QUrl(m_endpoint)); + const auto content = QJsonDocument(top).toJson(); + QUrl url(m_endpoint); + if (!m_micMacSalt.isEmpty()) { + QUrlQuery query; + + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(content); + const auto mic = md5.result().toHex(); + query.addQueryItem(QLatin1String("mic"), QString::fromLatin1(mic)); + + md5.reset(); + // yes, mic is added as hex-encoded string, and the salt is added as raw bytes + md5.addData(mic); + md5.addData(m_micMacSalt); + query.addQueryItem(QLatin1String("mac"), QString::fromLatin1(md5.result().toHex())); + + url.setQuery(query); + } + + auto netReq = QNetworkRequest(url); netReq.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/json")); - auto netReply = nam->post(netReq, QJsonDocument(top).toJson()); + + auto netReply = nam->post(netReq, content); + qDebug() << netReq.url(); qDebug().noquote() << QJsonDocument(top).toJson(); QObject::connect(netReply, &QNetworkReply::finished, [netReply, reply]() { qDebug() << netReply->request().url(); switch (netReply->error()) { case QNetworkReply::NoError: addResult(reply, HafasMgateParser::parseDepartures(netReply->readAll())); break; default: addError(reply, Reply::NetworkError, netReply->errorString()); qCDebug(Log) << netReply->error() << netReply->errorString(); break; } netReply->deleteLater(); }); return true; } + +void HafasMgateBackend::setMicMacSalt(const QString &salt) +{ + m_micMacSalt = QByteArray::fromHex(salt.toUtf8()); +} diff --git a/src/publictransport/backends/hafasmgatebackend.h b/src/publictransport/backends/hafasmgatebackend.h index 4d1a7c9..229cee0 100644 --- a/src/publictransport/backends/hafasmgatebackend.h +++ b/src/publictransport/backends/hafasmgatebackend.h @@ -1,51 +1,56 @@ /* Copyright (C) 2018 Volker Krause This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef KPUBLICTRANSPORT_HAFASMGATEBACKEND_H #define KPUBLICTRANSPORT_HAFASMGATEBACKEND_H #include "abstractbackend.h" #include namespace KPublicTransport { /** Backend for the Hafas mgate.exe interface. */ class HafasMgateBackend : public AbstractBackend { Q_GADGET Q_PROPERTY(QString endpoint MEMBER m_endpoint) Q_PROPERTY(QString aid MEMBER m_aid) Q_PROPERTY(QString clientId MEMBER m_clientId) Q_PROPERTY(QString clientType MEMBER m_clientType) Q_PROPERTY(QString version MEMBER m_version) + /** Salt for request mic/mac parameters, hex-encoded. */ + Q_PROPERTY(QString micMacSalt WRITE setMicMacSalt) public: HafasMgateBackend(); bool queryJourney(JourneyReply *reply, QNetworkAccessManager *nam) const override; bool queryDeparture(DepartureReply *reply, QNetworkAccessManager *nam) const override; private: + void setMicMacSalt(const QString &salt); + QString m_endpoint; QString m_aid; QString m_clientId; QString m_clientType; QString m_version; + QByteArray m_micMacSalt; }; } #endif // KPUBLICTRANSPORT_HAFASMGATEBACKEND_H diff --git a/src/publictransport/networks/deutschebahn.json b/src/publictransport/networks/db.json similarity index 100% rename from src/publictransport/networks/deutschebahn.json rename to src/publictransport/networks/db.json diff --git a/src/publictransport/networks/networks.qrc b/src/publictransport/networks/networks.qrc index 462c332..517ab7e 100644 --- a/src/publictransport/networks/networks.qrc +++ b/src/publictransport/networks/networks.qrc @@ -1,9 +1,10 @@ bvg.json - deutschebahn.json + db.json navitia.json sncb.json sncf.json + vbb.json diff --git a/src/publictransport/networks/vbb.json b/src/publictransport/networks/vbb.json new file mode 100644 index 0000000..a9b8502 --- /dev/null +++ b/src/publictransport/networks/vbb.json @@ -0,0 +1,11 @@ +{ + "type": "hafas_mgate", + "options": { + "endpoint": "https://fahrinfo.vbb.de/bin/mgate.exe", + "aid": "hafas-vbb-apps", + "clientId": "VBB", + "clientType": "AND", + "version": "1.14", + "micMacSalt": "5243544a4d3266467846667878516649" + } +}