⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gcgi.c

📁 C/C++语言的CGI接口库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*-mode:c; c-style:k&r; c-basic-offset:4; -*- *//* * GCGI Library, implementing NCSA'a Common Gateway Interface and RFC2338. * Copyright (C) 2001-2002 Julian Catchen, julian@catchen.org * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "gcgi_private.h"static const char* const envVars[] =     {	"HTTP_COOKIE",	"HTTP_REFERER",	"AUTH_TYPE", 	"CONTENT_LENGTH",	"CONTENT_TYPE",	"GATEWAY_INTERFACE",	"PATH_INFO",	"PATH_TRANSLATED",	"QUERY_STRING",	"REMOTE_ADDR",	"REMOTE_HOST",	"REMOTE_IDENT",	"REMOTE_USER",	"REQUEST_METHOD",	"SCRIPT_NAME",	"SERVER_NAME",	"SERVER_PORT",	"SERVER_PROTOCOL",	"SERVER_SOFTWARE"    };#define ENVCOUNT 19/*------ Global Variables ------*/static CgiQuery *cgiQuery         = NULL;static int       debug            = 0;static char     *envVariablesFile = NULL;static char     *cgiQueryFile     = NULL;static size_t    fieldLimit       = 0;static size_t    queryLimit       = 0;static const char gcgi_ident[] =    "$GCGI: GCGI " VERSION " Copyright (C) 2001-2002 Julian Catchen $\n"    "$Authors:  Julian Catchen, topeka@catchen.org $";gcgiReturnType initCgi( ) {    int numBytes, gcgifd;    if (debug)	gcgiLoadEnvVariables(envVariablesFile);    /* Dup stdout to gcgiOut */    gcgifd = dup(fileno(stdout));    gcgiOut = fdopen(gcgifd, "w");    /* Create the cgiQuery object. */    createCgiQuery();    if (cgiQuery->env[gcgiRequestMethod] == NULL ) 	return GCGIFATALERROR;        if (! strncasecmp(cgiQuery->env[gcgiRequestMethod],"GET", 3) ) {	parseGetQueryString(&numBytes);	if (numBytes < 0)	    return GCGIFATALERROR;    }    else if (! strncasecmp(cgiQuery->env[gcgiRequestMethod],"POST", 4) ) {	parsePostQueryString(&numBytes);	if (numBytes < 0)	    return GCGIFATALERROR;    }    else	return GCGIFATALERROR;      return GCGISUCCESS;}void freeCgi( ){    freeCgiQuery();    if (envVariablesFile != NULL) XFREE(envVariablesFile);    if (cgiQueryFile != NULL) XFREE(cgiQueryFile);    }/* Limits specified in number of bytes. */gcgiReturnTypegcgiSetLimits(size_t flimit, size_t qlimit){    fieldLimit = flimit;    queryLimit = qlimit;    return GCGISUCCESS;}gcgiReturnType parsePostQueryString(int *numBytes){    FILE   *input;    char   *querystring;    size_t  clen;    int     result;    querystring = NULL;    result      = 0;    /* Return if we don't have the content length env variable. */    if (cgiQuery->env[gcgiContentLength] == NULL || cgiQuery->env[gcgiContentType] == NULL)	return GCGIFATALERROR;        clen = strtol(cgiQuery->env[gcgiContentLength], NULL, 10);    /* Content Length was out of range */    if (errno == ERANGE)	return GCGIFATALERROR;    if (debug) {	if ((input = fopen(cgiQueryFile, "r")) == NULL)	    return GCGIFATALERROR;    }    else {	input = stdin;    }    /* Standard URL Encoded POST string. */    if (strncasecmp(cgiQuery->env[gcgiContentType], "application/x-www-form-urlencoded", 33) == 0) {	querystring = readQueryFromStream(input, clen);	parseUrlEncoded(querystring, clen);	*numBytes = clen;    }        /* RFC2388 Encoding */    else if (strncasecmp(cgiQuery->env[gcgiContentType], "multipart/form-data", 19) == 0) {	/* Pass the file to the MIME library to parse. */	if ((result = parseFormData(input)) == GCGIFATALERROR)	    return GCGIFATALERROR;		*numBytes = clen;        }       /* Unknown Encoding. */    else {	fprintf(stderr,"Unknown Encoding.\n");	return GCGIFATALERROR;    }    if (debug) fclose(input);	    XFREE(querystring);	    if (result == GCGITRUNCATED)	return GCGITRUNCATED;    else	return GCGISUCCESS;}gcgiReturnType parseGetQueryString(int *numBytes){    size_t clen;        if (cgiQuery->env[gcgiQueryString] == NULL)	return GCGIFATALERROR;    clen = strlen(cgiQuery->env[gcgiQueryString]);     if (clen <= 0)	return GCGIFATALERROR;    *numBytes = parseUrlEncoded(cgiQuery->env[gcgiQueryString], clen);    return GCGISUCCESS;}gcgiReturnType parseUrlEncoded(char *querystring, int clen) {    QueryStringNode *qstring;     char            *beg, *end, *qlen;    char            *offset, *p;     int              i;    beg = end = qlen = NULL;    offset = querystring + strlen(querystring);    /* Count the number of fileds in the Query String. */    for (p = querystring, i = 0; p < offset; p++)	if (*p == '&')	    i++;    /* There is one more field than '&' characters. */    i++;    /* Create the QueryStringColl Array */    createQueryStringCollArray(i);    qlen = querystring + clen;    for (beg = querystring; beg < qlen && end < qlen; beg = end+1) {	/* Malloc the queryString object and initialize it. */	createQueryStringNode(&qstring);	/* Get Field Name */	for (end = beg; *end != '=' && end < qlen; end++);	qstring->field = XMALLOC(char, end - beg + 1);	strncpy(qstring->field, beg, end-beg);	qstring->field[end-beg] = '\0';                      /* Zero out the string */	/* Get Data */	for (beg = end+1; *end != '&' && end < qlen; end++);	qstring->data = XMALLOC(char, end - beg + 1);	strncpy(qstring->data, beg, end-beg);	qstring->data[end-beg] = '\0';                       /* Zero out the string */	qstring->size = end - beg + 1;		decodeUrl(qstring);	/* Add struct to linked list. */	insertQueryStringNode(qstring);    } /* for (beg = querystring; *beg < qlen && *end < qlen; beg++) */        return GCGISUCCESS;}gcgiReturnType parseFormData(FILE *data){    MimePart *mime, *n;    QueryStringNode *node;    int len, i, trunc;    if ((mime = mimeParseMimeMessage(data, queryLimit, fieldLimit)) == NULL)	return GCGIFATALERROR;        /* Check if the MIME message was truncated. */    trunc = mime->truncated;    /* Count the number of fileds in the Query String. */    for (n = mime->next, i = 0; n != NULL; n = n->next) i++;    createQueryStringCollArray(i);    for (n = mime->next; n != NULL; n = n->next) {	createQueryStringNode(&node);	len = strlen(n->name);	node->field = XMALLOC(char, len + 1);	strncpy(node->field, n->name, len);	node->field[len] = '\0';	node->type     = n->type;	node->encoding = n->encoding;	len = strlen(n->subtype);	node->subtype = XMALLOC(char, len + 1);	strncpy(node->subtype, n->subtype, len);	node->subtype[len] = '\0';	if (n->filename != NULL) {	    len = strlen(n->filename);	    node->filename = XMALLOC(char, len + 1);	    strncpy(node->filename, n->filename, len);	    node->filename[len] = '\0';	}	len = n->bodylen;	node->data = XMALLOC(char, len + 1);	/* Remove final "\r\n" that separated the boundary from the body. */	if (n->body[len-1] == '\n' && n->body[len-2] == '\r') 	    len -= 2;		memcpy(node->data, n->body, len);	node->data[len] = '\0';	node->size = len;	node->truncated = n->truncated;		if (debug)	    fprintf(stderr,"N: Field: %s, Type: %d, Subtype: %s\n",n->name, n->type, n->subtype);	insertQueryStringNode(node);	node = NULL;    }    /* Free the MIME structures. */    mimeFreeMimeMessage(mime);    if (trunc)	return GCGITRUNCATED;    else	return GCGISUCCESS;}void decodeUrl(QueryStringNode *qstring){    char *f, *d;    int  flen, dlen;    gcgiDecodeUrlEncodedString(qstring->field, &f, &flen);    strncpy(qstring->field, f, flen);    qstring->field[flen-1] = '\0';    gcgiDecodeUrlEncodedString(qstring->data, &d, &dlen);    strncpy(qstring->data, d, dlen);    qstring->data[dlen-1] = '\0';    XFREE(d);    XFREE(f);}gcgiReturnType  gcgiSendContentType(char *mimeType, char *name, char *charset, HTTPHeader header){    fprintf(gcgiOut, "Content-Type: %s", mimeType);    if ( (charset!= NULL) && (strlen(charset) > 0) )	fprintf(gcgiOut, "; charset=\"%s\"", charset);    if ( (name!= NULL) && (strlen(name) > 0) )	fprintf(gcgiOut, "; name=\"%s\"", name);    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    return GCGISUCCESS;}gcgiReturnType  gcgiSendContentDisp(MimeDisposition disp, char *filename, HTTPHeader header){    char *strDisp[] = { "inlined",			"attachment",			"formdata"    };    fprintf(gcgiOut, "Content-Disposition: %s", strDisp[disp]);    if ( (filename!= NULL) && (strlen(filename) > 0) )	fprintf(gcgiOut, "; filename=\"%s\"", filename);    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    return GCGISUCCESS;}gcgiReturnType  gcgiSendContentLength(int length, HTTPHeader header){    fprintf(gcgiOut, "Content-Length: %d", length);    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    return GCGISUCCESS;}gcgiReturnType  gcgiSendLocation(char *redirectURL){    fprintf(gcgiOut, "Location: %s\r\n\r\n", redirectURL);    return GCGISUCCESS;}gcgiReturnType  gcgiSendStatus(int status, char *message){    fprintf(gcgiOut, "HTTP/1.1 %d %s\r\n\r\n", status, message);    return GCGISUCCESS;}gcgiReturnType  gcgiSendCacheControl(char *cache, HTTPHeader header){    fprintf(gcgiOut, "Cache-Control: %s", cache);    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    return GCGISUCCESS;}gcgiReturnType  gcgiSendCookie(char *name, char *value, char *path, char *domain, char *expires, int secure, HTTPHeader header){    char *cookieEncoded;    gcgiEncodeBaseSixtyFourString(value, strlen(value), &cookieEncoded);        fprintf(gcgiOut,	    "Set-Cookie: %s=%s; path=%s; domain=%s;", 	    name, cookieEncoded, path, domain);    if (expires && strlen(expires) > 0)	fprintf(gcgiOut, " expires=%s;", expires);    if (secure)	fprintf(gcgiOut, " secure");    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    XFREE(cookieEncoded);    return GCGISUCCESS;}gcgiReturnType  gcgiFetchCookies(char ***cookies){    tokenizeString(cgiQuery->env[gcgiHttpCookie], strlen(cgiQuery->env[gcgiHttpCookie]), cookies);    return GCGISUCCESS;}gcgiReturnType  gcgiParseCookie(char *cookie, char **name, char **value){    char *encoded, *decoded;    int   size;    parseToken(cookie, name, &encoded);    gcgiDecodeBaseSixtyFourString(encoded, &decoded, &size);    size++;    decoded = XREALLOC(char, decoded, size);    decoded[size-1] = '\0';    *value = decoded;    XFREE(encoded);    return GCGISUCCESS;}gcgiReturnType  gcgiFreeCookies(char **cookies){    freeStringArray(cookies);    return GCGISUCCESS;}#ifdef USE_SSLgcgiReturnType  gcgiSendEncryptedCookie(char *name, char *value, char *path, char *domain, char *expires, 			int secure, unsigned char *key, HTTPHeader header){    char          *cookieEncoded;    char          *ciphertext, *digestEncoded;    unsigned char *digest;    int            ctlen, dlen;    ciphertext    = NULL;    digest        = NULL;    digestEncoded = NULL;    ctlen         = 0;    dlen          = 0;    encryptString(value, strlen(value), key, &ciphertext, &ctlen);    generateStringHMAC(ciphertext, ctlen, &digest, &dlen);    gcgiEncodeBaseSixtyFourString(ciphertext, ctlen, &cookieEncoded);    gcgiEncodeBaseSixtyFourString(digest, dlen, &digestEncoded);        fprintf(gcgiOut,	    "Set-Cookie: %s=%s&%s; path=%s; domain=%s;", 	    name, cookieEncoded, digestEncoded, path, domain);    if (expires && strlen(expires) > 0)	fprintf(gcgiOut, " expires=%s;", expires);    if (secure)	fprintf(gcgiOut, " secure");    if (header == LAST)	fprintf(gcgiOut, "\r\n");    fprintf(gcgiOut, "\r\n");    XFREE(cookieEncoded);    XFREE(ciphertext);    XFREE(digest);    XFREE(digestEncoded);    return GCGISUCCESS;}gcgiReturnType  gcgiParseEncryptedCookie(char *cookie, unsigned char *key, char **name, char **value){    char          **tokens;    int             size;    char           *ciphertext, *cdigest, *encoded, *decoded;    unsigned char  *digest;    int             ctlen, dlen, cdlen;    ciphertext = NULL;    digest     = NULL;    cdigest    = NULL;    ctlen      = 0;    dlen       = 0;    cdlen      = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -