📄 cgi-util.c
字号:
/* cgi-util.c version 2.2.0 by Bill Kendrick <bill@newbreedsoftware.com> and Mike Simons <msimons@moria.simons-clan.com> and Gary Briggs <chunky@icculus.org> Other contributions; see CHANGES.txt New Breed Software http://www.newbreedsoftware.com/cgi-util/ April 6, 1996 - May 16, 2004*/#include <stdio.h>#include <ctype.h>#include <errno.h>#include <unistd.h>#ifndef NO_STDLIB_H#include <stdlib.h>#elsechar *getenv();#endif#include <string.h>#include "cgi-util.h"/* Globals: */cgi_entry_type * cgi_entries = NULL;cgi_cookie_type * cgi_cookies = NULL;int cgi_num_entries = 0;int cgi_num_cookies = 0;int cgi_errno = CGIERR_NONE;int cgi_request_method = CGIREQ_NONE;int cgi_content_type = CGITYPE_NONE;char * cgi_query = NULL;/* English error strings: */char * cgi_error_strings[CGIERR_NUM_ERRS] = { "", "Not an integer", "Not a double", "Not a boolean", "Unknown method", "Incorrect Content Type", "NULL Query String", "Bad Content Length", "Content Length Discrepancy", "No Cookies", "Cookie Not Found", "Not That Many"};/* Debugging. If set, this library will attempt to append debugging information to a file named "debug.txt" in the current directory. *//* #define DEBUG *//* Converts hexadecimal to decimal (character): */char x2c(char *what){ char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return (digit);}/* Unescapes "%"-escaped characters in a query: */void unescape_url(char *url){ int x,y,len; len = strlen(url); for (x=0, y=0; url[y]; ++x, ++y) { if ((url[x] = url[y]) == '%' && y < len - 2) /* 2.0.4 - MJ Pomraning (pilcrow@mailbag.com) */ { url[x] = x2c(&url[y+1]); y+=2; } } url[x] = '\0';}/* Converts pluses back to spaces in a query: */void plustospace(char *str){ int x; for (x=0; str[x]; x++) if (str[x] == '+') str[x] = ' ';}/* Internal use: Write debugging stuff to a file */void debug(char * str1, char * str2){#ifdef DEBUG FILE * fi; fi = fopen("debug.txt", "a"); if (fi != NULL) { fprintf(fi, "%s:%s\n", str1, str2); fclose(fi); }#endif}/* Internal use: Read a line and return its length: */int lineread(FILE * stream, char * buf, int count){ char * c; c = fgets(buf, count, stream); if (c != NULL) return(strlen(buf)); else return(0);}/* Initialize the CGI. Grab data from the browser and prepare it for us. */int cgi_init(void){ int cl, i, in_multipart_headers, which_entry, length_gotten, in_name; char * boundary; /* Default, no errors, no name/value pairs ("entries"): */ cgi_errno = CGIERR_NONE; cgi_num_entries = 0; length_gotten = 0; cgi_parse_cookies(); /* Check for REQUEST_METHOD (set by HTTP server): */ if (getenv("REQUEST_METHOD") == NULL) { /* None set? Assume the user is invoking the CGI from a shell prompt (for debugging): */ cgi_request_method = CGIREQ_NONE; } else { /* Determine the exact request method, and grab the data (if any) in the appropriate manner: */ if (strcmp(getenv("REQUEST_METHOD"), "POST") == 0) { /* Post method (data is sent to us via "stdin"): */ cgi_request_method = CGIREQ_POST; if (getenv("CONTENT_TYPE") == NULL) { /* Content type is not set! */ cgi_errno = CGIERR_INCORRECT_TYPE; cgi_content_type = CGITYPE_UNKNOWN; return(cgi_errno); } else if (strstr(getenv("CONTENT_TYPE"), "application/x-www-form-urlencoded") == getenv("CONTENT_TYPE")) { cgi_content_type = CGITYPE_APPLICATION_X_WWW_FORM_URLENCODED; /* How much data do we expect? */ if (getenv("CONTENT_LENGTH") == NULL || sscanf(getenv("CONTENT_LENGTH"), "%d", &cl) != 1) { cgi_errno = CGIERR_BAD_CONTENT_LENGTH; return(cgi_errno); } /* Create space for it: */ cgi_query = malloc(cl + 1); /* 2.0.1 - Tadek Orlowski (orlowski@epnet.com) ... "+1" */ if (cgi_query == NULL) { cgi_errno = CGIERR_OUT_OF_MEMORY; return(cgi_errno); } /* Read it in: */ fgets(cgi_query, cl + 1, stdin); /* Verify that we got as much data as we expected: */ if (cgi_query == NULL || strlen(cgi_query) != cl) cgi_errno = CGIERR_CONTENT_LENGTH_DISCREPANCY; } else if (strstr(getenv("CONTENT_TYPE"), "multipart/form-data") == getenv("CONTENT_TYPE")) { cgi_content_type = CGITYPE_MULTIPART_FORM_DATA; cgi_query = malloc(2050); if (cgi_query == NULL) { cgi_errno = CGIERR_OUT_OF_MEMORY; return(cgi_errno); } /* Determine the boundary string: */ if (strstr(getenv("CONTENT_TYPE"),"boundary=") == NULL) { cgi_errno = CGIERR_NO_BOUNDARY; return(cgi_errno); } /* boundary = strdup(strstr(getenv("CONTENT_TYPE"), "boundary=") + 9); */ boundary = malloc(strlen(strstr(getenv("CONTENT_TYPE"), "boundary=")) - strlen("boundary=") + 1); strcpy(boundary, strstr(getenv("CONTENT_TYPE"), "boundary=") + strlen("boundary=")); debug("boundary", boundary); /* Read in until there's no more: */ in_multipart_headers = 0; which_entry = -1; do { length_gotten = lineread(stdin, cgi_query, 2048); debug("cgi_query", cgi_query); if (length_gotten > 0) { if (strstr(cgi_query, boundary) == cgi_query + 2 && cgi_query[0] == '-' && cgi_query[1] == '-') { /* We got a boundary! */ in_multipart_headers = 1; which_entry = -1; } else /* (Not a boundary) */ { if (in_multipart_headers == 1) { /* We had just got a boundary, read headers: */ if (cgi_query[0] == '\r' || cgi_query[0] == '\n') { /* Blank line, end of headers: */ in_multipart_headers = 0; } else /* (Not a blank line) */ { /* What kind of header is it? */ if (strstr(cgi_query,"Content-Disposition: ") == cgi_query) { /* Content-disposition: */ /* For now, just look for "name=": */ if (strstr(cgi_query, "name=\"") != NULL) { /* Add a new entry: */ which_entry = cgi_num_entries; cgi_num_entries++; /* Make more room: */ cgi_entries = realloc(cgi_entries, sizeof(cgi_entry_type) * cgi_num_entries); if (cgi_entries == NULL) { cgi_errno = CGIERR_OUT_OF_MEMORY; return(cgi_errno); } /* Fill in the name slot: */ cgi_entries[which_entry].name = malloc(strlen(strstr(cgi_query,"name=")) -strlen("name=") + 1); strcpy(cgi_entries[which_entry].name, strstr(cgi_query, "name=") + strlen("name=") + strlen("name=")); /* strdup(strstr(cgi_query, "name=\"") + 6); */ /* Truncate after quote: */ if (strchr(cgi_entries[which_entry]. name, '\"') != NULL) { strcpy(strchr(cgi_entries [which_entry].name, '\"'), "\0"); } /* Set default content-type: */ cgi_entries[which_entry]. content_type = "application/octet-stream"; /* Set default content-length: */ cgi_entries[which_entry]. content_length = 0; /* Set default value: */ cgi_entries[which_entry].val = malloc(1); cgi_entries[which_entry].val[0] = '\0'; debug("entry.name", cgi_entries[which_entry].name); } } else if (strstr(cgi_query, "Content-Type: ") == cgi_query) { /* Content-type: */ cgi_entries[which_entry].content_type = malloc(strlen(strstr(cgi_query, "Content-Type: ")) - strlen("Content-Type: ") + 1); cgi_entries[which_entry].content_type = strcpy(cgi_entries[which_entry].content_type, strstr(getenv("CONTENT_TYPE"), "Content-Type: ") + strlen("Content-Type: ")); /* strdup(strstr(cgi_query, "Content-Type: ") + 14); */ debug("entry.content_type", cgi_entries[which_entry]. content_type); } } } else /* in_multipart_headers == 0 */ { /* If we're recording into a particular entry, copy the data: */ if (which_entry != -1) { /* Make more room: */ cgi_entries[which_entry].val = realloc(cgi_entries[which_entry].val, strlen(cgi_entries[which_entry]. val) + length_gotten + 1); if (cgi_entries[which_entry].val == NULL) { cgi_errno = CGIERR_OUT_OF_MEMORY; return(cgi_errno); } /* Append the data: */ memcpy(cgi_entries[which_entry].val + (cgi_entries[which_entry]. content_length), cgi_query, length_gotten); cgi_entries[which_entry].content_length = (cgi_entries[which_entry].content_length + length_gotten); } } } } } while (length_gotten > 0); free(cgi_query); cgi_query = NULL; } else { /* Content type is unrecognized! */ cgi_errno = CGIERR_INCORRECT_TYPE; cgi_content_type = CGITYPE_UNKNOWN; return(cgi_errno); } } else if (strcmp(getenv("REQUEST_METHOD"), "GET") == 0) { /* For now, assume Content Type of "application/x-www-form-urlencoded" (Is this a bad assumption?) */ cgi_content_type = CGITYPE_APPLICATION_X_WWW_FORM_URLENCODED; /* GET method (data sent via "QUERY_STRING" env. variable): */ cgi_request_method = CGIREQ_GET; /* Get a pointer to the data: */ cgi_query = getenv("QUERY_STRING"); if (cgi_query == NULL) { /* Does the "QUERY_STRING" env. variable not exist!? */ /* cgi_errno = CGIERR_NULL_QUERY_STRING; */ /* return(cgi_errno); */ cl = 0; cgi_query = ""; } else { /* Determine the content length by seeing how big the string is: */ cl = strlen(cgi_query); } } else { /* Something else? We can't handle it! */ cgi_request_method = CGIREQ_UNKNOWN; cgi_errno = CGIERR_UNKNOWN_METHOD; cgi_num_entries = 0; return(cgi_errno); } if (cgi_content_type != CGITYPE_MULTIPART_FORM_DATA) { /* How many entries (name/value pairs) do we need to allocate space for? (They should be separated by "&"'s) */ cgi_num_entries = 0; for (i = 0; i <= cl; i++) if (cgi_query[i] == '&' || cgi_query[i] == '\0') cgi_num_entries++; /* Allocate the space for that many structures: */ cgi_entries = malloc(sizeof(cgi_entry_type) * cgi_num_entries); if (cgi_entries == NULL) { cgi_errno = CGIERR_OUT_OF_MEMORY; return(cgi_errno); } /* Grab each name/value pair: */ cgi_num_entries = 0; /* (Begin with the first half of the first pair): */ if (cgi_query[0] != '\0' && cgi_query[0] != '&') { cgi_entries[0].name = cgi_query; cgi_entries[0].content_type = "text/html"; } /* Go through the entire string of characters: */ in_name = 1; for (i = 0; i <= cl; i++) { if (cgi_query[i] == '&') { /* "&" represents the end of a name/value pair: */ cgi_entries[cgi_num_entries].name = cgi_query + i + 1; cgi_entries[cgi_num_entries].content_type = "text/html"; cgi_query[i] = '\0'; in_name = 1; } else if (cgi_query[i] == '=' && in_name) { /* "=" is the end of the name half of a name/value pair: */ cgi_entries[cgi_num_entries].val = cgi_query + i + 1; /* plustospace(cgi_entries[cgi_num_entries].val); unescape_url(cgi_entries[cgi_num_entries].val); */ cgi_num_entries++; in_name = 0; cgi_query[i] = '\0'; } } for (i = 0; i < cgi_num_entries; i++) { plustospace(cgi_entries[i].val); unescape_url(cgi_entries[i].val); } } /* Fix any NULL strings to be empty strings */ /* 2.0.4 - MJ Pomraning (pilcrow@mailbag.com) */ for (i = 0; i < cgi_num_entries; i++) { if (cgi_entries[i].name == NULL) cgi_entries[i].name = ""; if (cgi_entries[i].val == NULL) cgi_entries[i].val = ""; } } return(CGIERR_NONE);}/* Free up memory that was allocated when we called "cgi_init()": */void cgi_quit(void){ if (cgi_query != NULL) free(cgi_query); if (cgi_entries != NULL) free(cgi_entries); if (cgi_cookies != NULL) free(cgi_cookies);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -