mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 12:43:16 -04:00
add toolinfo check
Co-Authored-By:Agent Signed-off-by: unknown <sijunjie@huawei.com>
This commit is contained in:
@@ -78,7 +78,7 @@ public:
|
||||
std::shared_ptr<ArgMapping> argMapping;
|
||||
std::vector<std::string> eventTypes;
|
||||
std::string eventSchemas; // JSON string (map of event type to schema)
|
||||
int32_t timeout = 30;
|
||||
int32_t timeout = 1800;
|
||||
bool hasSubCommand = false;
|
||||
std::map<std::string, SubCommandInfo> subcommands;
|
||||
|
||||
@@ -102,6 +102,20 @@ public:
|
||||
*/
|
||||
static bool ValidateExecutablePath(const std::string &path);
|
||||
|
||||
/**
|
||||
* @brief Validate requirePermissions array (all items must be unique strings)
|
||||
* @param permissions Permissions array to validate
|
||||
* @return bool true if valid
|
||||
*/
|
||||
static bool ValidateRequirePermissions(const std::vector<std::string> &permissions);
|
||||
|
||||
/**
|
||||
* @brief Validate eventTypes array (all items must be unique strings)
|
||||
* @param eventTypes Event types array to validate
|
||||
* @return bool true if valid
|
||||
*/
|
||||
static bool ValidateEventTypes(const std::vector<std::string> &eventTypes);
|
||||
|
||||
/**
|
||||
* @brief Parse ToolInfo from JSON object
|
||||
* @param json Input JSON object
|
||||
@@ -114,6 +128,13 @@ public:
|
||||
* @brief Convert ToolInfo to JSON object
|
||||
*/
|
||||
nlohmann::json ParseToJson() const;
|
||||
|
||||
/**
|
||||
* @brief Validate ToolInfo fields
|
||||
* @param tool ToolInfo to validate
|
||||
* @return bool true if valid
|
||||
*/
|
||||
static bool Validate(const ToolInfo &tool);
|
||||
};
|
||||
} // namespace CliTool
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "tool_info.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <set>
|
||||
|
||||
#include "hilog_tag_wrapper.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace CliTool {
|
||||
@@ -154,73 +157,167 @@ bool ToolInfo::ValidateExecutablePath(const std::string &path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToolInfo::ValidateRequirePermissions(const std::vector<std::string> &permissions)
|
||||
{
|
||||
if (permissions.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> seenPerms;
|
||||
for (const auto &perm : permissions) {
|
||||
if (seenPerms.find(perm) != seenPerms.end()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ValidateRequirePermissions failed: duplicate permission %{public}s",
|
||||
perm.c_str());
|
||||
return false;
|
||||
}
|
||||
seenPerms.insert(perm);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToolInfo::ValidateEventTypes(const std::vector<std::string> &eventTypes)
|
||||
{
|
||||
if (eventTypes.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> seenEvents;
|
||||
for (const auto &evt : eventTypes) {
|
||||
if (seenEvents.find(evt) != seenEvents.end()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ValidateEventTypes failed: duplicate eventType %{public}s",
|
||||
evt.c_str());
|
||||
return false;
|
||||
}
|
||||
seenEvents.insert(evt);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToolInfo::ParseFromJson(const nlohmann::json &json, ToolInfo &tool)
|
||||
{
|
||||
// name is required and must be valid
|
||||
if (!json.contains("name") || !json["name"].is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: name is missing or not a string");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name = json["name"];
|
||||
if (!ValidateName(name)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: name %{public}s is invalid", name.c_str());
|
||||
return false;
|
||||
}
|
||||
tool.name = name;
|
||||
|
||||
// version is required and must be non-empty
|
||||
if (!json.contains("version") || !json["version"].is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: version is missing or not a string");
|
||||
return false;
|
||||
}
|
||||
std::string version = json["version"];
|
||||
if (version.empty()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: version is empty");
|
||||
return false;
|
||||
}
|
||||
tool.version = version;
|
||||
|
||||
// description is required and must be non-empty
|
||||
if (!json.contains("description") || !json["description"].is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: description is missing or not a string");
|
||||
return false;
|
||||
}
|
||||
std::string description = json["description"];
|
||||
if (description.empty()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: description is empty");
|
||||
return false;
|
||||
}
|
||||
tool.description = description;
|
||||
|
||||
// executablePath is required and must be absolute path
|
||||
if (!json.contains("executablePath") || !json["executablePath"].is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: executablePath is missing or not a string");
|
||||
return false;
|
||||
}
|
||||
std::string executablePath = json["executablePath"];
|
||||
if (!ValidateExecutablePath(executablePath)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: executablePath %{public}s is invalid",
|
||||
executablePath.c_str());
|
||||
return false;
|
||||
}
|
||||
tool.executablePath = executablePath;
|
||||
|
||||
if (json.contains("requirePermissions") && json["requirePermissions"].is_array()) {
|
||||
tool.requirePermissions = json["requirePermissions"];
|
||||
std::vector<std::string> perms;
|
||||
for (const auto &perm : json["requirePermissions"]) {
|
||||
if (!perm.is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: requirePermissions contains non-string item");
|
||||
return false;
|
||||
}
|
||||
perms.push_back(perm.get<std::string>());
|
||||
}
|
||||
if (!ValidateRequirePermissions(perms)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: requirePermissions validation failed");
|
||||
return false;
|
||||
}
|
||||
tool.requirePermissions = std::move(perms);
|
||||
}
|
||||
if (json.contains("inputSchema") && json["inputSchema"].is_object()) {
|
||||
if (json.contains("inputSchema")) {
|
||||
if (!json["inputSchema"].is_object()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: inputSchema is not a JSON object");
|
||||
return false;
|
||||
}
|
||||
tool.inputSchema = json["inputSchema"].dump();
|
||||
}
|
||||
if (json.contains("outputSchema") && json["outputSchema"].is_object()) {
|
||||
if (json.contains("outputSchema")) {
|
||||
if (!json["outputSchema"].is_object()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: outputSchema is not a JSON object");
|
||||
return false;
|
||||
}
|
||||
tool.outputSchema = json["outputSchema"].dump();
|
||||
}
|
||||
if (json.contains("argMapping") && json["argMapping"].is_object()) {
|
||||
tool.argMapping = std::make_shared<ArgMapping>();
|
||||
if (!ArgMapping::ParseFromJson(json["argMapping"], *tool.argMapping)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: argMapping parse failed");
|
||||
tool.argMapping = nullptr;
|
||||
return false; // argMapping parse failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (json.contains("eventSchemas") && json["eventSchemas"].is_object()) {
|
||||
tool.eventSchemas = json["eventSchemas"].dump();
|
||||
}
|
||||
if (json.contains("timeout") && json["timeout"].is_number()) {
|
||||
tool.timeout = json["timeout"];
|
||||
if (json.contains("timeout")) {
|
||||
if (!json["timeout"].is_number_integer()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: timeout is not an integer");
|
||||
return false;
|
||||
}
|
||||
int32_t timeoutValue = json["timeout"];
|
||||
if (timeoutValue <= 0 || timeoutValue > 1800) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: timeout %{public}d is out of range (0, 1800]",
|
||||
timeoutValue);
|
||||
return false;
|
||||
}
|
||||
tool.timeout = timeoutValue;
|
||||
}
|
||||
if (json.contains("eventTypes") && json["eventTypes"].is_array()) {
|
||||
tool.eventTypes = json["eventTypes"];
|
||||
if (json.contains("eventTypes")) {
|
||||
if (!json["eventTypes"].is_array()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: eventTypes is not an array");
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> types;
|
||||
for (const auto &item : json["eventTypes"]) {
|
||||
if (!item.is_string()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: eventTypes contains non-string item");
|
||||
return false;
|
||||
}
|
||||
types.push_back(item.get<std::string>());
|
||||
}
|
||||
if (!ValidateEventTypes(types)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: eventTypes validation failed");
|
||||
return false;
|
||||
}
|
||||
tool.eventTypes = std::move(types);
|
||||
}
|
||||
if (json.contains("hasSubCommand") && json["hasSubCommand"].is_boolean()) {
|
||||
tool.hasSubCommand = json["hasSubCommand"];
|
||||
@@ -229,7 +326,9 @@ bool ToolInfo::ParseFromJson(const nlohmann::json &json, ToolInfo &tool)
|
||||
for (auto it = json["subcommands"].begin(); it != json["subcommands"].end(); ++it) {
|
||||
SubCommandInfo subCmd;
|
||||
if (!SubCommandInfo::ParseFromJson(it.value(), subCmd)) {
|
||||
return false; // subcommand parse failed
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "ParseFromJson failed: subcommand %{public}s parse failed",
|
||||
it.key().c_str());
|
||||
return false;
|
||||
}
|
||||
tool.subcommands[it.key()] = std::move(subCmd);
|
||||
}
|
||||
@@ -288,5 +387,95 @@ nlohmann::json ToolInfo::ParseToJson() const
|
||||
return j;
|
||||
}
|
||||
|
||||
bool ToolInfo::Validate(const ToolInfo &tool)
|
||||
{
|
||||
// name must be valid
|
||||
if (!ValidateName(tool.name)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: name %{public}s is invalid", tool.name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// version is required and must be non-empty
|
||||
if (tool.version.empty()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: version is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// description is required and must be non-empty
|
||||
if (tool.description.empty()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: description is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
// executablePath must be valid absolute path
|
||||
if (!ValidateExecutablePath(tool.executablePath)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: executablePath %{public}s is invalid",
|
||||
tool.executablePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// requirePermissions: if not empty, all items must be unique
|
||||
if (!ValidateRequirePermissions(tool.requirePermissions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// inputSchema: if not empty, must be valid JSON string
|
||||
if (!tool.inputSchema.empty()) {
|
||||
nlohmann::json inputSchemaJson = nlohmann::json::parse(tool.inputSchema, nullptr, false);
|
||||
if (inputSchemaJson.is_discarded()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: inputSchema is not valid JSON");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// outputSchema: if not empty, must be valid JSON string
|
||||
if (!tool.outputSchema.empty()) {
|
||||
nlohmann::json outputSchemaJson = nlohmann::json::parse(tool.outputSchema, nullptr, false);
|
||||
if (outputSchemaJson.is_discarded()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: outputSchema is not valid JSON");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// argMapping is required
|
||||
if (tool.argMapping == nullptr) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: argMapping is null");
|
||||
return false;
|
||||
}
|
||||
if (!ArgMapping::Validate(*tool.argMapping)) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: argMapping validation failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// timeout must be > 0 and <= 1800
|
||||
if (tool.timeout <= 0 || tool.timeout > 1800) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: timeout %{public}d is out of range (0, 1800]",
|
||||
tool.timeout);
|
||||
return false;
|
||||
}
|
||||
|
||||
// eventTypes: if not empty, all items must be unique
|
||||
if (!ValidateEventTypes(tool.eventTypes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// eventSchemas: if not empty, must be valid JSON string
|
||||
if (!tool.eventSchemas.empty()) {
|
||||
nlohmann::json eventSchemasJson = nlohmann::json::parse(tool.eventSchemas, nullptr, false);
|
||||
if (eventSchemasJson.is_discarded()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: eventSchemas is not valid JSON");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if hasSubCommand is true, subcommands must not be empty
|
||||
if (tool.hasSubCommand && tool.subcommands.empty()) {
|
||||
TAG_LOGE(AAFwkTag::CLI_TOOL, "Validate failed: hasSubCommand is true but subcommands is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace CliTool
|
||||
} // namespace OHOS
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user