You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1276 lines
26 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* CGI form variable and array functions for CUPS.
*
* Copyright © 2007-2019 by Apple Inc.
* Copyright © 1997-2005 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
*/
/*
* Include necessary headers...
*/
/*#define DEBUG*/
#include "cgi-private.h"
#include <cups/http.h>
/*
* Session ID name
*/
#define CUPS_SID "org.cups.sid"
/*
* Data structure to hold all the CGI form variables and arrays...
*/
typedef struct /**** Form variable structure ****/
{
char *name; /* Name of variable */
int nvalues, /* Number of values */
avalues; /* Number of values allocated */
char **values; /* Value(s) of variable */
} _cgi_var_t;
/*
* Local globals...
*/
static int num_cookies = 0;/* Number of cookies */
static cups_option_t *cookies = NULL;/* Cookies */
static int form_count = 0, /* Form variable count */
form_alloc = 0; /* Number of variables allocated */
static _cgi_var_t *form_vars = NULL;
/* Form variables */
static cgi_file_t *form_file = NULL;
/* Uploaded file */
/*
* Local functions...
*/
static void cgi_add_variable(const char *name, int element,
const char *value);
static int cgi_compare_variables(const _cgi_var_t *v1,
const _cgi_var_t *v2);
static _cgi_var_t *cgi_find_variable(const char *name);
static void cgi_initialize_cookies(void);
static int cgi_initialize_get(void);
static int cgi_initialize_multipart(const char *boundary);
static int cgi_initialize_post(void);
static int cgi_initialize_string(const char *data);
static const char *cgi_passwd(const char *prompt);
static const char *cgi_set_sid(void);
static void cgi_sort_variables(void);
static void cgi_unlink_file(void);
/*
* 'cgiCheckVariables()' - Check for the presence of "required" variables.
*
* Names may be separated by spaces and/or commas.
*/
int /* O - 1 if all variables present, 0 otherwise */
cgiCheckVariables(const char *names) /* I - Variables to look for */
{
char name[255], /* Current variable name */
*s; /* Pointer in string */
const char *val; /* Value of variable */
int element; /* Array element number */
if (names == NULL)
return (1);
while (*names != '\0')
{
while (*names == ' ' || *names == ',')
names ++;
for (s = name; *names != '\0' && *names != ' ' && *names != ','; s ++, names ++)
*s = *names;
*s = 0;
if (name[0] == '\0')
break;
if ((s = strrchr(name, '-')) != NULL)
{
*s = '\0';
element = atoi(s + 1) - 1;
val = cgiGetArray(name, element);
}
else
val = cgiGetVariable(name);
if (val == NULL)
return (0);
if (*val == '\0')
{
free((void *)val);
return (0); /* Can't be blank, either! */
}
free((void *)val);
}
return (1);
}
/*
* 'cgiClearVariables()' - Clear all form variables.
*/
void
cgiClearVariables(void)
{
int i, j; /* Looping vars */
_cgi_var_t *v; /* Current variable */
fputs("DEBUG: cgiClearVariables called.\n", stderr);
for (v = form_vars, i = form_count; i > 0; v ++, i --)
{
free(v->name);
for (j = 0; j < v->nvalues; j ++)
if (v->values[j])
free(v->values[j]);
}
form_count = 0;
cgi_unlink_file();
}
/*
* 'cgiGetArray()' - Get an element from a form array.
*/
char * /* O - Element value or NULL */
cgiGetArray(const char *name, /* I - Name of array variable */
int element) /* I - Element number (0 to N) */
{
_cgi_var_t *var; /* Pointer to variable */
if ((var = cgi_find_variable(name)) == NULL)
return (NULL);
if (element < 0 || element >= var->nvalues)
return (NULL);
if (var->values[element] == NULL)
return (NULL);
return (strdup(var->values[element]));
}
/*
* 'cgiGetCookie()' - Get a cookie value.
*/
const char * /* O - Value or NULL */
cgiGetCookie(const char *name) /* I - Name of cookie */
{
return (cupsGetOption(name, num_cookies, cookies));
}
/*
* 'cgiGetFile()' - Get the file (if any) that was submitted in the form.
*/
const cgi_file_t * /* O - Attached file or NULL */
cgiGetFile(void)
{
return (form_file);
}
/*
* 'cgiGetSize()' - Get the size of a form array value.
*/
int /* O - Number of elements */
cgiGetSize(const char *name) /* I - Name of variable */
{
_cgi_var_t *var; /* Pointer to variable */
if ((var = cgi_find_variable(name)) == NULL)
return (0);
return (var->nvalues);
}
/*
* 'cgiGetVariable()' - Get a CGI variable from the database.
*
* Returns NULL if the variable doesn't exist. If the variable is an
* array of values, returns the last element.
*/
char * /* O - Value of variable */
cgiGetVariable(const char *name) /* I - Name of variable */
{
const _cgi_var_t *var; /* Returned variable */
var = cgi_find_variable(name);
return ((var == NULL) ? NULL : strdup(var->values[var->nvalues - 1]));
}
/*
* 'cgiInitialize()' - Initialize the CGI variable "database".
*/
int /* O - Non-zero if there was form data */
cgiInitialize(void)
{
const char *method, /* Form posting method */
*content_type, /* Content-Type of post data */
*cups_sid_cookie, /* SID cookie */
*cups_sid_form; /* SID form variable */
/*
* Setup a password callback for authentication...
*/
cupsSetPasswordCB(cgi_passwd);
/*
* Set the locale so that times, etc. are formatted properly...
*/
setlocale(LC_ALL, "");
#ifdef DEBUG
/*
* Disable output buffering to find bugs...
*/
setbuf(stdout, NULL);
#endif /* DEBUG */
/*
* Get cookies...
*/
cgi_initialize_cookies();
if ((cups_sid_cookie = cgiGetCookie(CUPS_SID)) == NULL)
{
fputs("DEBUG: " CUPS_SID " cookie not found, initializing!\n", stderr);
cups_sid_cookie = cgi_set_sid();
}
fprintf(stderr, "DEBUG: " CUPS_SID " cookie is \"%s\"\n", cups_sid_cookie);
/*
* Get the request method (GET or POST)...
*/
method = getenv("REQUEST_METHOD");
content_type = getenv("CONTENT_TYPE");
if (!method)
return (0);
/*
* Grab form data from the corresponding location...
*/
if (!_cups_strcasecmp(method, "GET"))
return (cgi_initialize_get());
else if (!_cups_strcasecmp(method, "POST") && content_type)
{
const char *boundary = strstr(content_type, "boundary=");
if (boundary)
boundary += 9;
if (content_type && !strncmp(content_type, "multipart/form-data; ", 21))
{
if (!cgi_initialize_multipart(boundary))
return (0);
}
else if (!cgi_initialize_post())
return (0);
if ((cups_sid_form = cgiGetVariable(CUPS_SID)) == NULL ||
strcmp(cups_sid_cookie, cups_sid_form))
{
if (cups_sid_form)
fprintf(stderr, "DEBUG: " CUPS_SID " form variable is \"%s\"\n",
cups_sid_form);
else
fputs("DEBUG: " CUPS_SID " form variable is not present.\n", stderr);
free((void *)cups_sid_form);
cgiClearVariables();
return (0);
}
else
{
free((void *)cups_sid_form);
return (1);
}
}
else
return (0);
}
/*
* 'cgiIsPOST()' - Determine whether this page was POSTed.
*/
int /* O - 1 if POST, 0 if GET */
cgiIsPOST(void)
{
const char *method; /* REQUEST_METHOD environment variable */
if ((method = getenv("REQUEST_METHOD")) == NULL)
return (0);
else
return (!strcmp(method, "POST"));
}
/*
* 'cgiSetArray()' - Set array element N to the specified string.
*
* If the variable array is smaller than (element + 1), the intervening
* elements are set to NULL.
*/
void
cgiSetArray(const char *name, /* I - Name of variable */
int element, /* I - Element number (0 to N) */
const char *value) /* I - Value of variable */
{
int i; /* Looping var */
_cgi_var_t *var; /* Returned variable */
if (name == NULL || value == NULL || element < 0 || element > 100000)
return;
fprintf(stderr, "DEBUG: cgiSetArray: %s[%d]=\"%s\"\n", name, element, value);
if ((var = cgi_find_variable(name)) == NULL)
{
cgi_add_variable(name, element, value);
cgi_sort_variables();
}
else
{
if (element >= var->avalues)
{
char **temp; /* Temporary pointer */
temp = (char **)realloc((void *)(var->values), sizeof(char *) * (size_t)(element + 16));
if (!temp)
return;
var->avalues = element + 16;
var->values = temp;
}
if (element >= var->nvalues)
{
for (i = var->nvalues; i < element; i ++)
var->values[i] = NULL;
var->nvalues = element + 1;
}
else if (var->values[element])
free((char *)var->values[element]);
var->values[element] = strdup(value);
}
}
/*
* 'cgiSetCookie()' - Set a cookie value.
*/
void
cgiSetCookie(const char *name, /* I - Name */
const char *value, /* I - Value */
const char *path, /* I - Path (typically "/") */
const char *domain, /* I - Domain name */
time_t expires, /* I - Expiration date (0 for session) */
int secure) /* I - Require SSL */
{
num_cookies = cupsAddOption(name, value, num_cookies, &cookies);
printf("Set-Cookie: %s=%s;", name, value);
if (path)
printf(" path=%s;", path);
if (domain)
printf(" domain=%s;", domain);
if (expires)
{
char date[256]; /* Date string */
printf(" expires=%s;", httpGetDateString2(expires, date, sizeof(date)));
}
if (secure)
puts(" httponly; secure;");
else
puts(" httponly;");
}
/*
* 'cgiSetSize()' - Set the array size.
*/
void
cgiSetSize(const char *name, /* I - Name of variable */
int size) /* I - Number of elements (0 to N) */
{
int i; /* Looping var */
_cgi_var_t *var; /* Returned variable */
if (name == NULL || size < 0 || size > 100000)
return;
if ((var = cgi_find_variable(name)) == NULL)
return;
if (size >= var->avalues)
{
char **temp; /* Temporary pointer */
temp = (char **)realloc((void *)(var->values), sizeof(char *) * (size_t)(size + 16));
if (!temp)
return;
var->avalues = size + 16;
var->values = temp;
}
if (size > var->nvalues)
{
for (i = var->nvalues; i < size; i ++)
var->values[i] = NULL;
}
else if (size < var->nvalues)
{
for (i = size; i < var->nvalues; i ++)
if (var->values[i])
free((void *)(var->values[i]));
}
var->nvalues = size;
}
/*
* 'cgiSetVariable()' - Set a CGI variable in the database.
*
* If the variable is an array, this truncates the array to a single element.
*/
void
cgiSetVariable(const char *name, /* I - Name of variable */
const char *value) /* I - Value of variable */
{
int i; /* Looping var */
_cgi_var_t *var; /* Returned variable */
if (name == NULL || value == NULL)
return;
fprintf(stderr, "cgiSetVariable: %s=\"%s\"\n", name, value);
if ((var = cgi_find_variable(name)) == NULL)
{
cgi_add_variable(name, 0, value);
cgi_sort_variables();
}
else
{
for (i = 0; i < var->nvalues; i ++)
if (var->values[i])
free((char *)var->values[i]);
var->values[0] = strdup(value);
var->nvalues = 1;
}
}
/*
* 'cgi_add_variable()' - Add a form variable.
*/
static void
cgi_add_variable(const char *name, /* I - Variable name */
int element, /* I - Array element number */
const char *value) /* I - Variable value */
{
_cgi_var_t *var; /* New variable */
if (name == NULL || value == NULL || element < 0 || element > 100000)
return;
if (form_count >= form_alloc)
{
_cgi_var_t *temp_vars; /* Temporary form pointer */
if (form_alloc == 0)
temp_vars = malloc(sizeof(_cgi_var_t) * 16);
else
temp_vars = realloc(form_vars, (size_t)(form_alloc + 16) * sizeof(_cgi_var_t));
if (!temp_vars)
return;
form_vars = temp_vars;
form_alloc += 16;
}
var = form_vars + form_count;
if ((var->values = calloc((size_t)element + 1, sizeof(char *))) == NULL)
return;
var->name = strdup(name);
var->nvalues = element + 1;
var->avalues = element + 1;
var->values[element] = strdup(value);
form_count ++;
}
/*
* 'cgi_compare_variables()' - Compare two variables.
*/
static int /* O - Result of comparison */
cgi_compare_variables(
const _cgi_var_t *v1, /* I - First variable */
const _cgi_var_t *v2) /* I - Second variable */
{
return (_cups_strcasecmp(v1->name, v2->name));
}
/*
* 'cgi_find_variable()' - Find a variable.
*/
static _cgi_var_t * /* O - Variable pointer or NULL */
cgi_find_variable(const char *name) /* I - Name of variable */
{
_cgi_var_t key; /* Search key */
if (form_count < 1 || name == NULL)
return (NULL);
key.name = (char *)name;
return ((_cgi_var_t *)bsearch(&key, form_vars, (size_t)form_count, sizeof(_cgi_var_t),
(int (*)(const void *, const void *))cgi_compare_variables));
}
/*
* 'cgi_initialize_cookies()' - Initialize cookies.
*/
static void
cgi_initialize_cookies(void)
{
const char *cookie; /* HTTP_COOKIE environment variable */
char name[128], /* Name string */
value[512], /* Value string */
*ptr; /* Pointer into name/value */
if ((cookie = getenv("HTTP_COOKIE")) == NULL)
return;
while (*cookie)
{
int skip = 0; /* Skip this cookie? */
/*
* Skip leading whitespace...
*/
while (isspace(*cookie & 255))
cookie ++;
if (!*cookie)
break;
/*
* Copy the name...
*/
for (ptr = name; *cookie && *cookie != '=';)
if (ptr < (name + sizeof(name) - 1))
{
*ptr++ = *cookie++;
}
else
{
skip = 1;
cookie ++;
}
if (*cookie != '=')
break;
*ptr = '\0';
cookie ++;
/*
* Then the value...
*/
if (*cookie == '\"')
{
for (cookie ++, ptr = value; *cookie && *cookie != '\"';)
if (ptr < (value + sizeof(value) - 1))
{
*ptr++ = *cookie++;
}
else
{
skip = 1;
cookie ++;
}
if (*cookie == '\"')
cookie ++;
else
skip = 1;
}
else
{
for (ptr = value; *cookie && *cookie != ';';)
if (ptr < (value + sizeof(value) - 1))
{
*ptr++ = *cookie++;
}
else
{
skip = 1;
cookie ++;
}
}
if (*cookie == ';')
cookie ++;
else if (*cookie)
skip = 1;
*ptr = '\0';
/*
* Then add the cookie to an array as long as the name doesn't start with
* "$"...
*/
if (name[0] != '$' && !skip)
num_cookies = cupsAddOption(name, value, num_cookies, &cookies);
}
}
/*
* 'cgi_initialize_get()' - Initialize form variables using the GET method.
*/
static int /* O - 1 if form data read */
cgi_initialize_get(void)
{
char *data; /* Pointer to form data string */
/*
* Check to see if there is anything for us to read...
*/
data = getenv("QUERY_STRING");
if (data == NULL || strlen(data) == 0)
return (0);
/*
* Parse it out and return...
*/
return (cgi_initialize_string(data));
}
/*
* 'cgi_initialize_multipart()' - Initialize variables and file using the POST
* method.
*
* TODO: Update to support files > 2GB.
*/
static int /* O - 1 if form data was read */
cgi_initialize_multipart(
const char *boundary) /* I - Boundary string */
{
char line[10240], /* MIME header line */
name[1024], /* Form variable name */
filename[1024], /* Form filename */
mimetype[1024], /* MIME media type */
bstring[256], /* Boundary string to look for */
*ptr, /* Pointer into name/filename */
*end; /* End of buffer */
int ch, /* Character from file */
fd; /* Temporary file descriptor */
size_t blen; /* Length of boundary string */
/*
* Read multipart form data until we run out...
*/
name[0] = '\0';
filename[0] = '\0';
mimetype[0] = '\0';
snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary);
blen = strlen(bstring);
while (fgets(line, sizeof(line), stdin))
{
if (!strcmp(line, "\r\n"))
{
/*
* End of headers, grab value...
*/
if (filename[0])
{
/*
* Read an embedded file...
*/
if (form_file)
{
/*
* Remove previous file...
*/
cgi_unlink_file();
}
/*
* Allocate memory for the new file...
*/
if ((form_file = calloc(1, sizeof(cgi_file_t))) == NULL)
return (0);
form_file->name = strdup(name);
form_file->filename = strdup(filename);
form_file->mimetype = strdup(mimetype);
fd = cupsTempFd(form_file->tempfile, sizeof(form_file->tempfile));
if (fd < 0)
return (0);
atexit(cgi_unlink_file);
/*
* Copy file data to the temp file...
*/
ptr = line;
while ((ch = getchar()) != EOF)
{
*ptr++ = (char)ch;
if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
{
ptr -= blen;
break;
}
if ((ptr - line - (int)blen) >= 8192)
{
/*
* Write out the first 8k of the buffer...
*/
write(fd, line, 8192);
memmove(line, line + 8192, (size_t)(ptr - line - 8192));
ptr -= 8192;
}
}
/*
* Write the rest of the data and close the temp file...
*/
if (ptr > line)
write(fd, line, (size_t)(ptr - line));
close(fd);
}
else
{
/*
* Just get a form variable; the current code only handles
* form values up to 10k in size...
*/
ptr = line;
end = line + sizeof(line) - 1;
while ((ch = getchar()) != EOF)
{
if (ptr < end)
*ptr++ = (char)ch;
if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen))
{
ptr -= blen;
break;
}
}
*ptr = '\0';
/*
* Set the form variable...
*/
if ((ptr = strrchr(name, '-')) != NULL && isdigit(ptr[1] & 255))
{
/*
* Set a specific index in the array...
*/
*ptr++ = '\0';
if (line[0])
cgiSetArray(name, atoi(ptr) - 1, line);
}
else if ((ptr = cgiGetVariable(name)) != NULL)
{
/*
* Add another element in the array...
*/
free(ptr);
cgiSetArray(name, cgiGetSize(name), line);
}
else
{
/*
* Just set the line...
*/
cgiSetVariable(name, line);
}
}
/*
* Read the rest of the current line...
*/
fgets(line, sizeof(line), stdin);
/*
* Clear the state vars...
*/
name[0] = '\0';
filename[0] = '\0';
mimetype[0] = '\0';
}
else if (!_cups_strncasecmp(line, "Content-Disposition:", 20))
{
if ((ptr = strstr(line + 20, " name=\"")) != NULL)
{
strlcpy(name, ptr + 7, sizeof(name));
if ((ptr = strchr(name, '\"')) != NULL)
*ptr = '\0';
}
if ((ptr = strstr(line + 20, " filename=\"")) != NULL)
{
strlcpy(filename, ptr + 11, sizeof(filename));
if ((ptr = strchr(filename, '\"')) != NULL)
*ptr = '\0';
}
}
else if (!_cups_strncasecmp(line, "Content-Type:", 13))
{
for (ptr = line + 13; isspace(*ptr & 255); ptr ++);
strlcpy(mimetype, ptr, sizeof(mimetype));
for (ptr = mimetype + strlen(mimetype) - 1;
ptr > mimetype && isspace(*ptr & 255);
*ptr-- = '\0');
}
}
/*
* Return 1 for "form data found"...
*/
return (1);
}
/*
* 'cgi_initialize_post()' - Initialize variables using the POST method.
*/
static int /* O - 1 if form data was read */
cgi_initialize_post(void)
{
char *content_length, /* Length of input data (string) */
*data; /* Pointer to form data string */
size_t length, /* Length of input data */
tbytes; /* Total number of bytes read */
ssize_t nbytes; /* Number of bytes read this read() */
int status; /* Return status */
/*
* Check to see if there is anything for us to read...
*/
content_length = getenv("CONTENT_LENGTH");
if (content_length == NULL || atoi(content_length) <= 0)
return (0);
/*
* Get the length of the input stream and allocate a buffer for it...
*/
length = (size_t)strtol(content_length, NULL, 10);
data = malloc(length + 1); // lgtm [cpp/uncontrolled-allocation-size]
if (data == NULL)
return (0);
/*
* Read the data into the buffer...
*/
for (tbytes = 0; tbytes < length; tbytes += (size_t)nbytes)
if ((nbytes = read(0, data + tbytes, (size_t)(length - tbytes))) < 0)
{
if (errno != EAGAIN)
{
free(data);
return (0);
}
else
nbytes = 0;
}
else if (nbytes == 0)
{
/*
* CUPS STR #3176: OpenBSD: Early end-of-file on POST data causes 100% CPU
*
* This should never happen, but does on OpenBSD. If we see early end-of-
* file, treat this as an error and process no data.
*/
free(data);
return (0);
}
data[length] = '\0';
/*
* Parse it out...
*/
status = cgi_initialize_string(data);
/*
* Free the data and return...
*/
free(data);
return (status);
}
/*
* 'cgi_initialize_string()' - Initialize form variables from a string.
*/
static int /* O - 1 if form data was processed */
cgi_initialize_string(const char *data) /* I - Form data string */
{
int done; /* True if we're done reading a form variable */
char *s, /* Pointer to current form string */
ch, /* Temporary character */
name[255], /* Name of form variable */
value[65536], /* Variable value */
*temp; /* Temporary pointer */
/*
* Check input...
*/
if (data == NULL)
return (0);
/*
* Loop until we've read all the form data...
*/
while (*data != '\0')
{
/*
* Get the variable name...
*/
for (s = name; *data != '\0'; data ++)
if (*data == '=')
break;
else if (*data >= ' ' && s < (name + sizeof(name) - 1))
*s++ = *data;
*s = '\0';
if (*data == '=')
data ++;
else
return (0);
/*
* Read the variable value...
*/
for (s = value, done = 0; !done && *data != '\0'; data ++)
switch (*data)
{
case '&' : /* End of data... */
done = 1;
break;
case '+' : /* Escaped space character */
if (s < (value + sizeof(value) - 1))
*s++ = ' ';
break;
case '%' : /* Escaped control character */
/*
* Read the hex code...
*/
if (!isxdigit(data[1] & 255) || !isxdigit(data[2] & 255))
return (0);
if (s < (value + sizeof(value) - 1))
{
data ++;
ch = *data - '0';
if (ch > 9)
ch -= 7;
*s = (char)(ch << 4);
data ++;
ch = *data - '0';
if (ch > 9)
ch -= 7;
*s++ |= ch;
}
else
data += 2;
break;
default : /* Other characters come straight through */
if (*data >= ' ' && s < (value + sizeof(value) - 1))
*s++ = *data;
break;
}
*s = '\0'; /* nul terminate the string */
/*
* Remove trailing whitespace...
*/
if (s > value)
s --;
while (s >= value && isspace(*s & 255))
*s-- = '\0';
/*
* Add the string to the variable "database"...
*/
if ((s = strrchr(name, '-')) != NULL && isdigit(s[1] & 255))
{
*s++ = '\0';
if (value[0])
cgiSetArray(name, atoi(s) - 1, value);
}
else if ((temp = cgiGetVariable(name)) != NULL)
{
free(temp);
cgiSetArray(name, cgiGetSize(name), value);
}
else
cgiSetVariable(name, value);
}
return (1);
}
/*
* 'cgi_passwd()' - Catch authentication requests and notify the server.
*
* This function sends a Status header and exits, forcing authentication
* for this request.
*/
static const char * /* O - NULL (no return) */
cgi_passwd(const char *prompt) /* I - Prompt (not used) */
{
(void)prompt;
fprintf(stderr, "DEBUG: cgi_passwd(prompt=\"%s\") called!\n",
prompt ? prompt : "(null)");
/*
* Send a 401 (unauthorized) status to the server, so it can notify
* the client that authentication is required.
*/
puts("Status: 401\n");
exit(0);
/*
* This code is never executed, but is present to satisfy the compiler.
*/
return (NULL);
}
/*
* 'cgi_set_sid()' - Set the CUPS session ID.
*/
static const char * /* O - New session ID */
cgi_set_sid(void)
{
char buffer[512], /* SID data */
sid[33]; /* SID string */
unsigned char sum[16]; /* MD5 sum */
const char *remote_addr, /* REMOTE_ADDR */
*server_name, /* SERVER_NAME */
*server_port; /* SERVER_PORT */
struct timeval curtime; /* Current time */
if ((remote_addr = getenv("REMOTE_ADDR")) == NULL)
remote_addr = "REMOTE_ADDR";
if ((server_name = getenv("SERVER_NAME")) == NULL)
server_name = "SERVER_NAME";
if ((server_port = getenv("SERVER_PORT")) == NULL)
server_port = "SERVER_PORT";
gettimeofday(&curtime, NULL);
CUPS_SRAND(curtime.tv_sec + curtime.tv_usec);
snprintf(buffer, sizeof(buffer), "%s:%s:%s:%02X%02X%02X%02X%02X%02X%02X%02X",
remote_addr, server_name, server_port,
(unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
(unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
(unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255,
(unsigned)CUPS_RAND() & 255, (unsigned)CUPS_RAND() & 255);
cupsHashData("md5", (unsigned char *)buffer, strlen(buffer), sum, sizeof(sum));
cgiSetCookie(CUPS_SID, cupsHashString(sum, sizeof(sum), sid, sizeof(sid)), "/", NULL, 0, 0);
return (cupsGetOption(CUPS_SID, num_cookies, cookies));
}
/*
* 'cgi_sort_variables()' - Sort all form variables for faster lookup.
*/
static void
cgi_sort_variables(void)
{
if (form_count < 2)
return;
qsort(form_vars, (size_t)form_count, sizeof(_cgi_var_t),
(int (*)(const void *, const void *))cgi_compare_variables);
}
/*
* 'cgi_unlink_file()' - Remove the uploaded form.
*/
static void
cgi_unlink_file(void)
{
if (form_file)
{
/*
* Remove the temporary file...
*/
unlink(form_file->tempfile);
/*
* Free memory used...
*/
free(form_file->name);
free(form_file->filename);
free(form_file->mimetype);
free(form_file);
form_file = NULL;
}
}