/* CGI:IRC C Helper CGI * Copyright (c) David Leadbeater 2002-2007 * Released Under the GNU GPLv2 or Later * NO WARRANTY - See GNU GPL for more * $Id: 3cc9101e199095f574c9bd8b2c53f0f9042eeae9 $ */ /* To compile: cc -O2 -o client.cgi client.c */ /* Add -lsocket on Solaris */ #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-" /****************************************************************************** * Stralloc (from libowfat(-ish)) * If you'd rather use dietlibc/libowfat: * diet -Os gcc -include stralloc.h -o client.cgi client.c -lowfat */ #ifndef STRALLOC_H typedef struct stralloc { char* s; unsigned long int len; unsigned long int a; } stralloc; int stralloc_ready(stralloc *sa,unsigned long int len) { register int wanted=len+(len>>3)+30; /* heuristic from djb */ if(!sa->s || sa->as,wanted))) return 0; sa->a=wanted; sa->s=tmp; } return 1; } int stralloc_readyplus(stralloc *sa,unsigned long len) { if (sa->s) { if (sa->len + len < len) return 0; /* catch integer overflow */ return stralloc_ready(sa,sa->len+len); } else return stralloc_ready(sa,len); } int stralloc_catb(stralloc *sa,const char *buf,unsigned long int len) { if (stralloc_readyplus(sa,len)) { memcpy(sa->s+sa->len,buf,len); sa->len+=len; return 1; } return 0; } int stralloc_cats(stralloc *sa,const char *buf) { return stralloc_catb(sa,buf,strlen(buf)); } int stralloc_cat(stralloc *sa,stralloc *sa2) { return stralloc_catb(sa,sa2->s,sa2->len); } int stralloc_append(stralloc *sa,const char *in) { if (stralloc_readyplus(sa,1)) { sa->s[sa->len]=*in; ++sa->len; return 1; } return 0; } #define stralloc_0(sa) stralloc_append(sa,"") #endif /******************************************************************************/ int unix_connect(stralloc *where); int error(char *error); void readinput(stralloc *); void get_rand(stralloc *, stralloc *); void get_cookie(stralloc *); int main(void) { int fd, sz; char tmp[2048]; stralloc params = {0}, random = {0}, cookie = {0}; readinput(¶ms); if(!params.len) error("No input found"); stralloc_0(¶ms); get_rand(¶ms, &random); if(!random.len) error("Random value not found"); params.len--; get_cookie(&cookie); if(cookie.len) { stralloc_cats(¶ms, "&COOKIE="); stralloc_cat(¶ms, &cookie); } fd = unix_connect(&random); send(fd, params.s, params.len, 0); send(fd, "\n", 1, 0); while((sz = read(fd, tmp, sizeof tmp)) > 0) { write(STDOUT_FILENO, tmp, sz); } return 0; } int error(char *error) { puts("Content-type: text/html\nStatus: 500\n"); puts("An error occurred:"); puts(error); exit(1); } void readinput(stralloc *input) { char *method = getenv("REQUEST_METHOD"); if(!method) return; if(strcmp(method, "GET") == 0) { char *query = getenv("QUERY_STRING"); if(query) stralloc_cats(input, query); }else if(strcmp(method, "POST") == 0) { int length; char *ctlength = getenv("CONTENT_LENGTH"); size_t sz; if(!ctlength) return; length = atoi(ctlength); /* Hopefully noone will need to send more than 5KB */ if(length <= 0 || length > (1024*5)) return; stralloc_ready(input, length); sz = read(STDIN_FILENO, input->s, length); if(sz <= 0) return; input->len = sz; } } void get_rand(stralloc *params, stralloc *random) { char *ptr = strstr(params->s, "R="); if(!ptr) return; ptr += 2; while(ptr < params->s + params->len) { if(!isalpha((unsigned char)*ptr) && !isdigit((unsigned char)*ptr)) break; stralloc_append(random, ptr++); } } void get_cookie(stralloc *cookie) { char *httpcookie; char *sptr, *end_ptr; httpcookie = getenv("HTTP_COOKIE"); if(!httpcookie) return; #define COOKIE_NAME "cgiircauth=" sptr = strstr(httpcookie, COOKIE_NAME); if(sptr == NULL) return; sptr += strlen(COOKIE_NAME); if(!*sptr) return; end_ptr = strchr(sptr, ';'); if(end_ptr == NULL) end_ptr = sptr + strlen(sptr) - 1; stralloc_catb(cookie, sptr, 1 + end_ptr - sptr); } #ifndef SUN_LEN #define SUN_LEN(x) (sizeof(*(x)) - sizeof((x)->sun_path) + strlen((x)->sun_path)) #endif int unix_connect(stralloc *where) { stralloc filename = {0}, errmsg = {0}; struct sockaddr_un saddr; int sock; stralloc_cats(&filename, TMPLOCATION); stralloc_cat(&filename, where); stralloc_cats(&filename, "/sock"); stralloc_0(&filename); sock = socket(AF_UNIX, SOCK_STREAM, 0); if(sock == -1) error("socket() error"); saddr.sun_family = AF_UNIX; strncpy(saddr.sun_path, filename.s, sizeof(saddr.sun_path)); saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0'; if(connect(sock, (struct sockaddr *)&saddr, SUN_LEN(&saddr)) == -1) { stralloc_cats(&errmsg, "connect(): "); stralloc_cats(&errmsg, strerror(errno)); stralloc_0(&errmsg); error(errmsg.s); } return sock; }