diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 4ace2fc1..348754e8 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -93,6 +93,79 @@ bool pid_running(pid_t pid) { } } +std::string url_encode_path(std::string path) { + // We only need to escape a couple of special characters here. This is used + // in the notifications as well as in the XDND proxy. We encode the reserved + // characters mentioned here, with the exception of the forward slash: + // https://en.wikipedia.org/wiki/Percent-encoding#Reserved_characters + std::string escaped; + escaped.reserve( + static_cast(static_cast(path.size()) * 1.1)); + for (const char& character : path) { + switch (character) { + case '!': + escaped.append("%21"); + break; + case '#': + escaped.append("%23"); + break; + case '$': + escaped.append("%24"); + break; + case '%': + escaped.append("%25"); + break; + case '&': + escaped.append("%26"); + break; + case '\'': + escaped.append("%27"); + break; + case '(': + escaped.append("%28"); + break; + case ')': + escaped.append("%29"); + break; + case '*': + escaped.append("%2A"); + break; + case '+': + escaped.append("%2B"); + break; + case ',': + escaped.append("%2C"); + break; + case ':': + escaped.append("%3A"); + break; + case ';': + escaped.append("%3B"); + break; + case '=': + escaped.append("%3D"); + break; + case '?': + escaped.append("%3F"); + break; + case '@': + escaped.append("%40"); + break; + case '[': + escaped.append("%5B"); + break; + case ']': + escaped.append("%5D"); + break; + default: + escaped.push_back(character); + break; + } + } + + return escaped; +} + std::string xml_escape(std::string string) { // Implementation idea stolen from https://stackoverflow.com/a/5665377 std::string escaped; diff --git a/src/common/utils.h b/src/common/utils.h index 3fda783c..155f6538 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -133,6 +133,12 @@ bool is_watchdog_timer_disabled(); */ bool pid_running(pid_t pid); +/** + * URL encode a file path. We won't escape forward slashes, and `path` should + * not yet include the `file://` prefix. + */ +std::string url_encode_path(std::string path); + /** * Escape XML entities within a string. Used inside of desktop notifications. */