/*
* Copyright (c) 2009-2016 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Variable-related routines.
*/
#include "cgi.h"
#include
#include
#include
#include
#include
#include
#include
#include
/* Set a variable (format string). */
VAR *
VAR_Set(const char *key, const char *fmt, ...)
{
VAR *var;
if (key != NULL) {
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
} else {
var = NULL;
}
if (var == NULL) {
var = Malloc(sizeof(VAR));
if (key != NULL) {
CGI_Strlcpy(var->key, key, sizeof(var->key));
} else {
var->key[0] = '\0';
}
TAILQ_INSERT_HEAD(&cgi->vars, var, vars);
} else {
free(var->value);
}
if (fmt != NULL) {
va_list ap;
va_start(ap, fmt);
if (vasprintf(&var->value, fmt, ap) == -1) {
CGI_OutOfMem();
}
va_end(ap);
var->len = strlen(var->value);
var->bufSize = var->len+1;
} else {
var->value = Malloc(VAR_BUF_INIT);
var->value[0] = '\0';
var->len = 0;
var->bufSize = VAR_BUF_INIT;
}
var->global = 0;
return (var);
}
/* Set a variable (plain string). */
VAR *
VAR_SetS(const char *key, const char *s)
{
VAR *var;
if (key != NULL) {
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
} else {
var = NULL;
}
if (var == NULL) {
var = Malloc(sizeof(VAR));
if (key != NULL) {
CGI_Strlcpy(var->key, key, sizeof(var->key));
} else {
var->key[0] = '\0';
}
TAILQ_INSERT_HEAD(&cgi->vars, var, vars);
} else {
free(var->value);
}
if (s != NULL) {
var->value = Strdup(s);
var->len = strlen(s);
var->bufSize = var->len+1;
} else {
var->value = Malloc(VAR_BUF_INIT);
var->value[0] = '\0';
var->len = 0;
var->bufSize = VAR_BUF_INIT;
}
var->global = 0;
return (var);
}
/* Set a variable (plain string, use existing buffer). */
VAR *
VAR_SetS_NODUP(const char *key, char *s)
{
VAR *var;
if (key != NULL) {
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
} else {
var = NULL;
}
if (var == NULL) {
var = Malloc(sizeof(VAR));
if (key != NULL) {
CGI_Strlcpy(var->key, key, sizeof(var->key));
} else {
var->key[0] = '\0';
}
TAILQ_INSERT_HEAD(&cgi->vars, var, vars);
} else {
free(var->value);
}
var->value = s;
var->len = strlen(s);
var->bufSize = var->len+1;
var->global = 0;
return (var);
}
/* Append to an existing variable. */
void
VAR_Cat(VAR *var, const char *fmt, ...)
{
char *s;
size_t len;
va_list ap;
va_start(ap, fmt);
if (vasprintf(&s, fmt, ap) == -1) {
CGI_OutOfMem();
}
va_end(ap);
len = strlen(s);
VAR_Grow(var, len+1);
memcpy(&var->value[var->len], s, len+1);
var->len += len;
free(s);
}
/* Set a global variable (format string). */
VAR *
VAR_SetGlobal(const char *key, const char *fmt, ...)
{
VAR *var;
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
if (var == NULL) {
var = Malloc(sizeof(VAR));
CGI_Strlcpy(var->key, key, sizeof(var->key));
TAILQ_INSERT_HEAD(&cgi->vars, var, vars);
} else {
free(var->value);
}
if (fmt != NULL) {
va_list ap;
va_start(ap, fmt);
if (vasprintf(&var->value, fmt, ap) == -1) {
CGI_OutOfMem();
}
va_end(ap);
var->len = strlen(var->value);
var->bufSize = var->len+1;
} else {
var->value = Malloc(VAR_BUF_INIT);
var->value[0] = '\0';
var->len = 0;
var->bufSize = VAR_BUF_INIT;
}
var->global = 1;
return (var);
}
/* Set a global variable (plain string). */
VAR *
VAR_SetGlobalS(const char *key, const char *s)
{
VAR *var;
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
if (var == NULL) {
var = Malloc(sizeof(VAR));
CGI_Strlcpy(var->key, key, sizeof(var->key));
TAILQ_INSERT_HEAD(&cgi->vars, var, vars);
} else {
free(var->value);
}
if (s != NULL) {
var->value = Strdup(s);
var->len = strlen(var->value);
var->bufSize = var->len+1;
} else {
var->value = Malloc(VAR_BUF_INIT);
var->value[0] = '\0';
var->len = 0;
var->bufSize = VAR_BUF_INIT;
}
var->global = 1;
return (var);
}
void
VAR_Unset(const char *key)
{
VAR *var;
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
if (var != NULL) {
TAILQ_REMOVE(&cgi->vars, var, vars);
VAR_Free(var);
}
}
void
VAR_Wipe(const char *key)
{
VAR *var;
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
break;
}
if (var != NULL)
memset(var->value, 0, var->bufSize);
}
int
VAR_Defined(const char *key)
{
VAR *var;
TAILQ_FOREACH(var, &cgi->vars, vars) {
if (strcmp(var->key, key) == 0)
return (1);
}
return (0);
}
void
VAR_Free(VAR *v)
{
TAILQ_REMOVE(&cgi->vars, v, vars);
Free(v->value);
Free(v);
}