/* $Id: CGI.c,v 1.16 2005/04/03 05:26:14 starfish Exp $ */ #include "CGI.h" #include #include #include #include /* Both SearchField() and SearchFieldAlocate search the query string for the given field. SearchField() writes the result in a given space, but SearchFieldAllocate() allocate the memory for the result using realloc(). Therefore, the caller should free() the memory of the returned value in *bufptr. SearchFieldAllocate() can used only on the POST forms because the seperator is fixed to "&". */ static int SearchField(const char *str, const char *field, char *buf, size_t bufsize, const char *sep) { const char *match; size_t i; const size_t fieldlen = strlen(field); const size_t seplen = strlen(sep); match = str; for (;;) { match = strstr(match, field); if (match == NULL) { buf[0] = '\0'; return 1; } if (match[fieldlen] == '=' && (match == str || !strncmp(sep, match-seplen, seplen))) break; match += 1; } match = match + fieldlen + 1; for (i=0; i= bufsize) { bufsize += bufincr; buf2 = realloc(buf, bufsize); if (buf2 == NULL) { free(buf); return 3; } buf = buf2; } switch (s[i]) { case '%': ++i; if (s[i]<'0' || (s[i]>'9' && s[i]<'A') || s[i]>'F') break; buf[j] = (s[i]<='9' ? s[i]-'0' : s[i]-'A'+10); ++i; if (s[i]<'0' || (s[i]>'9' && s[i]<'A') || s[i]>'F') break; buf[j] = (buf[j] << 4) + (s[i]<='9' ? s[i]-'0' : s[i]-'A'+10); break; case '+': buf[j] = ' '; break; default: buf[j] = s[i]; } } buf[j] = '\0'; *bufptr = buf; return 0; } /* QueryString and PostString is the query from the web browser. QueryString is the query in GET method or in the URL. PostString is sent by POST method. QueryReady is set to non-zero if QueryString and PostString is ready. */ static char *QueryString = NULL; static char *PostString = NULL; static unsigned char QueryReady = 0; /* Read QueryString and PostString if they are not ready. */ static void PrepairQueryStrings(void) { if (!QueryReady) { char *new_ps; size_t pssize, len; const int step = 1024; QueryString = getenv("QUERY_STRING"); if (QueryString == NULL) QueryString = ""; if (PostString != NULL) { free(PostString); PostString = NULL; } pssize = 0; len = 0; do { pssize = len + step; new_ps = realloc(PostString, pssize); if (new_ps == NULL) break; PostString = new_ps; len += fread(PostString+len, 1, pssize-len, stdin); } while (len == pssize); PostString[len] = '\0'; QueryReady = 1; } } /* Search a input string in the form "field=value&...". "field" is the name of the field. "buf" is the value if the value is found and "bufsize" is the size of buf. This function returns zero if data found. */ int web_GetQuery(const char *field, char *buf, size_t bufsize) { if (bufsize <= 0 || field == NULL || field[0] == '\0') return 1; PrepairQueryStrings(); if (!SearchField(QueryString, field, buf, bufsize, "&")) return 0; else return SearchField(PostString, field, buf, bufsize, "&"); } /* This function does the same job as web_GetQuery(), but it will allocate the memory for the result. The caller should free() the space in *bufptr. */ int web_GetQueryAllocate(const char *field, char **bufptr) { PrepairQueryStrings(); if (!SearchFieldAllocate(QueryString, field, bufptr)) return 0; else return SearchFieldAllocate(PostString, field, bufptr); } static char *Cookie = NULL; static unsigned char CookieReady = 0; /* Get the value of a cookie. */ int web_GetCookie(const char *field, char *buf, size_t bufsize) { if (bufsize <= 0 || field == NULL || field[0] == '\0') return 1; if (!CookieReady) { Cookie = getenv("HTTP_COOKIE"); if (Cookie == NULL) { buf[0] = '\0'; return 1; } } return SearchField(Cookie, field, buf, bufsize, "; "); } /* Clear all allocated memory. This function is useful in FastCGI to clear the string of the last connection. */ void web_ClearCGI(void) { if (QueryReady) { if (PostString != NULL) free(PostString); } QueryReady = 0; CookieReady = 0; } /* Display a string in HTML. Special characters are replaced with HTML notation. */ void web_PrintString(FILE *file, char const *string) { int i; for (i=0; string[i]!='\0'; ++i) { if (string[i] == '<') { fprintf(file, "<"); } else if (string[i] == '>') { fprintf(file, ">"); } else if (string[i] == '&') { fprintf(file, "&"); } else if (string[i] == '\"') { fprintf(file, """); } else { fputc(string[i], file); } } }