winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }