/* * 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); }