/* CGI:IRC C Helper CGI * Copyright (c) David Leadbeater 2002 * Released Under the GNU GPLv2 or Later * NO WARRANTY - See GNU GPL for more * $Id: client.c,v 1.9 2002/05/11 14:52:18 dgl Exp $ */ #include #include #include #include #include #include #include #include #include /* Change this to the tmpfile path set in the CGI:IRC Config */ #define TMPLOCATION "/tmp/cgiirc-" int unix_connect(char *where); int error(char *error); int readinput(char *params); int get_rand(char *params, char *rand); int get_cookie(char *cookie); int main(void) { int fd; char params[2048]; /* Keep input in here */ char rand[50]; /* Random value - used for the socket location */ char tmp[2148]; /* I decided to stop adding comments after here */ char cookie[100]; if(!readinput(params)) error("No input found\n"); if(!get_rand(params, rand)) error("Random Value not found\n"); if(get_cookie(cookie)) { char tmp2[2148]; /* I'm sure there's a better way of doing this.. */ strncpy(tmp2, params, 2147); snprintf(params, 2148, "COOKIE=%s&%s", cookie, tmp2); } fd = unix_connect(rand); send(fd, params, strlen(params), 0); send(fd, "\n", 1, 0); while(read(fd, tmp, 2048) > 0) { printf("%s",tmp); } return 1; } int error(char *error) { printf("Content-type: text/html\n\n"); printf("An error occured: %s\n",error); exit(1); } int readinput(char *params) { char request[10]; if(!getenv("REQUEST_METHOD")) return 0; strncpy(request, getenv("REQUEST_METHOD"), 9); request[9] = 0; if(!strlen(request)) return 0; if(strncmp(request, "GET", 3) == 0) { strncpy(params, getenv("QUERY_STRING"), 2048); params[2048] = 0; if(!strlen(params)) return 0; return 1; }else if(strncmp(request, "POST", 4) == 0) { int length; if(!getenv("CONTENT_LENGTH")) return 0; length = atoi(getenv("CONTENT_LENGTH")); if(!length || length == 0) return 0; fread(params, length > 2048 ? 2048 : length, 1, stdin); params[length] = 0; return 1; }else{ return 0; } } int get_rand(char *params, char *rand) { char *ptr, *end_ptr; int r = 0, i = 0; ptr = params; end_ptr = ptr + strlen(ptr); for(;ptr < end_ptr; ptr++) { if(r == 1) { if(*ptr == '&') break; if(i > 48) break; if(isalpha(*ptr) || isdigit(*ptr)) { rand[i] = *ptr; i++; } }else if(*ptr == 'R' && *(++ptr) == '=') { r = 1; } } rand[i] = 0; if(r == 1 && strlen(rand)) return 1; return 0; } int get_cookie(char *cookie) { char ctmp[1024]; char *sptr, *end_ptr; int i; if(!getenv("HTTP_COOKIE")) return 0; strncpy(ctmp, getenv("HTTP_COOKIE"), 1023); sptr = strstr(ctmp, "cgiircauth="); if(sptr == NULL) return 0; if(strlen(sptr) < 12) return 0; sptr += 11; end_ptr = sptr + (strlen(sptr) < 99 ? strlen(sptr) : 99); i = 0; while((int)sptr < (int)end_ptr && *sptr != ';') { cookie[i] = *sptr; sptr++; i++; } cookie[i] = '\0'; return 1; } int unix_connect(char *where) { /*size_t size;*/ struct sockaddr_un saddr; int sock, len; char filename[100], errmsg[100]; len = strlen(TMPLOCATION) + strlen(where) + 6; if(len > 100) error("Too long"); snprintf(filename, len, "%s%s/sock", TMPLOCATION, where); filename[len] = 0; sock = socket(AF_UNIX, SOCK_STREAM, 0); if(sock == -1) error("socket() error\n"); saddr.sun_family = AF_UNIX; strcpy(saddr.sun_path, filename); if(connect(sock, (struct sockaddr *)&saddr, SUN_LEN(&saddr)) == -1) { switch(errno) { case EACCES: error("Access Denied in connect()\n"); case ECONNREFUSED: error("Connection refused in connect()\n"); case ENOENT: error("No such file in connect()\n"); default: snprintf(errmsg, 99, "Unhandled error in connect(): %s\n", strerror(errno)); error(errmsg); } } return sock; }