JsonUtil.cpp (7364B)
1 // Copyright(c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "winget/JsonUtil.h" 5 #include "AppInstallerStrings.h" 6 7 namespace AppInstaller::JSON 8 { 9 template<> 10 std::optional<std::string> GetValue(const Json::Value& node) 11 { 12 std::optional<std::string> value; 13 14 if (node.isString()) 15 { 16 value = node.asString(); 17 } 18 19 return value; 20 } 21 22 template<> 23 std::optional<uint32_t> GetValue(const Json::Value& node) 24 { 25 std::optional<uint32_t> value; 26 27 if (node.isUInt()) 28 { 29 value = node.asUInt(); 30 } 31 32 return value; 33 } 34 35 template<> 36 std::optional<bool> GetValue(const Json::Value& node) 37 { 38 std::optional<bool> value; 39 40 if (node.isBool()) 41 { 42 value = node.asBool(); 43 } 44 45 return value; 46 } 47 48 template<> 49 std::optional<std::vector<std::string>> GetValue(const Json::Value& node) 50 { 51 std::vector<std::string> result; 52 53 if (node.isArray()) 54 { 55 for (const Json::Value& entry : node) 56 { 57 if (!entry.isString()) 58 { 59 return std::nullopt; 60 } 61 62 result.emplace_back(entry.asString()); 63 } 64 65 return result; 66 } 67 68 return std::nullopt; 69 } 70 71 #ifndef WINGET_DISABLE_FOR_FUZZING 72 utility::string_t GetUtilityString(std::string_view nodeName) 73 { 74 return utility::conversions::to_string_t(nodeName.data()); 75 } 76 77 web::json::value GetStringValue(std::string_view value) 78 { 79 return web::json::value::string(Utility::ConvertToUTF16(value)); 80 } 81 82 std::optional<std::reference_wrapper<const web::json::value>> GetJsonValueFromNode(const web::json::value& node, const utility::string_t& keyName) 83 { 84 if (node.is_null() || !node.has_field(keyName)) 85 { 86 return {}; 87 } 88 89 return node.at(keyName); 90 } 91 92 std::optional<std::string> GetRawStringValueFromJsonValue(const web::json::value& value) 93 { 94 if (value.is_null() || !value.is_string()) 95 { 96 return {}; 97 } 98 99 return utility::conversions::to_utf8string(value.as_string()); 100 } 101 102 std::optional<std::string> GetRawStringValueFromJsonNode(const web::json::value& node, const utility::string_t& keyName) 103 { 104 std::optional<std::reference_wrapper<const web::json::value>> jsonValue = GetJsonValueFromNode(node, keyName); 105 106 if (jsonValue) 107 { 108 return GetRawStringValueFromJsonValue(jsonValue.value().get()); 109 } 110 111 return {}; 112 } 113 114 std::optional<int> GetRawIntValueFromJsonValue(const web::json::value& value) 115 { 116 if (value.is_null() || !value.is_integer()) 117 { 118 return {}; 119 } 120 121 return value.as_integer(); 122 } 123 124 std::optional<int> GetRawIntValueFromJsonNode(const web::json::value& node, const utility::string_t& keyName) 125 { 126 std::optional<std::reference_wrapper<const web::json::value>> jsonValue = GetJsonValueFromNode(node, keyName); 127 128 if (jsonValue) 129 { 130 return GetRawIntValueFromJsonValue(jsonValue.value().get()); 131 } 132 133 return {}; 134 } 135 136 std::optional<bool> GetRawBoolValueFromJsonValue(const web::json::value& value) 137 { 138 if (value.is_null() || !value.is_boolean()) 139 { 140 return {}; 141 } 142 143 return value.as_bool(); 144 } 145 146 std::optional<bool> GetRawBoolValueFromJsonNode(const web::json::value& node, const utility::string_t& keyName) 147 { 148 std::optional<std::reference_wrapper<const web::json::value>> jsonValue = GetJsonValueFromNode(node, keyName); 149 150 if (jsonValue) 151 { 152 return GetRawBoolValueFromJsonValue(jsonValue.value().get()); 153 } 154 155 return {}; 156 } 157 158 std::optional<std::reference_wrapper<const web::json::array>> GetRawJsonArrayFromJsonNode(const web::json::value& node, const utility::string_t& keyName) 159 { 160 std::optional<std::reference_wrapper<const web::json::value>> jsonValue = GetJsonValueFromNode(node, keyName); 161 162 if (!jsonValue || !jsonValue.value().get().is_array()) 163 { 164 return {}; 165 } 166 167 return jsonValue.value().get().as_array(); 168 } 169 170 std::vector<std::string> GetRawStringArrayFromJsonNode( 171 const web::json::value& node, const utility::string_t& keyName) 172 { 173 std::optional<std::reference_wrapper<const web::json::array>> arrayValue = GetRawJsonArrayFromJsonNode(node, keyName); 174 175 std::vector<std::string> result; 176 if (!arrayValue) 177 { 178 return result; 179 } 180 181 for (auto& value : arrayValue.value().get()) 182 { 183 std::optional<std::string> item = GetRawStringValueFromJsonValue(value); 184 if (item) 185 { 186 result.emplace_back(std::move(item.value())); 187 } 188 } 189 190 return result; 191 } 192 193 std::set<std::string> GetRawStringSetFromJsonNode( 194 const web::json::value& node, const utility::string_t& keyName) 195 { 196 std::optional<std::reference_wrapper<const web::json::array>> arrayValue = GetRawJsonArrayFromJsonNode(node, keyName); 197 198 std::set<std::string> result; 199 if (!arrayValue) 200 { 201 return result; 202 } 203 204 for (auto& value : arrayValue.value().get()) 205 { 206 std::optional<std::string> item = GetRawStringValueFromJsonValue(value); 207 if (item) 208 { 209 result.emplace(std::move(item.value())); 210 } 211 } 212 213 return result; 214 } 215 216 std::string Base64Encode(const std::vector<BYTE>& input) 217 { 218 if (input.size() == 0) 219 { 220 return {}; 221 } 222 223 std::wstring result; 224 DWORD resultSize = 0; 225 CryptBinaryToStringW(input.data(), static_cast<DWORD>(input.size()), CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &resultSize); 226 THROW_LAST_ERROR_IF(resultSize == 0); 227 228 result.resize(resultSize); 229 THROW_LAST_ERROR_IF(!CryptBinaryToStringW(input.data(), static_cast<DWORD>(input.size()), CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, result.data(), &resultSize)); 230 // Resize to remove trailing null terminator 231 result.resize(resultSize); 232 233 return Utility::ConvertToUTF8(result); 234 } 235 236 std::vector<BYTE> Base64Decode(const std::string& input) 237 { 238 if (input.empty()) 239 { 240 return {}; 241 } 242 243 auto inputWide = Utility::ConvertToUTF16(input); 244 245 std::vector<BYTE> result; 246 DWORD resultSize = 0; 247 CryptStringToBinaryW(inputWide.data(), static_cast<DWORD>(inputWide.size()), CRYPT_STRING_BASE64, nullptr, &resultSize, nullptr, nullptr); 248 THROW_LAST_ERROR_IF(resultSize == 0); 249 250 result.resize(resultSize); 251 THROW_LAST_ERROR_IF(!CryptStringToBinaryW(inputWide.data(), static_cast<DWORD>(inputWide.size()), CRYPT_STRING_BASE64, result.data(), &resultSize, nullptr, nullptr)); 252 253 return result; 254 } 255 #endif 256 257 bool IsValidNonEmptyStringValue(std::optional<std::string>& value) 258 { 259 if (Utility::IsEmptyOrWhitespace(value.value_or(""))) 260 { 261 return false; 262 } 263 264 return true; 265 } 266 }