From f7fceca9f3e364492da8f31b3bc73744013df57b Mon Sep 17 00:00:00 2001 From: yeshanshan Date: Tue, 10 Feb 2026 10:39:59 +0800 Subject: [PATCH 1/3] Revert "fix: improve JSON string handling in variant conversion" This reverts commit c58e9de6ae384e5bdfeee45181358f367cbd489a. --- dconfig-center/common/helper.hpp | 59 ++--- dconfig-center/dde-dconfig/main.cpp | 2 +- dconfig-center/tests/CMakeLists.txt | 1 - dconfig-center/tests/ut_dconfigserver.cpp | 4 +- dconfig-center/tests/ut_helper.cpp | 270 ---------------------- 5 files changed, 26 insertions(+), 310 deletions(-) delete mode 100644 dconfig-center/tests/ut_helper.cpp diff --git a/dconfig-center/common/helper.hpp b/dconfig-center/common/helper.hpp index 42a0cff..893b783 100644 --- a/dconfig-center/common/helper.hpp +++ b/dconfig-center/common/helper.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -211,20 +210,12 @@ static QVariant decodeQDBusArgument(const QVariant &v) static QString qvariantToString(const QVariant &v) { - const QJsonValue jsonVal = QJsonValue::fromVariant(v); - if (jsonVal.isString()) { - return QString("\"%1\"").arg(jsonVal.toString()); - } const auto &doc = QJsonDocument::fromVariant(v); return doc.isNull() ? v.toString() : doc.toJson(); } static QString qvariantToStringCompact(const QVariant &v) { - const QJsonValue jsonVal = QJsonValue::fromVariant(v); - if (jsonVal.isString()) { - return QString("\"%1\"").arg(jsonVal.toString()); - } const auto &doc = QJsonDocument::fromVariant(v); return doc.isNull() ? v.toString() : doc.toJson(QJsonDocument::Compact); } @@ -233,48 +224,46 @@ static QVariant stringToQVariant(const QString &s) { QJsonParseError error; const auto &doc = QJsonDocument::fromJson(s.toUtf8(), &error); - if (error.error == QJsonParseError::NoError) { - // 成功解析为对象或数组 + if (error.error == QJsonParseError::NoError) return doc.toVariant(); - } - // 尝试解析为单个 JSON 值(字符串、数字、布尔、null) - // 通过包装在数组中来解析 - QString wrapped = QString("[%1]").arg(s); - const auto &arrayDoc = QJsonDocument::fromJson(wrapped.toUtf8(), &error); + // 将单个JSON值包装成数组后解析(支持数字、布尔、null、字符串等) + const QString wrappedJson = QString("[") + s + QString("]"); + const auto &wrappedDoc = QJsonDocument::fromJson(wrappedJson.toUtf8(), &error); if (error.error == QJsonParseError::NoError) { - QJsonArray array = arrayDoc.array(); - if (!array.isEmpty()) { + QJsonArray array = wrappedDoc.array(); + if (!array.isEmpty()) return array.first().toVariant(); - } } - // 如果都失败了,返回原字符串 + // 解析失败则作为普通字符串处理 return s; } static bool isValidTextJsonValue(const QString &s) { - QString trimmed = s.trimmed(); - if (trimmed.isEmpty()) { - return false; - } - QJsonParseError error; - // 首先尝试解析为 JSON 文档(对象或数组) - QJsonDocument::fromJson(trimmed.toUtf8(), &error); - if (error.error == QJsonParseError::NoError) { + // 首先尝试作为JSON文档解析(对象或数组,包括多行格式) + QJsonDocument::fromJson(s.toUtf8(), &error); + if (error.error == QJsonParseError::NoError) return true; - } - // 如果不是对象或数组,尝试解析为单个 JSON 值(字符串、数字、布尔值、null) - // 通过将其包装在数组中来验证 - QString wrapped = QString("[%1]").arg(trimmed); - QJsonDocument::fromJson(wrapped.toUtf8(), &error); + // 尝试包装成数组解析(支持数字、布尔、null、带引号的JSON字符串) + const QString wrappedJson = QString("[") + s + QString("]"); + QJsonDocument::fromJson(wrappedJson.toUtf8(), &error); + if (error.error == QJsonParseError::NoError) + return true; + + // 如果字符串看起来像JSON结构(以{或[开头)但解析失败,说明是格式错误的JSON + // 例如: [value1","value2"] 或 {"key":value} 等 + // 但普通文本如 "use {key} here" 不会被拒绝 + QString trimmed = s.trimmed(); + if (!trimmed.isEmpty() && (trimmed[0] == '{' || trimmed[0] == '[')) + return false; - // 如果包装后能成功解析,说明是有效的 JSON 值 - return error.error == QJsonParseError::NoError; + // 其他情况作为普通字符串接受 + return true; } static QString qvariantToCmd(const QVariant &v) diff --git a/dconfig-center/dde-dconfig/main.cpp b/dconfig-center/dde-dconfig/main.cpp index 638201e..2e4defa 100644 --- a/dconfig-center/dde-dconfig/main.cpp +++ b/dconfig-center/dde-dconfig/main.cpp @@ -226,7 +226,7 @@ int CommandManager::getCommand() #endif outpuSTD(QString::number(result.toDouble())); } else { - outpuSTD(qvariantToString(result)); + outpuSTD(QString("\"%1\"").arg(qvariantToString(result))); } } else if (method == "name") { QString result = manager->displayName(key, language); diff --git a/dconfig-center/tests/CMakeLists.txt b/dconfig-center/tests/CMakeLists.txt index 15be242..4bb1f15 100644 --- a/dconfig-center/tests/CMakeLists.txt +++ b/dconfig-center/tests/CMakeLists.txt @@ -23,7 +23,6 @@ list(APPEND SOURCES ut_dconfigconn.cpp ut_dconfigrefmanager.cpp ut_dconfigserver.cpp - ut_helper.cpp ) ADD_EXECUTABLE(dconfigtest main.cpp ${HEADERS} ${SOURCES} ${DCONFIG_DBUS_XML} data.qrc) diff --git a/dconfig-center/tests/ut_dconfigserver.cpp b/dconfig-center/tests/ut_dconfigserver.cpp index ad952b8..d48a397 100644 --- a/dconfig-center/tests/ut_dconfigserver.cpp +++ b/dconfig-center/tests/ut_dconfigserver.cpp @@ -200,7 +200,6 @@ TEST_F(ut_DConfigServer, acquireManagerGeneric) { } TEST_F(ut_DConfigServer, removeUserData) { - GTEST_SKIP() << "Skipping removeUserData test for now"; // 测试用户ID const uint testUid1 = 1001; const uint testUid2 = 1002; @@ -255,7 +254,6 @@ TEST_F(ut_DConfigServer, removeUserData) { } TEST_F(ut_DConfigServer, removeUserDataMultipleResources) { - GTEST_SKIP() << "Skipping removeUserData test for now"; // 测试删除用户数据时涉及多个资源的情况 const uint testUid = 1003; @@ -412,7 +410,7 @@ TEST_F(ut_DConfigServer, removeUserDataFiles) { TEST_F(ut_DConfigServer, removeUserDataWithSubpath) { // 测试带有子路径的配置删除 const uint testUid = 1006; - const QString subpath = "/test/subdir"; + const QString subpath = "test/subdir"; // 创建带有子路径的连接 auto path = server->acquireManagerV2(testUid, APP_ID, FILE_NAME, subpath).path(); diff --git a/dconfig-center/tests/ut_helper.cpp b/dconfig-center/tests/ut_helper.cpp deleted file mode 100644 index 3c44539..0000000 --- a/dconfig-center/tests/ut_helper.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-FileCopyrightText: 2026 Uniontech Software Technology Co.,Ltd. -// -// SPDX-License-Identifier: LGPL-3.0-or-later - -#include -#include -#include - -#include "../common/helper.hpp" - -class HelperTest : public testing::Test { -protected: - void SetUp() override {} - void TearDown() override {} -}; - -// 测试 JSON 对象验证 -TEST_F(HelperTest, isValidTextJsonValue_ValidObjects) -{ - // 简单对象 - EXPECT_TRUE(isValidTextJsonValue(R"({"key":"value"})")); - - // 嵌套对象 - EXPECT_TRUE(isValidTextJsonValue(R"({"key1":{"key2":"value2"}})")); - - // 多个键值对 - EXPECT_TRUE(isValidTextJsonValue(R"({"key1":"value1","key2":"value2"})")); - - // 空对象 - EXPECT_TRUE(isValidTextJsonValue("{}")); - - // 对象包含数组 - EXPECT_TRUE(isValidTextJsonValue(R"({"key":["value1","value2"]})")); -} - -// 测试 JSON 数组验证 -TEST_F(HelperTest, isValidTextJsonValue_ValidArrays) -{ - // 字符串数组 - EXPECT_TRUE(isValidTextJsonValue(R"(["value1","value2"])")); - - // 数字数组 - EXPECT_TRUE(isValidTextJsonValue("[1,2,3]")); - - // 混合类型数组 - EXPECT_TRUE(isValidTextJsonValue(R"(["text",123,true,null])")); - - // 空数组 - EXPECT_TRUE(isValidTextJsonValue("[]")); - - // 嵌套数组 - EXPECT_TRUE(isValidTextJsonValue(R"([["a","b"],["c","d"]])")); - - // 对象数组 - EXPECT_TRUE(isValidTextJsonValue(R"([{"key1":"value1"},{"key2":"value2"}])")); -} - -// 测试单个 JSON 值:带引号的字符串 -TEST_F(HelperTest, isValidTextJsonValue_ValidStrings) -{ - // 普通字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("hello")")); - - // 空字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("")")); - - // 包含空格的字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("hello world")")); - - // 包含数字的字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("125")")); - - // 包含转义字符的字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("hello \"world\"")")); - - // 包含反斜杠的字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("C:\\path")")); - - // 包含换行符的字符串 - EXPECT_TRUE(isValidTextJsonValue(R"("line1\nline2")")); -} - -// 测试单个 JSON 值:数字 -TEST_F(HelperTest, isValidTextJsonValue_ValidNumbers) -{ - // 整数 - EXPECT_TRUE(isValidTextJsonValue("123")); - - // 负整数 - EXPECT_TRUE(isValidTextJsonValue("-456")); - - // 浮点数 - EXPECT_TRUE(isValidTextJsonValue("3.14")); - - // 负浮点数 - EXPECT_TRUE(isValidTextJsonValue("-223.56")); - - // 科学计数法 - EXPECT_TRUE(isValidTextJsonValue("1.23e10")); - - // 零 - EXPECT_TRUE(isValidTextJsonValue("0")); -} - -// 测试单个 JSON 值:布尔值 -TEST_F(HelperTest, isValidTextJsonValue_ValidBooleans) -{ - EXPECT_TRUE(isValidTextJsonValue("true")); - EXPECT_TRUE(isValidTextJsonValue("false")); -} - -// 测试单个 JSON 值:null -TEST_F(HelperTest, isValidTextJsonValue_ValidNull) -{ - EXPECT_TRUE(isValidTextJsonValue("null")); -} - -// 测试拒绝不带引号的纯文本 -TEST_F(HelperTest, isValidTextJsonValue_RejectPlainText) -{ - // 不带引号的单词 - EXPECT_FALSE(isValidTextJsonValue("hello")); - EXPECT_FALSE(isValidTextJsonValue("application")); - EXPECT_FALSE(isValidTextJsonValue("text")); - - // 不带引号的多个单词 - EXPECT_FALSE(isValidTextJsonValue("hello world")); - - // 不带引号的数字字符串(应该用引号) - // 注意:纯数字如 "123" 是有效的 JSON 数字 -} - -// 测试拒绝格式错误的 JSON -TEST_F(HelperTest, isValidTextJsonValue_RejectMalformedJSON) -{ - // 数组格式错误 - EXPECT_FALSE(isValidTextJsonValue(R"([s", "d"])")); - EXPECT_FALSE(isValidTextJsonValue(R"(["unclosed)")); - EXPECT_FALSE(isValidTextJsonValue(R"("value1", "value2"])")); - - // 对象格式错误 - EXPECT_FALSE(isValidTextJsonValue(R"({key: "value"})")); // 键没有引号 - EXPECT_FALSE(isValidTextJsonValue(R"({"key":value})")); // 值没有引号 - EXPECT_FALSE(isValidTextJsonValue(R"({"key": "value")")); // 未闭合 - - // 字符串格式错误 - EXPECT_FALSE(isValidTextJsonValue(R"("unclosed)")); - EXPECT_FALSE(isValidTextJsonValue(R"(unclosed")")); - - // 无效的布尔值 - EXPECT_FALSE(isValidTextJsonValue("True")); // 大写 - EXPECT_FALSE(isValidTextJsonValue("FALSE")); // 大写 - EXPECT_FALSE(isValidTextJsonValue("yes")); - - // 无效的 null - EXPECT_FALSE(isValidTextJsonValue("NULL")); - EXPECT_FALSE(isValidTextJsonValue("Null")); - - // 多个顶层值(不是数组) - EXPECT_FALSE(isValidTextJsonValue(R"("value1" "value2")")); -} - -// 测试包装方法的边界情况 -TEST_F(HelperTest, isValidTextJsonValue_EdgeCases) -{ - // 空字符串 - EXPECT_FALSE(isValidTextJsonValue("")); - - // 只有空格 - EXPECT_FALSE(isValidTextJsonValue(" ")); - EXPECT_FALSE(isValidTextJsonValue("\n")); - EXPECT_FALSE(isValidTextJsonValue("\t")); - - // 带前后空格的有效 JSON(应该被 trim 后验证) - EXPECT_TRUE(isValidTextJsonValue(R"( "hello" )")); - EXPECT_TRUE(isValidTextJsonValue("\n[1,2,3]\n")); - EXPECT_TRUE(isValidTextJsonValue(R"( {"key":"value"} )")); - - // 只有引号 - EXPECT_FALSE(isValidTextJsonValue(R"(")")); - - // 只有括号 - EXPECT_FALSE(isValidTextJsonValue("[")); - EXPECT_FALSE(isValidTextJsonValue("]")); - EXPECT_FALSE(isValidTextJsonValue("{")); - EXPECT_FALSE(isValidTextJsonValue("}")); -} - -// 测试 stringToQVariant 函数 -TEST_F(HelperTest, stringToQVariant_ValidConversions) -{ - // 对象 - QVariant obj = stringToQVariant(R"({"key":"value"})"); - EXPECT_EQ(obj.typeId(), QMetaType::QVariantMap); - - // 数组 - QVariant arr = stringToQVariant(R"(["value1","value2"])"); - EXPECT_EQ(arr.typeId(), QMetaType::QVariantList); - - // 字符串 - QVariant str = stringToQVariant(R"("hello")"); - EXPECT_EQ(str.typeId(), QMetaType::QString); - EXPECT_EQ(str.toString(), QString("hello")); - - // 数字 - QVariant num = stringToQVariant("123"); - EXPECT_TRUE(num.canConvert()); - EXPECT_EQ(num.toInt(), 123); - - // 浮点数 - QVariant dbl = stringToQVariant("3.14"); - EXPECT_TRUE(dbl.canConvert()); - EXPECT_DOUBLE_EQ(dbl.toDouble(), 3.14); - - // 布尔值 - QVariant boolTrue = stringToQVariant("true"); - EXPECT_EQ(boolTrue.typeId(), QMetaType::Bool); - EXPECT_TRUE(boolTrue.toBool()); - - QVariant boolFalse = stringToQVariant("false"); - EXPECT_EQ(boolFalse.typeId(), QMetaType::Bool); - EXPECT_FALSE(boolFalse.toBool()); -} - -// 测试 qvariantToString 和 stringToQVariant 的往返转换 -TEST_F(HelperTest, RoundTripConversion) -{ - // 字符串往返 - QString originalStr = "hello world"; - QVariant varStr(originalStr); - QString jsonStr = qvariantToStringCompact(varStr); - QVariant varStr2 = stringToQVariant(jsonStr); - EXPECT_EQ(varStr2.toString(), originalStr); - - QString quotedStr = "he said \"hello\""; - QVariant varQuoted(quotedStr); - QString jsonQuoted = qvariantToStringCompact(varQuoted); - QVariant varQuoted2 = stringToQVariant(jsonQuoted); - EXPECT_EQ(varQuoted2.toString(), QString("\"%1\"").arg(quotedStr)); - - // 数字往返 - int num = 123; - QVariant varNum(num); - QString jsonNum = qvariantToStringCompact(varNum); - QVariant varNum2 = stringToQVariant(jsonNum); - EXPECT_EQ(varNum2.toInt(), num); - - // 布尔值往返 - bool boolVal = true; - QVariant varBool(boolVal); - QString jsonBool = qvariantToStringCompact(varBool); - QVariant varBool2 = stringToQVariant(jsonBool); - EXPECT_EQ(varBool2.toBool(), boolVal); -} - -// 测试特殊字符的处理 -TEST_F(HelperTest, SpecialCharacters) -{ - // 字符串中的特殊字符应该被正确转义 - QString special = "line1\nline2\ttab"; - QVariant varSpecial(special); - QString json = qvariantToStringCompact(varSpecial); - - // 验证 JSON 有效 - EXPECT_TRUE(isValidTextJsonValue(json)); - - // 验证往返转换 - QVariant varSpecial2 = stringToQVariant(json); - EXPECT_EQ(varSpecial2.toString(), special); -} From c4e40b911b0faf9c6b5dbe3b3fc481181db042d5 Mon Sep 17 00:00:00 2001 From: yeshanshan Date: Tue, 10 Feb 2026 10:41:15 +0800 Subject: [PATCH 2/3] Revert "fix: fix JSON validation to accept plain strings" This reverts commit b09e4a1f12d2f2c81db36eee954640531b238d87. --- dconfig-center/common/helper.hpp | 33 +------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/dconfig-center/common/helper.hpp b/dconfig-center/common/helper.hpp index 893b783..8b9d8f6 100644 --- a/dconfig-center/common/helper.hpp +++ b/dconfig-center/common/helper.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -226,44 +225,14 @@ static QVariant stringToQVariant(const QString &s) const auto &doc = QJsonDocument::fromJson(s.toUtf8(), &error); if (error.error == QJsonParseError::NoError) return doc.toVariant(); - - // 将单个JSON值包装成数组后解析(支持数字、布尔、null、字符串等) - const QString wrappedJson = QString("[") + s + QString("]"); - const auto &wrappedDoc = QJsonDocument::fromJson(wrappedJson.toUtf8(), &error); - if (error.error == QJsonParseError::NoError) { - QJsonArray array = wrappedDoc.array(); - if (!array.isEmpty()) - return array.first().toVariant(); - } - - // 解析失败则作为普通字符串处理 return s; } static bool isValidTextJsonValue(const QString &s) { QJsonParseError error; - - // 首先尝试作为JSON文档解析(对象或数组,包括多行格式) QJsonDocument::fromJson(s.toUtf8(), &error); - if (error.error == QJsonParseError::NoError) - return true; - - // 尝试包装成数组解析(支持数字、布尔、null、带引号的JSON字符串) - const QString wrappedJson = QString("[") + s + QString("]"); - QJsonDocument::fromJson(wrappedJson.toUtf8(), &error); - if (error.error == QJsonParseError::NoError) - return true; - - // 如果字符串看起来像JSON结构(以{或[开头)但解析失败,说明是格式错误的JSON - // 例如: [value1","value2"] 或 {"key":value} 等 - // 但普通文本如 "use {key} here" 不会被拒绝 - QString trimmed = s.trimmed(); - if (!trimmed.isEmpty() && (trimmed[0] == '{' || trimmed[0] == '[')) - return false; - - // 其他情况作为普通字符串接受 - return true; + return error.error == QJsonParseError::NoError; } static QString qvariantToCmd(const QVariant &v) From 01da2a59861401a74d1a1b34c6d6f0259c8daa7d Mon Sep 17 00:00:00 2001 From: yeshanshan Date: Tue, 10 Feb 2026 10:45:05 +0800 Subject: [PATCH 3/3] Revert "fix: add JSON validation for text input fields" This reverts commit 528403caba17986a5f8e70d3a0abf4f7761c0b76. --- dconfig-center/common/helper.hpp | 7 ------- dconfig-center/dde-dconfig-editor/mainwindow.cpp | 4 ---- dconfig-center/dde-dconfig-editor/oemdialog.cpp | 4 ---- dconfig-center/dde-dconfig/main.cpp | 4 ---- 4 files changed, 19 deletions(-) diff --git a/dconfig-center/common/helper.hpp b/dconfig-center/common/helper.hpp index 8b9d8f6..ed6dbed 100644 --- a/dconfig-center/common/helper.hpp +++ b/dconfig-center/common/helper.hpp @@ -228,13 +228,6 @@ static QVariant stringToQVariant(const QString &s) return s; } -static bool isValidTextJsonValue(const QString &s) -{ - QJsonParseError error; - QJsonDocument::fromJson(s.toUtf8(), &error); - return error.error == QJsonParseError::NoError; -} - static QString qvariantToCmd(const QVariant &v) { auto stringValue = qvariantToStringCompact(v); diff --git a/dconfig-center/dde-dconfig-editor/mainwindow.cpp b/dconfig-center/dde-dconfig-editor/mainwindow.cpp index 955c376..1b04967 100644 --- a/dconfig-center/dde-dconfig-editor/mainwindow.cpp +++ b/dconfig-center/dde-dconfig-editor/mainwindow.cpp @@ -734,10 +734,6 @@ void KeyContent::setBaseInfo(ConfigGetter *getter, const QString &language) auto widget = new DLineEdit(this); widget->setEnabled(canWrite); connect(widget, &DLineEdit::editingFinished, widget, [this, widget](){ - if (!isValidTextJsonValue(widget->text())) { - qWarning() << "invalid json value" << widget->text(); - return; - } widget->clearFocus(); emit valueChanged(stringToQVariant(widget->text())); }); diff --git a/dconfig-center/dde-dconfig-editor/oemdialog.cpp b/dconfig-center/dde-dconfig-editor/oemdialog.cpp index 17c7b7e..01965d2 100644 --- a/dconfig-center/dde-dconfig-editor/oemdialog.cpp +++ b/dconfig-center/dde-dconfig-editor/oemdialog.cpp @@ -392,10 +392,6 @@ QWidget *OEMDialog::getItemWidget(ConfigGetter *getter, DStandardItem *item) widget->setText(qvariantToString(v)); widget->setEnabled(canWrite); connect(widget, &DLineEdit::textChanged, widget, [this, item](const QString &text){ - if (!isValidTextJsonValue(text)) { - qWarning() << "invalid json value" << text; - return; - } item->setData(stringToQVariant(text), ValueRole); treeItemChanged(item); }); diff --git a/dconfig-center/dde-dconfig/main.cpp b/dconfig-center/dde-dconfig/main.cpp index 2e4defa..8de0774 100644 --- a/dconfig-center/dde-dconfig/main.cpp +++ b/dconfig-center/dde-dconfig/main.cpp @@ -292,10 +292,6 @@ int CommandManager::setCommand() #endif manager->setValue(key, value.toDouble()); } else { - if (!isValidTextJsonValue(value)) { - outpuSTDError(QString("the value:[%1] is not a valid json text.").arg(value)); - return 1; - } manager->setValue(key, stringToQVariant(value)); } } else {