File indexing completed on 2024-05-19 05:17:26

0001 /*
0002  * SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003  * SPDX-License-Identifier: LGPL-2.0-or-later
0004  */
0005 
0006 #include <KCodecs>
0007 #include <QCborStreamReader>
0008 #include <QDebug>
0009 #include <QFile>
0010 #include <QJsonArray>
0011 #include <QJsonDocument>
0012 #include <QJsonObject>
0013 #include <QJsonValue>
0014 
0015 #include <zlib.h>
0016 
0017 static QString cborDecodeString(QCborStreamReader &reader)
0018 {
0019     QString result;
0020     auto r = reader.readString();
0021     while (r.status == QCborStreamReader::Ok) {
0022         result += r.data;
0023         r = reader.readString();
0024     }
0025 
0026     if (r.status == QCborStreamReader::Error) {
0027         // handle error condition
0028         result.clear();
0029     }
0030     return result;
0031 }
0032 
0033 static QJsonValue readOneValue(QCborStreamReader &reader)
0034 {
0035     switch (reader.type()) {
0036         case QCborStreamReader::Map:
0037         {
0038             reader.enterContainer();
0039             QJsonObject obj;
0040             while (reader.hasNext()) {
0041                 const auto key = readOneValue(reader);
0042                 const auto value = readOneValue(reader);
0043                 obj.insert(key.toVariant().toString(), value);
0044             }
0045             if (reader.lastError() == QCborError::NoError)
0046                 reader.leaveContainer();
0047             return obj;
0048         }
0049         case QCborStreamReader::Array:
0050         {
0051             reader.enterContainer();
0052             QJsonArray array;
0053             while (reader.hasNext()) {
0054                 const auto value = readOneValue(reader);
0055                 array.push_back(value);
0056             }
0057             if (reader.lastError() == QCborError::NoError)
0058                 reader.leaveContainer();
0059             return array;
0060         }
0061         case QCborStreamReader::String:
0062             return cborDecodeString(reader);
0063         case QCborStreamReader::UnsignedInteger:
0064         {
0065             const auto v = reader.toInteger();
0066             reader.next();
0067             return v;
0068         }
0069         case QCborStreamReader::NegativeInteger:
0070         {
0071             const auto v = -(qint64)reader.toNegativeInteger();
0072             reader.next();
0073             return v;
0074         }
0075     }
0076     return QStringLiteral("TODO");
0077 }
0078 
0079 int main(int argc, char **argv)
0080 {
0081     QFile f;
0082     f.open(stdin, QFile::ReadOnly);
0083     const auto in = f.readAll();
0084 
0085     // strip prefix
0086     if (!in.startsWith("HC1:") && !in.startsWith("DK3:")) {
0087         return 1;
0088     }
0089 
0090     // base45 decode
0091     const auto base45Decoded = KCodecs::base45Decode(in.mid(4));
0092 
0093     // decompress
0094     QByteArray inflateOut;
0095     inflateOut.resize(4096);
0096     z_stream stream;
0097     stream.zalloc = nullptr;
0098     stream.zfree = nullptr;
0099     stream.opaque = nullptr;
0100     stream.avail_in = base45Decoded.size();
0101     stream.next_in = reinterpret_cast<unsigned char*>(const_cast<char*>(base45Decoded.data()));
0102     stream.avail_out = inflateOut.size();
0103     stream.next_out = reinterpret_cast<unsigned char*>(inflateOut.data());
0104 
0105     inflateInit(&stream);
0106     const auto res = inflate(&stream, Z_NO_FLUSH);
0107     switch (res) {
0108         case Z_OK:
0109         case Z_STREAM_END:
0110             break; // all good
0111         default:
0112             qWarning() << "zlib decompression failed" << stream.msg;
0113             return 1;
0114     }
0115     inflateEnd(&stream);
0116     inflateOut.truncate(inflateOut.size() - stream.avail_out);
0117 
0118     // unpack COSE
0119     QCborStreamReader cborReader(inflateOut);
0120     cborReader.next();
0121     assert(cborReader.isArray());
0122     cborReader.enterContainer();
0123     cborReader.next();
0124     cborReader.next();
0125     QByteArray cbor2 = cborReader.readByteArray().data;
0126 
0127     // decode CBOR payload
0128     QCborStreamReader cborReader2(cbor2);
0129     QJsonDocument doc(readOneValue(cborReader2).toObject());
0130     qDebug().noquote() << doc.toJson();
0131 
0132     return 0;
0133 }