Skip to content

Commit

Permalink
Near total rewrite, the old version sucked.
Browse files Browse the repository at this point in the history
  • Loading branch information
dgl committed May 3, 2006
1 parent 22748ec commit 1a9df9a
Showing 1 changed file with 165 additions and 110 deletions.
275 changes: 165 additions & 110 deletions client.c
Expand Up @@ -2,8 +2,9 @@
* Copyright (c) David Leadbeater 2002-2006
* Released Under the GNU GPLv2 or Later
* NO WARRANTY - See GNU GPL for more
* $Id: client.c,v 1.13 2006/04/30 20:24:41 dgl Exp $
* $Id: client.c,v 1.14 2006/05/03 06:51:16 dgl Exp $
*/
/* To compile: cc -O2 -o client.cgi client.c */

#include <stdio.h>
#include <stdlib.h>
Expand All @@ -18,149 +19,203 @@
/* Change this to the tmpfile path set in the CGI:IRC Config */
#define TMPLOCATION "/tmp/cgiirc-"

int unix_connect(char *where);
/******************************************************************************
* 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->a<len) {
register char* tmp;
if (!(tmp=realloc(sa->s,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);
int readinput(char *params, size_t len);
int get_rand(char *params, char *rand, size_t len);
int get_cookie(char *cookie);
void readinput(stralloc *);
void get_rand(stralloc *, stralloc *);
void get_cookie(stralloc *);

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];
char cookie[100];

if(!readinput(params, sizeof params)) error("No input found\n");
if(!get_rand(params, rand, sizeof 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, sizeof tmp2);
snprintf(params, sizeof params, "COOKIE=%s&%s", cookie, tmp2);
int fd, sz;
char tmp[2048];
stralloc params = {0}, random = {0}, cookie = {0};

readinput(&params);

if(!params.len)
error("No input found");

stralloc_0(&params);

get_rand(&params, &random);

if(!random.len)
error("Random value not found");

params.len--;

get_cookie(&cookie);

if(cookie.len) {
stralloc_cats(&params, "&COOKIE=");
stralloc_cat(&params, &cookie);
}

fd = unix_connect(rand);
send(fd, params, strlen(params), 0);
fd = unix_connect(&random);
send(fd, params.s, params.len, 0);
send(fd, "\n", 1, 0);

while(read(fd, tmp, sizeof tmp) > 0) {
printf("%s",tmp);
while((sz = read(fd, tmp, sizeof tmp)) > 0) {
write(STDOUT_FILENO, tmp, sz);
}

return 1;
return 0;
}

int error(char *error) {
printf("Content-type: text/html\n\n");
printf("An error occurred: %s\n",error);
puts("Content-type: text/html\n");
puts("An error occurred:");
puts(error);
exit(1);
}

int readinput(char *params, size_t len) {
char request[10];

if(!getenv("REQUEST_METHOD")) return 0;
strncpy(request, getenv("REQUEST_METHOD"), 9);
request[9] = 0;
if(!strlen(request)) return 0;
void readinput(stralloc *input) {
char *method = getenv("REQUEST_METHOD");
if(!method) return;

if(strncmp(request, "GET", 3) == 0) {
strncpy(params, getenv("QUERY_STRING"), 2048);
params[len - 1] = 0;
if(!strlen(params)) return 0;
return 1;
}else if(strncmp(request, "POST", 4) == 0) {
if(strcmp(method, "GET") == 0) {
char *query = getenv("QUERY_STRING");
if(query)
stralloc_cats(input, query);
}else if(strcmp(method, "POST") == 0) {
int length;
if(!getenv("CONTENT_LENGTH")) return 0;
length = atoi(getenv("CONTENT_LENGTH"));
if(!length || length == 0) return 0;
length = (length >= len ? len - 1 : length);
fread(params, length, 1, stdin);
params[length] = 0;
return 1;
}else{
return 0;
char *ctlength = getenv("CONTENT_LENGTH");
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);
size_t sz = read(STDIN_FILENO, input->s, length);
if(sz <= 0) return;
input->len = sz;
}
}

int get_rand(char *params, char *rand, size_t len) {
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 > len - 2) break;
if(isalpha(*ptr) || isdigit(*ptr)) {
rand[i] = *ptr;
i++;
}
}else if(*ptr == 'R' && *(++ptr) == '=') {
r = 1;
}
}
rand[i] = 0;
void get_rand(stralloc *params, stralloc *random) {
char *ptr = strstr(params->s, "R=");

if(r == 1 && strlen(rand)) return 1;
return 0;
if(!ptr)
return;

ptr += 2;

while(ptr < params->s + params->len) {
if(!isalpha(*ptr) && !isdigit(*ptr))
break;
stralloc_append(random, ptr++);
}
}

int get_cookie(char *cookie) {
char ctmp[1024];
void get_cookie(stralloc *cookie) {
char *httpcookie;
char *sptr, *end_ptr;
int i;

if(!getenv("HTTP_COOKIE")) return 0;
strncpy(ctmp, getenv("HTTP_COOKIE"), sizeof ctmp - 1);

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(sptr < end_ptr && *sptr != ';') {
cookie[i] = *sptr;
sptr++;
i++;
}
cookie[i] = '\0';
return 1;

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);
}

int unix_connect(char *where) {
/*size_t size;*/
#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, len;
char filename[100], errmsg[100];
int sock;

len = strlen(TMPLOCATION) + strlen(where) + 6;
if(len > 100) error("Too long");
snprintf(filename, len, "%s%s/sock", TMPLOCATION, where);
filename[len] = 0;
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\n");
if(sock == -1) error("socket() error");

saddr.sun_family = AF_UNIX;
strcpy(saddr.sun_path, filename);
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) {
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);
}
stralloc_cats(&errmsg, "connect(): ");
stralloc_cats(&errmsg, strerror(errno));
stralloc_0(&errmsg);
error(errmsg.s);
}

return sock;
Expand Down

0 comments on commit 1a9df9a

Please sign in to comment.