From bbe23d4c42760591a683da9d13335ab106a3a920 Mon Sep 17 00:00:00 2001
From: Leon Styhre <leon@leonstyhre.com>
Date: Fri, 28 Jul 2023 21:55:39 +0200
Subject: [PATCH] Added support for using most characters in custom collection
 names

Also added log output when creating and deleting custom collections
---
 es-app/src/CollectionSystemsManager.cpp       | 50 +++++++++++++------
 .../src/guis/GuiCollectionSystemsOptions.cpp  |  2 +
 2 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/es-app/src/CollectionSystemsManager.cpp b/es-app/src/CollectionSystemsManager.cpp
index 99d3f2b54..66f7cd9e6 100644
--- a/es-app/src/CollectionSystemsManager.cpp
+++ b/es-app/src/CollectionSystemsManager.cpp
@@ -38,6 +38,8 @@
 #include <pugixml.hpp>
 #include <random>
 
+#define INVALID_COLLECTION_CHARACTERS "*\",./:;<>\\|"
+
 CollectionSystemsManager::CollectionSystemsManager() noexcept
     : mWindow {Window::getInstance()}
     , mApplicationStartup {false}
@@ -551,26 +553,30 @@ std::string CollectionSystemsManager::getValidNewCollectionName(const std::strin
 {
     std::string name {inName};
 
-    // Trim leading and trailing whitespaces.
-    name = Utils::String::trim(name);
-
     if (index == 0) {
         size_t remove {std::string::npos};
-        // Get valid name.
-        while ((remove = name.find_first_not_of(
-                    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-[]()' ")) !=
-               std::string::npos)
+        // Remove invalid characters.
+        while ((remove = name.find_first_of(INVALID_COLLECTION_CHARACTERS)) != std::string::npos)
             name.erase(remove, 1);
     }
     else {
-        name += " (" + std::to_string(index) + ")";
+        name.append(" (").append(std::to_string(index)).append(")");
+        LOG(LogInfo)
+            << "A custom collection with the requested name already exists, changing name from \""
+            << inName << "\" to \"" << name << "\"";
     }
 
+    // Trim leading and trailing whitespaces.
+    name = Utils::String::trim(name);
+
     if (name == "")
         name = "new collection";
 
-    if (Utils::String::toLower(name) != Utils::String::toLower(inName)) {
-        LOG(LogInfo) << "Had to change name, from: " << inName << " to: " << name;
+    if (index == 0 && (Utils::String::toLower(name) != Utils::String::toLower(inName))) {
+        LOG(LogWarning)
+            << "Requested custom collection name contained one or more invalid characters, name "
+               "was changed from \""
+            << inName << "\" to \"" << name << "\"";
     }
 
     // Get used systems from es_systems.xml.
@@ -978,15 +984,19 @@ void CollectionSystemsManager::deleteCustomCollection(const std::string& collect
         // Remove the collection configuration file.
         std::string configFile {getCustomCollectionConfigPath(collectionName)};
         Utils::FileSystem::removeFile(configFile);
-        LOG(LogDebug) << "CollectionSystemsManager::deleteCustomCollection(): Deleted the "
-                         "configuration file '"
-                      << configFile << "'.";
-
+        LOG(LogInfo) << "Deleted custom collection \"" << collectionName << "\"";
+        LOG(LogDebug) << "CollectionSystemsManager::deleteCustomCollection(): Deleted "
+                         "configuration file \""
+#if defined(_WIN64)
+                      << Utils::String::replace(configFile, "/", "\\") << "\"";
+#else
+                      << configFile << "\"";
+#endif
         mWindow->queueInfoPopup(
             "DELETED COLLECTION '" + Utils::String::toUpper(collectionName) + "'", 5000);
     }
     else {
-        LOG(LogError) << "Attempted to delete custom collection '" + collectionName + "' " +
+        LOG(LogError) << "Attempted to delete custom collection \"" + collectionName + "\" " +
                              "which doesn't exist.";
     }
 }
@@ -1485,6 +1495,16 @@ std::vector<std::string> CollectionSystemsManager::getCollectionsFromConfigFolde
              it != dirContent.cend(); ++it) {
             if (Utils::FileSystem::isRegularFile(*it)) {
                 std::string filename {Utils::FileSystem::getFileName(*it)};
+
+                if (Utils::FileSystem::getStem(filename).find_first_of(
+                        INVALID_COLLECTION_CHARACTERS) != std::string::npos) {
+                    LOG(LogWarning)
+                        << "Found a custom collection configuration file name with at least one "
+                           "invalid character, skipping file \""
+                        << filename << "\"";
+                    continue;
+                }
+
                 if (std::find(filenames.cbegin(), filenames.cend(),
                               Utils::String::toLower(filename)) != filenames.cend()) {
                     LOG(LogWarning)
diff --git a/es-app/src/guis/GuiCollectionSystemsOptions.cpp b/es-app/src/guis/GuiCollectionSystemsOptions.cpp
index 54a7fa027..14797f808 100644
--- a/es-app/src/guis/GuiCollectionSystemsOptions.cpp
+++ b/es-app/src/guis/GuiCollectionSystemsOptions.cpp
@@ -403,6 +403,8 @@ void GuiCollectionSystemsOptions::createCustomCollection(std::string inName)
         setNeedsGoToSystem(newCollection);
     }
 
+    LOG(LogInfo) << "Created new custom collection \"" << newCollection->getName() << "\"";
+
     Window* window {mWindow};
     while (window->peekGui() && window->peekGui() != ViewController::getInstance())
         delete window->peekGui();