#include #include #include #include #include "global.h" struct var_t { char *name, *data; struct var_t *next; }; struct env_t { char *name, *data; struct env_t *next; }; extern char **environ, allowpassword; unsigned int content_length = 0; unsigned char *gdata = NULL; struct var_t *varlist = NULL; struct env_t *envlist = NULL; /* Determine what user is trying to do based on variables supplied */ void cgi_nav(void) { char *r = NULL, i = 0; i = 0; r = cgi_is_var("Register"); if (r) { go_register(); return; } if (allowpassword) t_open(T_REGISTER_WITH_PASSWORD); else t_open(T_REGISTER); } /* Parse out information in stdin, if any gdata contains parsed out data, which is pointed to by the var_t linked list. */ void cgi_var(void) { int ret = 0; struct var_t *v = NULL, *vt = NULL; unsigned char *h = NULL, *t = NULL, *n = NULL, *d = NULL; gdata = (unsigned char *)malloc(content_length + 1); if (gdata == NULL) global_error("Out of memory", 1, 0); memset((unsigned char *)gdata, 0, (content_length + 1)); ret = read(0, (unsigned char *)gdata, content_length); if (ret != content_length) global_error("Unable to read content", 1, 0); cgi_parse_hex(); varlist = (struct var_t *)malloc(sizeof(struct var_t)); varlist->next = NULL; vt = varlist; for (n = NULL, d = NULL, h = t = gdata;;) { if ((*h == '=') && (n == NULL)) { *h++ = '\0'; n = t; t = h; } else if (((*h == '&') && (n != NULL) && (d == NULL)) || ((!(*h)) && (n != NULL) && (d == NULL))) { if (*h) *h++ = '\0'; else h = NULL; d = t; t = h; v = (struct var_t *)malloc(sizeof(struct var_t)); if (v == NULL) global_error("Out of memory", 1, 0); v->name = n; v->data = d; v->next = NULL; vt->next = v; vt = v; n = d = NULL; if (h == NULL) break; } else h++; } } /* Convert all hex codes in content to ascii */ void cgi_parse_hex(void) { unsigned int len = 0; unsigned char r = 0; unsigned char *p = NULL; len = content_length; for (p = gdata; *p; p++) { len--; if (*p == '%') { if ((*(p + 1)) && (*(p + 2))) { r = hex2asc(*(p + 1), *(p + 2)); *p = r; memcpy((char *)(p + 1), (char *)(p + 3), (len - 2)); *(p + len - 1) = '\0'; } } else if (*p == '+') *p = ' '; } } /* Fetch HTTP environment variables */ void cgi_env(void) { struct env_t *et = NULL, *e = NULL; char *t = NULL, *n = NULL, *v = NULL; int i = 0, elen = 0, nlen = 0, vlen = 0; envlist = (struct env_t *)malloc(sizeof(struct env_t)); if (envlist == NULL) global_error("Out of memory", 1, 0); envlist->next = NULL; et = envlist; for (i = 0; environ[i]; i++) { for (t = environ[i]; *t != '='; t++); elen = strlen(environ[i]); nlen = (elen - strlen(t)); vlen = (elen - nlen); e = (struct env_t *)malloc(sizeof(struct env_t)); if (e == NULL) global_error("Out of memory", 1, 0); n = (char *)malloc(nlen + 1); if (n == NULL) global_error("Out of memory", 1, 0); v = (char *)malloc(vlen + 1); if (v == NULL) global_error("Out of memory", 1, 0); e->name = n; e->data = v; e->next = NULL; memset(n, 0, (nlen + 1)); memset(v, 0, (vlen + 1)); memcpy(n, environ[i], nlen); memcpy(v, (++t), vlen); et->next = e; et = e; } } void cgi_init(void) { int val = 0; char *env = NULL; cgi_env(); env = cgi_is_env("REQUEST_METHOD"); if (env == NULL) global_error("Unknown request method", 1, 0); if (strcasecmp(env, "POST")) { if (strcasecmp(env, "GET")) global_error("Unsupported request method", 1, 0); gdata = NULL; varlist = NULL; if (allowpassword) t_open(T_REGISTER_WITH_PASSWORD); else t_open(T_REGISTER); } env = cgi_is_env("CONTENT_LENGTH"); if (env == NULL) global_error("Unknown content", 1, 0); val = atoi(env); if (val < 1) global_error("Invalid content length", 1, 0); if (val > MAX_CONTENT_LENGTH) val = (MAX_CONTENT_LENGTH - 1); content_length = val; cgi_var(); } char *cgi_is_env(char *name) { struct env_t *e = NULL; for (e = envlist; e->next; e = e->next) { if (!(strcmp(e->next->name, name))) return e->next->data; } return NULL; } char *cgi_is_var(char *name) { struct var_t *v = NULL; if (varlist == NULL) return NULL; for (v = varlist; v->next; v = v->next) { if (!(strcmp(v->next->name, name))) return v->next->data; } return NULL; } char matoh(char x) { char ret = 0; switch(x) { case '0': ret = 0; break; case '1': ret = 1; break; case '2': ret = 2; break; case '3': ret = 3; break; case '4': ret = 4; break; case '5': ret = 5; break; case '6': ret = 6; break; case '7': ret = 7; break; case '8': ret = 8; break; case '9': ret = 9; break; case 'A': ret = 10; break; case 'B': ret = 11; break; case 'C': ret = 12; break; case 'D': ret = 13; break; case 'E': ret = 14; break; case 'F': ret = 15; break; default: ret = -1; break; } return ret; } unsigned char hex2asc(char s, char f) { char ret = 0; unsigned char val1 = 0, val2 = 0, val3 = 0; ret = matoh(f); if (ret == -1) return 0; val1 = ret; ret = matoh(s); if (ret == -1) return 0; val2 = ret; val3 = val1 + (val2 * 15) + val2; return val3; }