Browse Source

Escaped regexp

git-svn-id: https://klish.googlecode.com/svn/trunk@452 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 13 years ago
parent
commit
bf68961b67

+ 4 - 4
clish/callback_config.c

@@ -105,7 +105,7 @@ bool_t clish_config_callback(clish_context_t *context)
 		lub_string_cat(&command, "-d");
 
 		/* Add filename */
-		str = clish_shell_expand(clish_config__get_file(config), context);
+		str = clish_shell_expand(clish_config__get_file(config), SHELL_VAR_ACTION, context);
 		if (str) {
 			lub_string_cat(&command, " -f \"");
 			if (str[0] != '\0')
@@ -123,7 +123,7 @@ bool_t clish_config_callback(clish_context_t *context)
 
 	/* Add pattern */
 	if ((CLISH_CONFIG_SET == op) || (CLISH_CONFIG_UNSET == op)) {
-		str = clish_shell_expand(clish_config__get_pattern(config), context);
+		str = clish_shell_expand(clish_config__get_pattern(config), SHELL_VAR_REGEX, context);
 		if (!str) {
 			lub_string_free(command);
 			return BOOL_FALSE;
@@ -144,7 +144,7 @@ bool_t clish_config_callback(clish_context_t *context)
 
 	/* Add sequence */
 	if (clish_config__get_seq(config)) {
-		str = clish_shell_expand(clish_config__get_seq(config), context);
+		str = clish_shell_expand(clish_config__get_seq(config), SHELL_VAR_ACTION, context);
 		snprintf(tmp, sizeof(tmp) - 1, " -q %u", str2ushort(str));
 		tmp[sizeof(tmp) - 1] = '\0';
 		lub_string_cat(&command, tmp);
@@ -153,7 +153,7 @@ bool_t clish_config_callback(clish_context_t *context)
 
 	/* Add pwd */
 	if (clish_config__get_depth(config)) {
-		str = clish_shell_expand(clish_config__get_depth(config), context);
+		str = clish_shell_expand(clish_config__get_depth(config), SHELL_VAR_ACTION, context);
 		num = str2ushort(str);
 		lub_string_free(str);
 	} else {

+ 4 - 2
clish/command.h

@@ -50,6 +50,7 @@ const char *clish_command__get_suffix(const clish_command_t * instance);
 const char *clish_command__get_text(const clish_command_t * instance);
 const char *clish_command__get_detail(const clish_command_t * instance);
 const char *clish_command__get_escape_chars(const clish_command_t * instance);
+const char *clish_command__get_regex_chars(const clish_command_t * instance);
 const clish_param_t *clish_command__get_args(const clish_command_t * instance);
 clish_action_t *clish_command__get_action(const clish_command_t *instance);
 clish_view_t *clish_command__get_view(const clish_command_t * instance);
@@ -58,8 +59,9 @@ unsigned int clish_command__get_param_count(const clish_command_t * instance);
 const clish_param_t *clish_command__get_param(const clish_command_t * instance,
 	unsigned index);
 clish_paramv_t *clish_command__get_paramv(const clish_command_t * instance);
-void
-clish_command__set_escape_chars(clish_command_t * instance,
+void clish_command__set_escape_chars(clish_command_t * instance,
+	const char *escape_chars);
+void clish_command__set_regex_chars(clish_command_t * instance,
 	const char *escape_chars);
 void clish_command__set_args(clish_command_t * instance, clish_param_t * args);
 void clish_command__set_detail(clish_command_t * instance, const char *detail);

+ 17 - 1
clish/command/command.c

@@ -37,6 +37,7 @@ clish_command_init(clish_command_t *this, const char *name, const char *text)
 	this->config = clish_config_new();
 	this->detail = NULL;
 	this->escape_chars = NULL;
+	this->regex_chars = NULL;
 	this->args = NULL;
 	this->pview = NULL;
 	this->lock = BOOL_TRUE;
@@ -63,6 +64,7 @@ static void clish_command_fini(clish_command_t * this)
 	clish_config_delete(this->config);
 	lub_string_free(this->detail);
 	lub_string_free(this->escape_chars);
+	lub_string_free(this->regex_chars);
 	if (this->args)
 		clish_param_delete(this->args);
 }
@@ -303,7 +305,7 @@ void
 clish_command__set_escape_chars(clish_command_t * this,
 	const char *escape_chars)
 {
-	assert(NULL == this->escape_chars);
+	assert(!this->escape_chars);
 	this->escape_chars = lub_string_dup(escape_chars);
 }
 
@@ -313,6 +315,20 @@ const char *clish_command__get_escape_chars(const clish_command_t * this)
 	return this->escape_chars;
 }
 
+/*--------------------------------------------------------- */
+void clish_command__set_regex_chars(clish_command_t *this,
+	const char *escape_chars)
+{
+	assert(!this->regex_chars);
+	this->regex_chars = lub_string_dup(escape_chars);
+}
+
+/*--------------------------------------------------------- */
+const char *clish_command__get_regex_chars(const clish_command_t *this)
+{
+	return this->regex_chars;
+}
+
 /*--------------------------------------------------------- */
 void clish_command__set_args(clish_command_t * this, clish_param_t * args)
 {

+ 1 - 0
clish/command/private.h

@@ -18,6 +18,7 @@ struct clish_command_s {
 	char *viewid;
 	char *detail;
 	char *escape_chars;
+	char *regex_chars;
 	clish_param_t *args;
 	const struct clish_command_s *link;
 	clish_view_t *alias_view;

+ 1 - 1
clish/ptype/ptype.c

@@ -283,7 +283,7 @@ static char *clish_ptype_validate_or_translate(const clish_ptype_t * this,
 		/* test the regular expression against the string */
 		/*lint -e64 Type mismatch (arg. no. 4) */
 		/*
-		 * lint seems to equate regmatch_t[] as being of type regmatch_t !!!
+		 * lint seems to equate regmatch_t[] as being of type regmatch_t !
 		 */
 		if (0 != regexec(&this->u.regexp, result, 0, NULL, 0)) {
 			lub_string_free(result);

+ 8 - 2
clish/shell.h

@@ -48,6 +48,12 @@ typedef enum {
 	SHELL_STATE_CLOSING
 } clish_shell_state_t;
 
+typedef enum {
+	SHELL_VAR_NONE, /* Nothing to escape */
+	SHELL_VAR_ACTION, /* Variable expanding for ACTION script */
+	SHELL_VAR_REGEX /* Variable expanding for regex usage */
+} clish_shell_var_t;
+
 _BEGIN_C_DECL
 
 /*=====================================
@@ -331,8 +337,8 @@ bool_t clish_shell_push_fd(clish_shell_t * instance, FILE * file,
 	bool_t stop_on_error);
 void clish_shell_insert_var(clish_shell_t *instance, clish_var_t *var);
 clish_var_t *clish_shell_find_var(clish_shell_t *instance, const char *name);
-char *clish_shell_expand_var(const char *name, void *context);
-char *clish_shell_expand(const char *str, void *context);
+char *clish_shell_expand_var(const char *name, clish_shell_var_t vtype, void *context);
+char *clish_shell_expand(const char *str, clish_shell_var_t vtype, void *context);
 
 /*-----------------
  * attributes

+ 1 - 1
clish/shell/shell_command.c

@@ -125,7 +125,7 @@ void clish_shell_param_generator(clish_shell_t *this, lub_argv_t *matches,
 				char *str, *q;
 				char *saveptr;
 				str = clish_shell_expand(
-					clish_param__get_completion(param), &context);
+					clish_param__get_completion(param), SHELL_VAR_ACTION, &context);
 				for (q = strtok_r(str, " \n", &saveptr);
 					q; q = strtok_r(NULL, " \n", &saveptr)) {
 					if (q == strstr(q, text))

+ 4 - 4
clish/shell/shell_execute.c

@@ -284,7 +284,7 @@ bool_t clish_shell_execute(clish_context_t *context, char **out)
 	}
 
 	/* Call config callback */
-	if ((BOOL_TRUE == result) && this->client_hooks->config_fn)
+	if (result && this->client_hooks->config_fn)
 		this->client_hooks->config_fn(context);
 
 	/* Unlock the lockfile */
@@ -294,10 +294,10 @@ bool_t clish_shell_execute(clish_context_t *context, char **out)
 	}
 
 	/* Move into the new view */
-	if (BOOL_TRUE == result) {
+	if (result) {
 		clish_view_t *view = clish_command__get_view(cmd);
 		char *viewid = clish_shell_expand(
-			clish_command__get_viewid(cmd), context);
+			clish_command__get_viewid(cmd), SHELL_VAR_ACTION, context);
 		if (view) {
 			/* Save the current config PWD */
 			char *line = clish_shell__get_line(cmd, pargv);
@@ -328,7 +328,7 @@ bool_t clish_shell_exec_action(clish_action_t *action,
 	char *script;
 
 	builtin = clish_action__get_builtin(action);
-	script = clish_shell_expand(clish_action__get_script(action), context);
+	script = clish_shell_expand(clish_action__get_script(action), SHELL_VAR_ACTION, context);
 	if (builtin) {
 		clish_shell_builtin_fn_t *callback;
 		lub_argv_t *argv = script ? lub_argv_new(script, 0) : NULL;

+ 1 - 1
clish/shell/shell_parse.c

@@ -104,7 +104,7 @@ clish_pargv_status_t clish_shell_parse_pargv(clish_pargv_t *pargv,
 
 		/* Check the 'test' conditions */
 		if (param) {
-			char *str = clish_shell_expand(clish_param__get_test(param), context);
+			char *str = clish_shell_expand(clish_param__get_test(param), SHELL_VAR_ACTION, context);
 			if (str && !lub_system_line_test(str)) {
 				lub_string_free(str);
 				index++;

+ 3 - 3
clish/shell/shell_tinyrl.c

@@ -28,7 +28,7 @@ static void clish_shell_renew_prompt(tinyrl_t *this)
 	/* Obtain the prompt */
 	view = clish_shell__get_view(context->shell);
 	assert(view);
-	prompt = clish_shell_expand(clish_view__get_prompt(view), context);
+	prompt = clish_shell_expand(clish_view__get_prompt(view), SHELL_VAR_ACTION, context);
 	assert(prompt);
 	tinyrl__set_prompt(this, prompt);
 	lub_string_free(prompt);
@@ -118,7 +118,7 @@ static tinyrl_match_e clish_shell_tinyrl_complete(tinyrl_t * this)
 	switch (status) {
 	case TINYRL_NO_MATCH:
 		if (BOOL_FALSE == tinyrl_is_completion_error_over(this)) {
-			/* The user hasn't even entered a valid prefix!!! */
+			/* The user hasn't even entered a valid prefix! */
 /*			tinyrl_crlf(this);
 			clish_shell_help(context->shell,
 				tinyrl__get_line(this));
@@ -409,7 +409,7 @@ bool_t clish_shell_execline(clish_shell_t *this, const char *line, char **out)
 	/* Obtain the prompt */
 	view = clish_shell__get_view(this);
 	assert(view);
-	prompt = clish_shell_expand(clish_view__get_prompt(view), &context);
+	prompt = clish_shell_expand(clish_view__get_prompt(view), SHELL_VAR_ACTION, &context);
 	assert(prompt);
 
 	/* Push the specified line or interactive line */

+ 22 - 12
clish/shell/shell_var.c

@@ -52,7 +52,7 @@ static char *find_viewid_var(const char *name, const char *viewid)
 	/* now perform the matching */
 	/*lint -e64 Type mismatch (arg. no. 4) */
 	/*
-	 * lint seems to equate regmatch_t[] as being of type regmatch_t !!!
+	 * lint seems to equate regmatch_t[] as being of type regmatch_t !
 	 */
 	status = regexec(&regex, viewid, 2, pmatches, 0);
 	/*lint +e64 */
@@ -111,7 +111,7 @@ static char *find_context_var(const char *name, clish_context_t *this)
 }
 
 /*--------------------------------------------------------- */
-static char *find_global_var(const char *name, clish_context_t *context)
+static char *find_global_var(const char *name, clish_shell_var_t vtype, clish_context_t *context)
 {
 	clish_shell_t *this = context->shell;
 	clish_var_t *var = clish_shell_find_var(this, name);
@@ -135,7 +135,7 @@ static char *find_global_var(const char *name, clish_context_t *context)
 	/* Try to expand value field */
 	value = clish_var__get_value(var);
 	if (value)
-		res = clish_shell_expand(value, context);
+		res = clish_shell_expand(value, vtype, context);
 
 	/* Try to execute ACTION */
 	if (!res) {
@@ -163,7 +163,7 @@ static char *find_global_var(const char *name, clish_context_t *context)
  * return the next segment of text from the provided string
  * segments are delimited by variables within the string.
  */
-static char *expand_nextsegment(const char **string, clish_context_t *this)
+static char *expand_nextsegment(const char **string, clish_shell_var_t vtype, clish_context_t *this)
 {
 	const char *p = *string;
 	char *result = NULL;
@@ -199,7 +199,7 @@ static char *expand_nextsegment(const char **string, clish_context_t *this)
 				 */
 				for (q = strtok_r(text, ":", &saveptr);
 					q; q = strtok_r(NULL, ":", &saveptr)) {
-					char *var = clish_shell_expand_var(q, this);
+					char *var = clish_shell_expand_var(q, vtype, this);
 
 					/* copy the expansion or the raw word */
 					lub_string_cat(&result, var ? var : q);
@@ -242,12 +242,12 @@ static char *expand_nextsegment(const char **string, clish_context_t *this)
  * subtituting each occurance of a "${FRED}" type variable sub-string
  * with the appropriate value.
  */
-char *clish_shell_expand(const char *str, void *context)
+char *clish_shell_expand(const char *str, clish_shell_var_t vtype, void *context)
 {
 	char *seg, *result = NULL;
 
 	/* read each segment and extend the result */
-	while ((seg = expand_nextsegment(&str, context))) {
+	while ((seg = expand_nextsegment(&str, vtype, context))) {
 		lub_string_cat(&result, seg);
 		lub_string_free(seg);
 	}
@@ -311,7 +311,7 @@ char *clish_shell__get_line(const clish_command_t *cmd, clish_pargv_t *pargv)
 }
 
 /*--------------------------------------------------------- */
-char *clish_shell_expand_var(const char *name, void *context)
+char *clish_shell_expand_var(const char *name, clish_shell_var_t vtype, void *context)
 {
 	clish_context_t *con = (clish_context_t *)context;
 	clish_shell_t *this;
@@ -348,18 +348,28 @@ char *clish_shell_expand_var(const char *name, void *context)
 		tmp = string = find_context_var(name, context);
 	/* try and substitute a global var value */
 	if (!tmp && this)
-		tmp = string = find_global_var(name, context);
+		tmp = string = find_global_var(name, vtype, context);
 	/* get the contents of an environment variable */
 	if (!tmp)
 		tmp = getenv(name);
 
-	/* override the escape characters */
+	/* Escape special characters */
+	if (SHELL_VAR_REGEX == vtype) {
+		char *tstr;
+		if (cmd)
+			escape_chars = clish_command__get_regex_chars(cmd);
+		if (!escape_chars)
+			escape_chars = lub_string_esc_regex;
+		tstr = lub_string_encode(tmp, escape_chars);
+		lub_string_free(string);
+		tmp = string = tstr;
+	}
+	escape_chars = NULL;
 	if (cmd)
 		escape_chars = clish_command__get_escape_chars(cmd);
 	result = lub_string_encode(tmp, escape_chars);
 	/* free the dynamic memory */
-	if (string)
-		lub_string_free(string);
+	lub_string_free(string);
 
 	return result;
 }

+ 11 - 0
lub/string.h

@@ -219,6 +219,17 @@ void lub_string_free(
          */
 			    char *string);
 
+/*
+ * These are the escape characters which are used by default when 
+ * expanding variables. These characters will be backslash escaped
+ * to prevent them from being interpreted in a script.
+ *
+ * This is a security feature to prevent users from arbitarily setting
+ * parameters to contain special sequences.
+ */
+extern const char *lub_string_esc_default;
+extern const char *lub_string_esc_regex;
+
 /**
  * This operation decode the escaped string.
  *

+ 5 - 12
lub/string/string_escape.c

@@ -6,15 +6,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-/*
- * These are the escape characters which are used by default when 
- * expanding variables. These characters will be backslash escaped
- * to prevent them from being interpreted in a script.
- *
- * This is a security feature to prevent users from arbitarily setting
- * parameters to contain special sequences.
- */
-static const char *default_escape_chars = "`|$<>&()#;";
+const char *lub_string_esc_default = "`|$<>&()#;\\\"";
+const char *lub_string_esc_regex = "^$.*+[](){}";
 
 /*--------------------------------------------------------- */
 char *lub_string_ndecode(const char *string, unsigned int len)
@@ -75,9 +68,9 @@ char *lub_string_encode(const char *string, const char *escape_chars)
 	char *result = NULL;
 	const char *p;
 
-	if (NULL == escape_chars) {
-		escape_chars = default_escape_chars;
-	}
+	if (!escape_chars)
+		escape_chars = lub_string_esc_default;
+
 	for (p = string; p && *p; p++) {
 		/* find any special characters and prefix them with '\' */
 		size_t len = strcspn(p, escape_chars);