Unify code that validates identifiers in Kakoune

Session/Client/User modes names are now requiered to be "identifiers"
they must be in [a-zA-Z0-9_-]. Option names are the same except they
do not allow '-' as they need to be made available through the env vars
and '-' is not supported there.

Fixes #1946
This commit is contained in:
Maxime Coste 2018-03-25 16:35:33 +11:00
parent 2d85e94516
commit 435b5b7ff9
7 changed files with 36 additions and 12 deletions

View File

@ -174,7 +174,8 @@ void ClientManager::clear_client_trash()
bool ClientManager::validate_client_name(StringView name) const
{
return const_cast<ClientManager*>(this)->get_client_ifp(name) == nullptr;
return all_of(name, is_identifier) and
const_cast<ClientManager*>(this)->get_client_ifp(name) == nullptr;
}
Client* ClientManager::get_client_ifp(StringView name)

View File

@ -846,7 +846,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel
const String& cmd_name = parser[0];
auto& cm = CommandManager::instance();
if (contains_that(cmd_name, is_blank))
if (not all_of(cmd_name, is_identifier))
throw runtime_error(format("invalid command name: '{}'", cmd_name));
if (cm.command_defined(cmd_name) and not parser.get_switch("allow-override"))

View File

@ -61,7 +61,7 @@ void KeymapManager::add_user_mode(String user_mode_name)
if (contains(user_modes(), user_mode_name))
throw runtime_error(format("user mode '{}' already defined", user_mode_name));
if (contains_that(user_mode_name, is_blank))
if (not all_of(user_mode_name, is_identifier))
throw runtime_error(format("invalid mode name: '{}'", user_mode_name));
user_modes().push_back(std::move(user_mode_name));

View File

@ -214,13 +214,11 @@ public:
const T& value,
OptionFlags flags = OptionFlags::None)
{
auto is_not_identifier = [](char c) {
return (c < 'a' or c > 'z') and
(c < 'A' or c > 'Z') and
(c < '0' or c > '9') and c != '_';
auto is_option_identifier = [](char c) {
return is_basic_alpha(c) or is_basic_digit(c) or c == '_';
};
if (contains_that(name, is_not_identifier))
if (not all_of(name, is_option_identifier))
throw runtime_error{format("name '{}' contains char out of [a-zA-Z0-9_]", name)};
auto& opts = m_global_manager.m_options;

View File

@ -338,6 +338,20 @@ bool contains_that(Range&& range, T op)
return find_if(range, op) != end(range);
}
template<typename Range, typename T>
bool all_of(Range&& range, T op)
{
using std::begin; using std::end;
return std::all_of(begin(range), end(range), op);
}
template<typename Range, typename T>
bool any_of(Range&& range, T op)
{
using std::begin; using std::end;
return std::any_of(begin(range), end(range), op);
}
template<typename Range, typename U>
void unordered_erase(Range&& vec, U&& value)
{

View File

@ -777,8 +777,8 @@ private:
Server::Server(String session_name)
: m_session{std::move(session_name)}
{
if (contains(m_session, '/'))
throw runtime_error{"Cannot create sessions with '/' in their name"};
if (not all_of(m_session, is_identifier))
throw runtime_error{format("Invalid session name '{}'", session_name)};
int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
fcntl(listen_sock, F_SETFD, FD_CLOEXEC);
@ -816,8 +816,8 @@ Server::Server(String session_name)
bool Server::rename_session(StringView name)
{
if (contains(name, '/'))
throw runtime_error{"Cannot create sessions with '/' in their name"};
if (not all_of(name, is_identifier))
throw runtime_error{format("Invalid session name '{}'", name)};
String old_socket_file = format("{}/kakoune/{}/{}", tmpdir(),
get_user_name(geteuid()), m_session);

View File

@ -53,6 +53,17 @@ inline bool is_basic_alpha(Codepoint c) noexcept
return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z');
}
inline bool is_basic_digit(Codepoint c) noexcept
{
return c >= '0' and c <= '9';
}
inline bool is_identifier(Codepoint c) noexcept
{
return is_basic_alpha(c) or is_basic_digit(c) or
c == '_' or c == '-';
}
inline ColumnCount codepoint_width(Codepoint c) noexcept
{
if (c == '\n')