From d3261e64152397db2dca4d691a990c6bc2a6f4dd Mon Sep 17 00:00:00 2001 From: Mehmet Samet Duman Date: Thu, 2 Apr 2026 18:51:45 +0300 Subject: NOISSUE add archived projects Signed-off-by: Mehmet Samet Duman --- archived/projt-launcher/launcher/Json.cpp | 388 ++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 archived/projt-launcher/launcher/Json.cpp (limited to 'archived/projt-launcher/launcher/Json.cpp') diff --git a/archived/projt-launcher/launcher/Json.cpp b/archived/projt-launcher/launcher/Json.cpp new file mode 100644 index 0000000000..27393afc8c --- /dev/null +++ b/archived/projt-launcher/launcher/Json.cpp @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +/* === Upstream License Block (Do Not Modify) ============================== + * + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ======================================================================== */ + +#include "Json.h" + +#include + +#include +#include "FileSystem.h" + +namespace Json +{ + void write(const QJsonDocument& doc, const QString& filename) + { + FS::write(filename, doc.toJson()); + } + void write(const QJsonObject& object, const QString& filename) + { + write(QJsonDocument(object), filename); + } + void write(const QJsonArray& array, const QString& filename) + { + write(QJsonDocument(array), filename); + } + + QByteArray toText(const QJsonObject& obj) + { + return QJsonDocument(obj).toJson(QJsonDocument::Compact); + } + QByteArray toText(const QJsonArray& array) + { + return QJsonDocument(array).toJson(QJsonDocument::Compact); + } + + static bool isBinaryJson(const QByteArray& data) + { + decltype(QJsonDocument::BinaryFormatTag) tag = QJsonDocument::BinaryFormatTag; + return memcmp(data.constData(), &tag, sizeof(QJsonDocument::BinaryFormatTag)) == 0; + } + QJsonDocument requireDocument(const QByteArray& data, const QString& what) + { + if (isBinaryJson(data)) + { + // Binary JSON is not supported by this application + throw JsonException(what + ": Invalid JSON. Binary JSON unsupported"); + } + else + { + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(data, &error); + if (error.error != QJsonParseError::NoError) + { + throw JsonException(what + ": Error parsing JSON: " + error.errorString()); + } + return doc; + } + } + QJsonDocument requireDocument(const QString& filename, const QString& what) + { + return requireDocument(FS::read(filename), what); + } + QJsonObject requireObject(const QJsonDocument& doc, const QString& what) + { + if (!doc.isObject()) + { + throw JsonException(what + " is not an object"); + } + return doc.object(); + } + QJsonArray requireArray(const QJsonDocument& doc, const QString& what) + { + if (!doc.isArray()) + { + throw JsonException(what + " is not an array"); + } + return doc.array(); + } + + void writeString(QJsonObject& to, const QString& key, const QString& value) + { + if (!value.isEmpty()) + { + to.insert(key, value); + } + } + + void writeStringList(QJsonObject& to, const QString& key, const QStringList& values) + { + if (!values.isEmpty()) + { + QJsonArray array; + for (auto value : values) + { + array.append(value); + } + to.insert(key, array); + } + } + + template <> + QJsonValue toJson(const QUrl& url) + { + return QJsonValue(url.toString(QUrl::FullyEncoded)); + } + template <> + QJsonValue toJson(const QByteArray& data) + { + return QJsonValue(QString::fromLatin1(data.toHex())); + } + template <> + QJsonValue toJson(const QDateTime& datetime) + { + return QJsonValue(datetime.toString(Qt::ISODate)); + } + template <> + QJsonValue toJson(const QDir& dir) + { + return QDir::current().relativeFilePath(dir.absolutePath()); + } + template <> + QJsonValue toJson(const QUuid& uuid) + { + return uuid.toString(); + } + template <> + QJsonValue toJson(const QVariant& variant) + { + return QJsonValue::fromVariant(variant); + } + + template <> + QByteArray requireIsType(const QJsonValue& value, const QString& what) + { + const QString string = ensureIsType(value, what); + // ensure that the string can be safely cast to Latin1 + if (string != QString::fromLatin1(string.toLatin1())) + { + throw JsonException(what + " is not encodable as Latin1"); + } + return QByteArray::fromHex(string.toLatin1()); + } + + template <> + QJsonArray requireIsType(const QJsonValue& value, const QString& what) + { + if (!value.isArray()) + { + throw JsonException(what + " is not an array"); + } + return value.toArray(); + } + + template <> + QString requireIsType(const QJsonValue& value, const QString& what) + { + if (!value.isString()) + { + throw JsonException(what + " is not a string"); + } + return value.toString(); + } + + template <> + bool requireIsType(const QJsonValue& value, const QString& what) + { + if (!value.isBool()) + { + throw JsonException(what + " is not a bool"); + } + return value.toBool(); + } + + template <> + double requireIsType(const QJsonValue& value, const QString& what) + { + if (!value.isDouble()) + { + throw JsonException(what + " is not a double"); + } + // Burada value'nin double'a çevrilmesi bekleniyor. Eğer value uygun değilse, Qt varsayılan olarak 0 döndürür. + return value.toDouble(); + } + + template <> + int requireIsType(const QJsonValue& value, const QString& what) + { + const double doubl = requireIsType(value, what); + if (fmod(doubl, 1) != 0) + { + throw JsonException(what + " is not an integer"); + } + return int(doubl); + } + + template <> + QDateTime requireIsType(const QJsonValue& value, const QString& what) + { + const QString string = requireIsType(value, what); + const QDateTime datetime = QDateTime::fromString(string, Qt::ISODate); + if (!datetime.isValid()) + { + throw JsonException(what + " is not a ISO formatted date/time value"); + } + return datetime; + } + + template <> + QUrl requireIsType(const QJsonValue& value, const QString& what) + { + const QString string = ensureIsType(value, what); + if (string.isEmpty()) + { + return QUrl(); + } + const QUrl url = QUrl(string, QUrl::StrictMode); + if (!url.isValid()) + { + throw JsonException(what + " is not a correctly formatted URL"); + } + return url; + } + + template <> + QDir requireIsType(const QJsonValue& value, const QString& what) + { + const QString string = requireIsType(value, what); + + // Security: Prevent path traversal attacks + if (QFileInfo(string).isAbsolute()) + { + throw JsonException(what + ": Absolute paths are not allowed"); + } + + // Sanitize path - remove dangerous characters and sequences + QString sanitized = string; + sanitized.replace("..", ""); // Remove parent directory references + sanitized.replace("\\", "/"); // Normalize separators + // Remove other potentially dangerous characters + sanitized.remove(QRegularExpression("[<>:\"|?*]")); + + return QDir::current().absoluteFilePath(sanitized); + } + + template <> + QUuid requireIsType(const QJsonValue& value, const QString& what) + { + const QString string = requireIsType(value, what); + const QUuid uuid = QUuid(string); + if (uuid.toString() != string) // converts back => valid + { + throw JsonException(what + " is not a valid UUID"); + } + return uuid; + } + + template <> + QJsonObject requireIsType(const QJsonValue& value, const QString& what) + { + if (!value.isObject()) + { + throw JsonException(what + " is not an object"); + } + return value.toObject(); + } + + template <> + QVariant requireIsType(const QJsonValue& value, const QString& what) + { + if (value.isNull() || value.isUndefined()) + { + throw JsonException(what + " is null or undefined"); + } + return value.toVariant(); + } + + template <> + QJsonValue requireIsType(const QJsonValue& value, const QString& what) + { + if (value.isNull() || value.isUndefined()) + { + throw JsonException(what + " is null or undefined"); + } + return value; + } + + QStringList toStringList(const QString& jsonString) + { + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError); + + if (parseError.error != QJsonParseError::NoError || !doc.isArray()) + return {}; + try + { + return ensureIsArrayOf(doc.array(), ""); + } + catch (Json::JsonException&) + { + return {}; + } + } + + QString fromStringList(const QStringList& list) + { + QJsonArray array; + for (const QString& str : list) + { + array.append(str); + } + + QJsonDocument doc(toJsonArray(list)); + return QString::fromUtf8(doc.toJson(QJsonDocument::Compact)); + } + + QVariantMap toMap(const QString& jsonString) + { + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError); + + if (parseError.error != QJsonParseError::NoError || !doc.isObject()) + return {}; + + QJsonObject obj = doc.object(); + return obj.toVariantMap(); + } + + QString fromMap(const QVariantMap& map) + { + QJsonObject obj = QJsonObject::fromVariantMap(map); + QJsonDocument doc(obj); + return QString::fromUtf8(doc.toJson(QJsonDocument::Compact)); + } + +} // namespace Json -- cgit 0.0.5-2-1-g0f52