File indexing completed on 2024-06-16 04:55:34

0001 /*
0002     SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include <kitinerary_version.h>
0007 
0008 #include <../lib/plist/plistreader.cpp>
0009 #include "../lib/plist/plistdata_p.h"
0010 
0011 #include <QCommandLineParser>
0012 #include <QCoreApplication>
0013 #include <QFile>
0014 #include <QJsonDocument>
0015 
0016 #include <iostream>
0017 
0018 using namespace KItinerary;
0019 
0020 void dumpValue(const QVariant &v)
0021 {
0022     if (v.userType() == qMetaTypeId<PListArray>()) {
0023         const auto a = v.value<PListArray>();
0024         std::cout << "[";
0025         for (uint64_t i = 0; i < a.size(); ++i) {
0026             std::cout << a.value(i);
0027             if (i != a.size() - 1) {
0028                 std::cout << ",";
0029             }
0030         }
0031         std::cout << "]";
0032         return;
0033     }
0034 
0035     if (v.userType() == qMetaTypeId<PListDict>()) {
0036         const auto a = v.value<PListDict>();
0037         std::cout << "{";
0038         for (uint64_t i = 0; i < a.size(); ++i) {
0039             std::cout << a.key(i) << ":" << a.value(i);
0040             if (i != a.size() - 1) {
0041                 std::cout << ", ";
0042             }
0043         }
0044         std::cout << "}";
0045         return;
0046     }
0047 
0048     if (v.userType() == qMetaTypeId<PListUid>()) {
0049         std::cout << "UID:" << v.value<PListUid>().value;
0050         return;
0051     }
0052 
0053     std::cout << qPrintable(v.toString());
0054 }
0055 
0056 static void writeIndent(int indent)
0057 {
0058     while (indent) {
0059         std::cout << "  ";
0060         --indent;
0061     }
0062 }
0063 
0064 static void dumpRecursive(const PListReader &reader, uint64_t idx, int indent = 0)
0065 {
0066     const auto type = reader.objectType(idx);
0067     switch (type) {
0068         case PListObjectType::Array:
0069         {
0070             const auto a = reader.object(idx).value<PListArray>();
0071             std::cout << "[" << std::endl;
0072             for (uint64_t i = 0; i < a.size(); ++i) {
0073                 writeIndent(indent + 1);
0074                 dumpRecursive(reader, a.value(i), indent + 1);
0075             }
0076             writeIndent(indent);
0077             std::cout << "]" << std::endl;
0078             break;
0079         }
0080         case PListObjectType::Dict:
0081         {
0082             const auto d = reader.object(idx).value<PListDict>();
0083             std::cout << "{" << std::endl;
0084             for (uint64_t i = 0; i < d.size(); ++i) {
0085                 writeIndent(indent + 1);
0086                 dumpValue(reader.object(d.key(i)));
0087                 std::cout << ": ";
0088                 dumpRecursive(reader, d.value(i), indent + 1);
0089             }
0090             writeIndent(indent);
0091             std::cout << "}" << std::endl;
0092             break;
0093         }
0094         default:
0095             dumpValue(reader.object(idx));
0096             std::cout << std::endl;
0097     }
0098 }
0099 
0100 int main(int argc, char **argv)
0101 {
0102     QCoreApplication::setApplicationName(QStringLiteral("plist-dump"));
0103     QCoreApplication::setApplicationVersion(QStringLiteral(KITINERARY_VERSION_STRING));
0104     QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
0105     QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
0106     QCoreApplication app(argc, argv);
0107 
0108     QCommandLineParser parser;
0109     parser.setApplicationDescription(QStringLiteral("Dump binary plist content."));
0110     parser.addHelpOption();
0111     parser.addVersionOption();
0112     parser.addPositionalArgument(QStringLiteral("input"), QStringLiteral("File to read data from, omit for using stdin."));
0113     parser.process(app);
0114 
0115     QFile file;
0116     if (parser.positionalArguments().isEmpty()) {
0117         file.open(stdin, QFile::ReadOnly);
0118     } else {
0119         file.setFileName(parser.positionalArguments().at(0));
0120         if (!file.open(QFile::ReadOnly)) {
0121             std::cerr << qPrintable(file.errorString()) << std::endl;
0122             return 1;
0123         }
0124     }
0125 
0126     const auto buffer = file.readAll();
0127     PListReader reader(buffer);
0128 
0129     // object list
0130     for (uint64_t i = 0; i < reader.objectCount(); ++i) {
0131         std::cout << i << ": [" << (int)reader.objectType(i) << "] ";
0132         dumpValue(reader.object(i));
0133         std::cout << std::endl;
0134     }
0135     std::cout << std::endl << std::endl;
0136 
0137     // object tree
0138     dumpRecursive(reader, reader.rootObjectIndex());
0139     std::cout << std::endl << std::endl;
0140 
0141     // NSKeyedArchiver
0142     std::cout << QJsonDocument(reader.unpackKeyedArchive().toObject()).toJson().constData() << std::endl;
0143 }
0144