Added constrains to id generator
This commit prevents id with more than one '/'. Slash can be used to
create namespaces to avoid id conflicts between multiple users.
Changed generator logic to take provided id as a name if no name was
provided.
Tested:
- Tested that id and name generates correctly
- It is no longer possible to add id with more than one '/'
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: Ieef32ddb71b5a4870117aab0d624cbd46b5893e6
diff --git a/src/utils/generate_id.cpp b/src/utils/generate_id.cpp
index adb1a5b..6631e69 100644
--- a/src/utils/generate_id.cpp
+++ b/src/utils/generate_id.cpp
@@ -12,28 +12,44 @@
static constexpr std::string_view allowedCharactersInId =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_/";
-}
-
-void verifyIdCharacters(std::string_view triggerId)
+size_t countDigits(size_t value)
{
- if (triggerId.find_first_not_of(details::allowedCharactersInId) !=
- std::string::npos)
+ size_t result = 1;
+ while (value >= 10)
{
- throw sdbusplus::exception::SdBusError(
- static_cast<int>(std::errc::invalid_argument),
- "Invalid character in id");
+ ++result;
+ value /= 10;
}
+ return result;
}
-std::string generateId(std::string_view prefix, std::string_view name,
+std::string generateId(std::string_view id, std::string_view name,
const std::vector<std::string>& conflictIds,
size_t maxLength)
{
- verifyIdCharacters(prefix);
+ verifyIdCharacters(id);
- if (!prefix.empty() && !prefix.ends_with('/'))
+ if (id.starts_with('/'))
{
- return std::string(prefix);
+ id = id.substr(1);
+ }
+
+ if ((id.length() > maxLength) ||
+ (id.ends_with('/') && id.length() >= maxLength))
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::invalid_argument), "Id too long");
+ }
+
+ if (!id.empty() && !id.ends_with('/'))
+ {
+ if (std::find(conflictIds.begin(), conflictIds.end(), id) !=
+ conflictIds.end())
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::file_exists), "Duplicated id");
+ }
+ return std::string(id);
}
std::string strippedId(name);
@@ -45,7 +61,7 @@
std::string_view::npos;
}),
strippedId.end());
- strippedId = std::string(prefix) + strippedId;
+ strippedId = std::string(id) + strippedId;
size_t idx = 0;
std::string tmpId = strippedId.substr(0, maxLength);
@@ -54,11 +70,65 @@
conflictIds.end() ||
tmpId.empty())
{
- tmpId = strippedId.substr(0, maxLength - std::to_string(idx).length()) +
- std::to_string(idx);
+ size_t digitsInIdx = countDigits(idx);
+
+ if (digitsInIdx > maxLength)
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::file_exists),
+ "Unique indices are depleted");
+ }
+
+ tmpId =
+ strippedId.substr(0, maxLength - digitsInIdx) + std::to_string(idx);
++idx;
}
+
return tmpId;
}
+} // namespace details
+
+void verifyIdCharacters(std::string_view id)
+{
+ if (id.find_first_not_of(details::allowedCharactersInId) !=
+ std::string::npos)
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::invalid_argument),
+ "Invalid character in id");
+ }
+
+ if (auto pos = id.find_first_of("/");
+ pos != std::string::npos && pos != id.find_last_of("/"))
+ {
+ throw sdbusplus::exception::SdBusError(
+ static_cast<int>(std::errc::invalid_argument),
+ "Too many '/' in id");
+ }
+}
+
+std::pair<std::string, std::string> generateId(
+ std::string_view id, std::string_view name, std::string_view defaultName,
+ const std::vector<std::string>& conflictIds, const size_t maxLength)
+{
+ if (name.empty() && !id.ends_with('/'))
+ {
+ name = id;
+
+ if (auto pos = name.find_last_of("/"); pos != std::string::npos)
+ {
+ name = name.substr(pos + 1);
+ }
+ }
+
+ if (name.empty())
+ {
+ name = defaultName;
+ }
+
+ return std::make_pair(details::generateId(id, name, conflictIds, maxLength),
+ std::string{name});
+}
+
} // namespace utils
diff --git a/src/utils/generate_id.hpp b/src/utils/generate_id.hpp
index aa9508e..94952dc 100644
--- a/src/utils/generate_id.hpp
+++ b/src/utils/generate_id.hpp
@@ -7,9 +7,9 @@
namespace utils
{
-void verifyIdCharacters(std::string_view triggerId);
-std::string generateId(std::string_view prefix, std::string_view triggerName,
- const std::vector<std::string>& conflictIds,
- size_t maxLength);
+void verifyIdCharacters(std::string_view id);
+std::pair<std::string, std::string> generateId(
+ std::string_view id, std::string_view name, std::string_view defaultName,
+ const std::vector<std::string>& conflictIds, const size_t maxLength);
} // namespace utils