From a4e9deec494b308387b3f29b8ee8fc2aa934d4c2 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Wed, 23 Jun 2010 17:54:48 +0200 Subject: [PATCH] src/utils_cgi.[ch]: Basically a rewrite of the parameter handling functions. --- src/utils_cgi.c | 448 +++++++++++++++++++++++++++++++++++++++----------------- src/utils_cgi.h | 18 ++- 2 files changed, 334 insertions(+), 132 deletions(-) diff --git a/src/utils_cgi.c b/src/utils_cgi.c index 97dfc7c..b96e15a 100644 --- a/src/utils_cgi.c +++ b/src/utils_cgi.c @@ -4,8 +4,10 @@ #include #include #include +#include #include "utils_cgi.h" +#include "common.h" #include #include @@ -17,87 +19,45 @@ struct parameter_s }; typedef struct parameter_s parameter_t; -static parameter_t *parameters = NULL; -static size_t parameters_num = 0; -static _Bool parameters_init = 0; - -static int parameter_add (const char *key, const char *value) /* {{{ */ +struct param_list_s { - parameter_t *ptr; - - if (value == NULL) - return (EINVAL); - - ptr = realloc (parameters, sizeof (*parameters) * (parameters_num + 1)); - if (ptr == NULL) - return (ENOMEM); - parameters = ptr; - - ptr = parameters + parameters_num; - if (key == NULL) - { - ptr->key = NULL; - } - else - { - ptr->key = strdup (key); - if (ptr->key == NULL) - return (ENOMEM); - } - - ptr->value = strdup (value); - if (ptr->value == NULL) - { - free (ptr->key); - return (ENOMEM); - } - - parameters_num++; - return (0); -} /* }}} int parameter_add */ - -static char *parameter_lookup (const char *key) /* {{{ */ -{ - size_t i; - - for (i = 0; i < parameters_num; i++) - { - if ((key == NULL) && (parameters[i].key == NULL)) - return (parameters[i].value); - else if ((key != NULL) && (parameters[i].key != NULL) - && (strcmp (key, parameters[i].key) == 0)) - return (parameters[i].value); - } + parameter_t *parameters; + size_t parameters_num; +}; - return (NULL); -} /* }}} char *parameter_lookup */ +static param_list_t *pl_global = NULL; -static char *uri_unescape (char *string) /* {{{ */ +static char *uri_unescape_copy (char *dest, const char *src, size_t n) /* {{{ */ { - char *in; - char *out; + const char *src_ptr; + char *dest_ptr; - if (string == NULL) + if ((dest == NULL) || (src == NULL) || (n < 1)) return (NULL); - in = string; - out = string; + src_ptr = src; + dest_ptr = dest; + + *dest_ptr = 0; - while (*in != 0) + while (*src_ptr != 0) { - if (*in == '+') + if (n < 2) + break; + + if (*src_ptr == '+') { - *out = ' '; + *dest_ptr = ' '; } - else if ((in[0] == '%') - && isxdigit ((int) in[1]) && isxdigit ((int) in[2])) + else if ((src_ptr[0] == '%') + && isxdigit ((int) src_ptr[1]) && isxdigit ((int) src_ptr[2])) { char tmpstr[3]; char *endptr; long value; - tmpstr[0] = in[1]; - tmpstr[1] = in[2]; + tmpstr[0] = src_ptr[1]; + tmpstr[1] = src_ptr[2]; tmpstr[2] = 0; errno = 0; @@ -105,64 +65,88 @@ static char *uri_unescape (char *string) /* {{{ */ value = strtol (tmpstr, &endptr, /* base = */ 16); if ((endptr == tmpstr) || (errno != 0)) { - *out = '?'; + *dest_ptr = '?'; } else { - *out = (char) value; + *dest_ptr = (char) value; } - in += 2; + src_ptr += 2; } else { - *out = *in; + *dest_ptr = *src_ptr; } - in++; - out++; - } /* while (*in != 0) */ + src_ptr++; + dest_ptr++; + *dest_ptr = 0; + } /* while (*src_ptr != 0) */ + + assert (*dest_ptr == 0); + return (dest); +} /* }}} char *uri_unescape */ + +static char *uri_unescape (const char *string) /* {{{ */ +{ + char buffer[4096]; - *out = 0; - return (string); + if (string == NULL) + return (NULL); + + uri_unescape_copy (buffer, string, sizeof (buffer)); + + return (strdup (buffer)); } /* }}} char *uri_unescape */ -static int parse_keyval (char *keyval) /* {{{ */ +static int param_parse_keyval (param_list_t *pl, char *keyval) /* {{{ */ { + char *key_raw; + char *value_raw; char *key; - char *val; + char *value; - val = strchr (keyval, '='); - if (val == NULL) - { - key = NULL; - val = keyval; - } - else + key_raw = keyval; + value_raw = strchr (key_raw, '='); + if (value_raw == NULL) + return (EINVAL); + *value_raw = 0; + value_raw++; + + key = uri_unescape (key_raw); + if (key == NULL) + return (ENOMEM); + + value = uri_unescape (value_raw); + if (value == NULL) { - key = keyval; - *val = 0; - val++; + free (key); + return (ENOMEM); } + + param_set (pl, key, value); - parameter_add (uri_unescape (key), uri_unescape (val)); + free (key); + free (value); return (0); -} /* }}} int parse_keyval */ +} /* }}} int param_parse_keyval */ -static int parse_query_string (char *query_string) /* {{{ */ +static int parse_query_string (param_list_t *pl, /* {{{ */ + char *query_string) { char *dummy; char *keyval; - if (query_string == NULL) + if ((pl == NULL) || (query_string == NULL)) return (EINVAL); dummy = query_string; while ((keyval = strtok (dummy, ";&")) != NULL) { dummy = NULL; - parse_keyval (keyval); + param_parse_keyval (pl, keyval); } return (0); @@ -170,56 +154,244 @@ static int parse_query_string (char *query_string) /* {{{ */ int param_init (void) /* {{{ */ { - const char *query_string; - char *copy; - int status; - - if (parameters_init) + if (pl_global != NULL) return (0); - query_string = getenv ("QUERY_STRING"); + pl_global = param_create (/* query string = */ NULL); + if (pl_global == NULL) + return (ENOMEM); + + return (0); +} /* }}} int param_init */ + +void param_finish (void) /* {{{ */ +{ + param_destroy (pl_global); + pl_global = NULL; +} /* }}} void param_finish */ + +const char *param (const char *key) /* {{{ */ +{ + param_init (); + + return (param_get (pl_global, key)); +} /* }}} const char *param */ + +param_list_t *param_create (const char *query_string) /* {{{ */ +{ + char *tmp; + param_list_t *pl; + if (query_string == NULL) - return (ENOENT); + query_string = getenv ("QUERY_STRING"); - copy = strdup (query_string); - if (copy == NULL) - return (ENOMEM); + if (query_string == NULL) + return (NULL); + + tmp = strdup (query_string); + if (tmp == NULL) + return (NULL); + + pl = malloc (sizeof (*pl)); + if (pl == NULL) + { + free (tmp); + return (NULL); + } + memset (pl, 0, sizeof (*pl)); - status = parse_query_string (copy); - free (copy); + parse_query_string (pl, tmp); - parameters_init = 1; + free (tmp); + return (pl); +} /* }}} param_list_t *param_create */ - return (status); -} /* }}} int param_init */ + param_list_t *param_clone (__attribute__((unused)) param_list_t *pl) /* {{{ */ +{ + /* FIXME: To be implemented. */ + assert (23 == 42); + return (NULL); +} /* }}} param_list_t *param_clone */ -void param_finish (void) /* {{{ */ +void param_destroy (param_list_t *pl) /* {{{ */ { size_t i; - if (!parameters_init) + if (pl == NULL) return; - for (i = 0; i < parameters_num; i++) + for (i = 0; i < pl->parameters_num; i++) { - free (parameters[i].key); - free (parameters[i].value); + free (pl->parameters[i].key); + free (pl->parameters[i].value); } - free (parameters); + free (pl->parameters); + free (pl); +} /* }}} void param_destroy */ - parameters = NULL; - parameters_num = 0; - parameters_init = 0; -} /* }}} void param_finish */ +const char *param_get (param_list_t *pl, const char *name) /* {{{ */ +{ + size_t i; -const char *param (const char *key) /* {{{ */ + if ((pl == NULL) || (name == NULL)) + return (NULL); + + for (i = 0; i < pl->parameters_num; i++) + { + if ((name == NULL) && (pl->parameters[i].key == NULL)) + return (pl->parameters[i].value); + else if ((name != NULL) && (pl->parameters[i].key != NULL) + && (strcmp (name, pl->parameters[i].key) == 0)) + return (pl->parameters[i].value); + } + + return (NULL); +} /* }}} char *param_get */ + +static int param_add (param_list_t *pl, /* {{{ */ + const char *key, const char *value) { - param_init (); + parameter_t *tmp; - return (parameter_lookup (key)); -} /* }}} const char *param */ + tmp = realloc (pl->parameters, + sizeof (*pl->parameters) * (pl->parameters_num + 1)); + if (tmp == NULL) + return (ENOMEM); + pl->parameters = tmp; + tmp = pl->parameters + pl->parameters_num; + + memset (tmp, 0, sizeof (*tmp)); + tmp->key = strdup (key); + if (tmp->key == NULL) + return (ENOMEM); + + tmp->value = strdup (value); + if (tmp->value == NULL) + { + free (tmp->key); + return (ENOMEM); + } + + pl->parameters_num++; + + return (0); +} /* }}} int param_add */ + +static int param_delete (param_list_t *pl, /* {{{ */ + const char *name) +{ + size_t i; + + if ((pl == NULL) || (name == NULL)) + return (EINVAL); + + for (i = 0; i < pl->parameters_num; i++) + if (strcasecmp (pl->parameters[i].key, name) == 0) + break; + + if (i >= pl->parameters_num) + return (ENOENT); + + if (i < (pl->parameters_num - 1)) + { + parameter_t p; + + p = pl->parameters[i]; + pl->parameters[i] = pl->parameters[pl->parameters_num - 1]; + pl->parameters[pl->parameters_num - 1] = p; + } + + pl->parameters_num--; + free (pl->parameters[pl->parameters_num].key); + free (pl->parameters[pl->parameters_num].value); + + return (0); +} /* }}} int param_delete */ + +int param_set (param_list_t *pl, const char *name, /* {{{ */ + const char *value) +{ + parameter_t *p; + char *value_copy; + size_t i; + + if ((pl == NULL) || (name == NULL)) + return (EINVAL); + + if (value == NULL) + return (param_delete (pl, name)); + + p = NULL; + for (i = 0; i < pl->parameters_num; i++) + { + if (strcasecmp (pl->parameters[i].key, name) == 0) + { + p = pl->parameters + i; + break; + } + } + + if (p == NULL) + return (param_add (pl, name, value)); + + value_copy = strdup (value); + if (value_copy == NULL) + return (ENOMEM); + + free (p->value); + p->value = value_copy; + + return (0); +} /* }}} int param_set */ + +const char *param_as_string (param_list_t *pl) /* {{{ */ +{ + char buffer[4096]; + char key[2048]; + char value[2048]; + size_t i; + + if (pl == NULL) + return (NULL); + + buffer[0] = 0; + for (i = 0; i < pl->parameters_num; i++) + { + uri_escape_copy (key, pl->parameters[i].key, sizeof (key)); + uri_escape_copy (value, pl->parameters[i].value, sizeof (value)); + + if (i != 0) + strlcat (buffer, ";", sizeof (buffer)); + strlcat (buffer, key, sizeof (buffer)); + strlcat (buffer, "=", sizeof (buffer)); + strlcat (buffer, value, sizeof (buffer)); + } + + return (strdup (buffer)); +} /* }}} char *param_as_string */ -int uri_escape (char *dst, const char *src, size_t size) /* {{{ */ +int param_print_hidden (param_list_t *pl) /* {{{ */ +{ + char key[2048]; + char value[2048]; + size_t i; + + if (pl == NULL) + return (EINVAL); + + for (i = 0; i < pl->parameters_num; i++) + { + html_escape_copy (key, pl->parameters[i].key, sizeof (key)); + html_escape_copy (value, pl->parameters[i].value, sizeof (value)); + + printf (" \n", + key, value); + } + + return (0); +} /* }}} int param_print_hidden */ + +char *uri_escape_copy (char *dest, const char *src, size_t n) /* {{{ */ { size_t in; size_t out; @@ -230,37 +402,51 @@ int uri_escape (char *dst, const char *src, size_t size) /* {{{ */ { if (src[in] == 0) { - dst[out] = 0; - return (0); + dest[out] = 0; + return (dest); } - else if ((src[in] < 32) + else if ((((unsigned char) src[in]) < 32) || (src[in] == '&') || (src[in] == ';') + || (src[in] == '?') + || (src[in] == '/') || (((unsigned char) src[in]) >= 128)) { char esc[4]; - if ((size - out) < 4) + if ((n - out) < 4) break; snprintf (esc, sizeof (esc), "%%%02x", (unsigned int) src[in]); - dst[out] = esc[0]; - dst[out+1] = esc[1]; - dst[out+2] = esc[2]; + dest[out] = esc[0]; + dest[out+1] = esc[1]; + dest[out+2] = esc[2]; out += 3; in++; } else { - dst[out] = src[in]; + dest[out] = src[in]; out++; in++; } } /* while (42) */ - return (0); -} /* }}} int uri_escape */ + return (dest); +} /* }}} char *uri_escape_copy */ + +char *uri_escape (const char *string) /* {{{ */ +{ + char buffer[4096]; + + if (string == NULL) + return (NULL); + + uri_escape_copy (buffer, string, sizeof (buffer)); + + return (strdup (buffer)); +} /* }}} char *uri_escape */ const char *script_name (void) /* {{{ */ { diff --git a/src/utils_cgi.h b/src/utils_cgi.h index e8e847e..973d3f3 100644 --- a/src/utils_cgi.h +++ b/src/utils_cgi.h @@ -19,6 +19,9 @@ struct page_callbacks_s }; typedef struct page_callbacks_s page_callbacks_t; +struct param_list_s; +typedef struct param_list_s param_list_t; + #define PAGE_CALLBACKS_INIT \ { NULL, NULL, NULL, \ NULL, NULL, NULL, \ @@ -29,7 +32,20 @@ void param_finish (void); const char *param (const char *key); -int uri_escape (char *dst, const char *src, size_t size); +/* Create a new parameter list from "query_string". If "query_string" is NULL, + * the "QUERY_STRING" will be used. */ +param_list_t *param_create (const char *query_string); +param_list_t *param_clone (param_list_t *pl); +void param_destroy (param_list_t *pl); +const char *param_get (param_list_t *pl, const char *name); +int param_set (param_list_t *pl, + const char *name, const char *value); +const char *param_as_string (param_list_t *pl); +int param_print_hidden (param_list_t *pl); + +char *uri_escape (const char *string); +char *uri_escape_buffer (char *buffer, size_t buffer_size); +char *uri_escape_copy (char *dest, const char *src, size_t n); const char *script_name (void); -- 2.11.0