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 }