File indexing completed on 2024-05-05 05:45:56
0001 /* 0002 Copyright Hannah von Reth <vonreth@kde.org> 0003 0004 Redistribution and use in source and binary forms, with or without 0005 modification, are permitted provided that the following conditions 0006 are met: 0007 1. Redistributions of source code must retain the above copyright 0008 notice, this list of conditions and the following disclaimer. 0009 2. Redistributions in binary form must reproduce the above copyright 0010 notice, this list of conditions and the following disclaimer in the 0011 documentation and/or other materials provided with the distribution. 0012 0013 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 0014 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0015 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0016 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 0017 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 0018 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 0019 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 0020 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 0021 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 0022 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 0023 SUCH DAMAGE. 0024 */ 0025 0026 #include "kshimdata.h" 0027 #include "kshim.h" 0028 0029 #include "../3dparty/nlohmann/json.hpp" 0030 0031 #include <cstring> 0032 #include <iostream> 0033 #include <iomanip> 0034 #include <fstream> 0035 #include <sstream> 0036 0037 using namespace nlohmann; 0038 0039 namespace { 0040 enum class Format { Json, Ubjson }; 0041 Format KSHIM_DATA_FORMAT() 0042 { 0043 static Format format = [] { 0044 const auto var = KShimLib::getenv(KSTRING("KSHIM_FORMAT"), KSTRING("ubjson")); 0045 kLog << "DataFormat: " << var; 0046 if (var == KSTRING("ubjson")) { 0047 return Format::Ubjson; 0048 } 0049 return Format::Json; 0050 }(); 0051 return format; 0052 } 0053 } 0054 0055 KShimData::KShimData(const std::filesystem::path &app) : m_app(app) { } 0056 0057 KShimData::KShimData(const std::vector<uint8_t> &payLoad) 0058 { 0059 kLog << "PayLoad Size: " << payLoad.size(); 0060 json data; 0061 switch (KSHIM_DATA_FORMAT()) { 0062 case Format::Json: 0063 data = json::parse(payLoad.cbegin(), payLoad.cend()); 0064 break; 0065 case Format::Ubjson: 0066 data = json::from_ubjson(payLoad.cbegin(), payLoad.cend()); 0067 break; 0068 } 0069 kLog << "Json Data: " << data.dump(4); 0070 m_app = std::filesystem::path(data["app"].get<KShimLib::string>()); 0071 m_args = data["args"].get<std::vector<KShimLib::string>>(); 0072 m_env = data["env"].get<std::vector<std::pair<KShimLib::string, KShimLib::string>>>(); 0073 m_envOverrideEnabled = data["envOverrideEnabled"].get<bool>(); 0074 m_keepArgv0Enabled = data["keepArgv0Enabled"].get<bool>(); 0075 } 0076 0077 std::filesystem::path KShimData::app() const 0078 { 0079 return m_app; 0080 } 0081 0082 std::filesystem::path KShimData::appAbs() const 0083 { 0084 return makeAbsouteCommand(app()); 0085 } 0086 0087 void KShimData::setApp(const std::filesystem::path &app) 0088 { 0089 m_app = app; 0090 } 0091 0092 const std::vector<KShimLib::string> &KShimData::args() const 0093 { 0094 return m_args; 0095 } 0096 0097 void KShimData::setArgs(const std::vector<KShimLib::string_view> &args) 0098 { 0099 m_args = { args.cbegin(), args.cend() }; 0100 } 0101 0102 void KShimData::addArg(const KShimLib::string_view &arg) 0103 { 0104 m_args.push_back(KShimLib::string(arg)); 0105 } 0106 0107 KShimLib::string KShimData::formatArgs(const std::vector<KShimLib::string_view> &arguments) const 0108 { 0109 KShimLib::stringstream cmd; 0110 cmd << KShimLib::quoteArgs({ args().cbegin(), args().cend() }) 0111 << KShimLib::quoteArgs(arguments); 0112 return cmd.str(); 0113 } 0114 0115 std::vector<uint8_t> KShimData::toJson() const 0116 { 0117 const auto jsonData = json { { "app", app().native() }, 0118 { "args", args() }, 0119 { "env", env() }, 0120 { "envOverrideEnabled", isEnvOverrideEnabled() }, 0121 { "keepArgv0Enabled", isKeepArgv0Enabled() } }; 0122 std::vector<uint8_t> out; 0123 switch (KSHIM_DATA_FORMAT()) { 0124 case Format::Json: { 0125 const auto dump = jsonData.dump(); 0126 out = std::vector<uint8_t>(dump.cbegin(), dump.cend()); 0127 break; 0128 } 0129 case Format::Ubjson: 0130 out = json::to_ubjson(jsonData); 0131 } 0132 0133 kLog << "toJson:" << out.size(); 0134 return out; 0135 } 0136 0137 std::filesystem::path KShimData::makeAbsouteCommand(const std::filesystem::path &path) const 0138 { 0139 if (path.is_absolute()) { 0140 return path; 0141 } else { 0142 auto tmp = KShimLib::binaryName().parent_path() / path; 0143 if (tmp != KShimLib::binaryName() && KShimLib::exists(tmp)) { 0144 return tmp; 0145 } 0146 } 0147 return KShimLib::findInPath(path); 0148 } 0149 0150 const std::vector<std::pair<KShimLib::string, KShimLib::string>> &KShimData::env() const 0151 { 0152 return m_env; 0153 } 0154 0155 void KShimData::setEnv( 0156 const std::vector<std::pair<KShimLib::string_view, KShimLib::string_view>> &env) 0157 { 0158 m_env = { env.cbegin(), env.cend() }; 0159 } 0160 0161 void KShimData::addEnvVar(const std::pair<KShimLib::string_view, KShimLib::string_view> &var) 0162 { 0163 m_env.push_back({ KShimLib::string(var.first), KShimLib::string(var.second) }); 0164 } 0165 0166 bool KShimData::isEnvOverrideEnabled() const 0167 { 0168 return m_envOverrideEnabled; 0169 } 0170 0171 void KShimData::setEnvOverrideEnabled(bool envOverrideEnabled) 0172 { 0173 m_envOverrideEnabled = envOverrideEnabled; 0174 } 0175 0176 std::filesystem::path KShimData::appAbsWithOverride() const 0177 { 0178 if (m_envOverrideEnabled) { 0179 KShimLib::stringstream stream; 0180 stream << "KSHIM_" << KShimLib::string(KShimLib::binaryName().filename()); 0181 const auto overrideApp = 0182 std::filesystem::path(KShimLib::getenv(stream.str(), KShimLib::string(appAbs()))); 0183 if (overrideApp.is_absolute()) { 0184 return overrideApp; 0185 } 0186 kLog2(KLog::Type::Error) << stream.str() 0187 << " must be absolute, current value: " << overrideApp 0188 << " falling back to internal value " << appAbs(); 0189 } 0190 return appAbs(); 0191 } 0192 0193 bool KShimData::isKeepArgv0Enabled() const 0194 { 0195 return m_keepArgv0Enabled; 0196 } 0197 0198 void KShimData::setKeepArgv0Enabled(bool keepArgv0Enabled) 0199 { 0200 m_keepArgv0Enabled = keepArgv0Enabled; 0201 }