/* parser v 1.1 * Kacper Nowicki (Kacper.Nowicki@fuw.edu.pl), 1994 */ #include <fcntl.h> #include <stdlib.h> #include <string.h> #include "parser.h" /* Structure with CGI variables */ cgi_t cgi; static int cgi_get(void); /* Main parser routine */ int parser(partab_t *table) { int sign = 0, num = 0, length; long OK; char **mm, **mm1, **mm2; char *buffer, *ptr, *tmpbuf, *tmpptr, *begin; partab_t *tt; /* Set length from environment * Malloc buffer * Read data from standard input to buffer */ if(cgi_get()) return(-1); length = cgi.CONTENT_LENGTH; if(fcntl(0, F_SETFL, FNDELAY)) return(-1); if(!(buffer = (char *)malloc(length + 1))) return(-1); if(read(PARSER_FD, buffer, length) < length) { free(buffer); return(-1); } *(buffer + length) = '&'; /* Process standard input : Search for variable names and * set their values */ begin = ptr = buffer; tt = NULL; if(!(tmpbuf = (char *)malloc(length))) return(-1); while(ptr < buffer + length + 1) { /* End of variable name, beginning of value */ if(*ptr == '=') { *ptr++ = '\0'; for(tt = table; tt->varptr; tt++) if(!strcmp(begin, tt->varname)) break; if(tt->varptr) { tmpptr = tmpbuf; OK = 1; sign = 0; if(tt->vartype == PARSER_BOOL) { *(int *)tt->varptr = 1; } else if(tt->vartype >= PARSER_INT) /* Numeric variables */ { if(*ptr == '-') { ptr++; sign = 1; } switch(tt->vartype) { case PARSER_INT: *(int *)tt->varptr = 0; break; case PARSER_LONG: *(long *)tt->varptr = 0l; break; case PARSER_FLOAT: *(float *)tt->varptr = 0.0; } } } else tt = NULL; } /* End of variable value * '&' is set also after last variable value */ else if(*ptr == '&') { begin = ++ptr; if(!tt) /* It isn't variable from the table */ continue; num++; switch(tt->vartype) { case PARSER_BOOL: break; case PARSER_CHAR: if(tmpptr > tmpbuf) *(char *)tt->varptr = *tmpbuf; break; case PARSER_STRING: if(tmpptr - tmpbuf) { *tmpptr++ = '\0'; if(!(*(char **)tt->varptr = (char *)malloc(tmpptr - tmpbuf))) return (-1); memcpy(*(char **)tt->varptr, tmpbuf, tmpptr - tmpbuf); } else *(char **)tt->varptr = NULL; break; case PARSER_MULTIS: if(tmpptr == tmpbuf) break; if(*(char ***)tt->varptr) { mm2 = *(char ***)tt->varptr; while(*mm2++) ; if(! (mm1 = mm = (char **) malloc((1 + mm2 - *(char ***)tt->varptr) * sizeof(char **)))) return(-1); mm2 = *(char ***)tt->varptr; while(*mm1++ = *mm2++) ; mm1--; free(*(char ***)tt->varptr); *(char ***)tt->varptr = mm; } else if(! (mm1 = *(char ***)tt->varptr = (char **)malloc(2*sizeof(char **)))) return(-1); *tmpptr++ = '\0'; if(!(*mm1 = (char *)malloc(tmpptr - tmpbuf))) return (-1); memcpy(*mm1, tmpbuf, tmpptr - tmpbuf); *++mm1 = NULL; break; case PARSER_INT: if(sign) *(int *)tt->varptr *= -1; break; case PARSER_LONG: if(sign) *(long *)tt->varptr *= -1; break; case PARSER_FLOAT: if(sign) *(float *)tt->varptr *= -1.0; break; default: return(-1); } tt = NULL; } /* Variable value (tt is set) */ else if(tt) switch(tt->vartype) { case PARSER_BOOL: ptr++; break; case PARSER_CHAR: case PARSER_STRING: case PARSER_MULTIS: if(*ptr == '+') *tmpptr++ = ' '; else if (*ptr == '%') { ptr++; *tmpptr = (*ptr >= 'A'? (*ptr & 0xdf) - 'A' + 10: *ptr - '0'); ptr++; *tmpptr = 16 * (*tmpptr) + (*ptr >= 'A'? (*ptr & 0xdf) - 'A' + 10: *ptr - '0'); tmpptr++; } else *tmpptr++ = *ptr; ptr++; break; case PARSER_INT: if(OK && (*ptr >= '0') && (*ptr <= '9')) *(int *)tt->varptr = 10 * *(int *)tt->varptr + (*ptr - '0'); else OK = 0; ptr++; break; case PARSER_LONG: if(OK && (*ptr >= '0') && (*ptr <= '9')) *(long *)tt->varptr = 10 * *(long *)tt->varptr + (*ptr - '0'); else OK = 0; ptr++; break; case PARSER_FLOAT: if(OK) { if(*ptr == '.') OK = 10; else if((*ptr >= '0') && (*ptr <= '9')) { if(OK > 1) { *(float *)tt->varptr = *(float *)tt->varptr + (float)(*ptr - '0')/OK; OK *= 10; } else *(float *)tt->varptr = 10 * *(float *)tt->varptr + (*ptr - '0'); } else OK = 0; } ptr++; break; default: return(-1); } /* Variable name or skipped value */ else ptr++; } free(buffer); free(tmpbuf); return(num); } /* parser */ static int cgi_get(void) { char *ptr; int i; struct { char *name; char **varp; } strings[] = { {"SERVER_SOFTWARE", &cgi.SERVER_SOFTWARE}, {"SERVER_NAME", &cgi.SERVER_NAME}, {"GATEWAY_INTERFACE", &cgi.GATEWAY_INTERFACE}, {"SERVER_PROTOCOL", &cgi.SERVER_PROTOCOL}, {"REQUEST_METHOD", &cgi.REQUEST_METHOD}, {"HTTP_ACCEPT", &cgi.HTTP_ACCEPT}, {"PATH_INFO", &cgi.PATH_INFO}, {"PATH_TRANSLATED", &cgi.PATH_TRANSLATED}, {"SCRIPT_NAME", &cgi.SCRIPT_NAME}, {"QUERY_STRING", &cgi.QUERY_STRING}, {"REMOTE_HOST", &cgi.REMOTE_HOST}, {"REMOTE_ADDR", &cgi.REMOTE_ADDR}, {"AUTH_TYPE", &cgi.AUTH_TYPE}, {"REMOTE_USER", &cgi.REMOTE_USER}, {"CONTENT_TYPE", &cgi.CONTENT_TYPE}, {NULL, NULL} }; /* Numerical variables */ ptr = getenv("SERVER_PORT"); cgi.SERVER_PORT = (ptr? atoi(ptr): 0); ptr = getenv("CONTENT_LENGTH"); cgi.CONTENT_LENGTH = (ptr? atoi(ptr): 0); /* String variables */ for(i = 0; strings[i].name; i++) { ptr = getenv(strings[i].name); if(!ptr) { *strings[i].varp = NULL; continue; } if(! (*strings[i].varp = (char *)malloc(strlen(ptr) + 1))) return(1); strcpy(*strings[i].varp, ptr); } return(0); } /* cgi_get */