/* @(#)$Id: http.c,v 1.31 2000/10/26 03:00:35 seks Exp $ */ /* Undernet Channel Service (X) * Copyright (C) 1995-2002 Robin Thellend * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * The author can be contact by email at * * Please note that this software is unsupported and mostly * obsolete. It was replaced by GNUworld/CMaster. See * http://gnuworld.sourceforge.net/ for more information. */ #include "h.h" #ifdef DOHTTP #include void cold_save_one(RegUser * reg); struct http_deny { struct in_addr addr; struct http_deny *next; } *HttpDeny = NULL; #ifdef DEBUG static void show_list(void) { register http_socket *tmp; register http_file_pipe *fpipe; printf("http fd list: "); for (tmp = HttpList; tmp != NULL; tmp = tmp->next) { printf("%d ", tmp->fd); switch (tmp->status) { case HTTP_ERROR: printf("(ERROR) "); break; case HTTP_LISTEN: printf("(LISTEN) "); break; case HTTP_ACTIVE: printf("(ACTIVE) "); break; case HTTP_ENDING: printf("(ENDING) "); break; case HTTP_RECV_POST: printf("(POST) "); break; case HTTP_PIPE: printf("(PIPE) "); break; default: printf("(----) "); break; } } printf("\nFiles: "); for (fpipe = FilePipes; fpipe != NULL; fpipe = fpipe->next) { printf("%d (FILE->%d) ", fpipe->fd, fpipe->hsock->fd); } printf("\n"); } #endif void http_log(char *fmt,...) { char buffer[1024], date[80]; va_list ap; int fd; strcpy(date, ctime(&now)); *strchr(date, '\n') = '\0'; va_start(ap, fmt); alarm(2); if ((fd = open(HTTP_LOG, O_WRONLY | O_CREAT | O_APPEND, 0600)) >= 0) { alarm(0); sprintf(buffer, "%s: ", date); alarm(2); write(fd, buffer, strlen(buffer)); alarm(0); vsprintf(buffer, fmt, ap); alarm(2); write(fd, buffer, strlen(buffer)); write(fd, "\n", 1); alarm(0); close(fd); } alarm(0); va_end(ap); } void quote_html(char *in, char *out) { do { if (*in == '<') { out[0] = '&'; out[1] = 'l'; out[2] = 't'; out[3] = ';'; out += 4; } else if (*in == '>') { out[0] = '&'; out[1] = 'g'; out[2] = 't'; out[3] = ';'; out += 4; } else if (*in == '&') { out[0] = '&'; out[1] = 'a'; out[2] = 'm'; out[3] = 'p'; out[4] = ';'; out += 5; } else { out[0] = in[0]; out++; } } while (*(in++) != '\0'); } static http_socket *new_struct(void) { register http_socket *tmp; tmp = (http_socket *) MALLOC(sizeof(http_socket)); #ifdef DEBUG printf("New http_socket struct at %p\n", tmp); #endif tmp->next = NULL; tmp->inbuf = NULL; tmp->outbuf = NULL; tmp->hook = NULL; tmp->fd = -1; tmp->status = -1; tmp->dbio = 0; tmp->TS = now; tmp->since = now; return tmp; } static void add_struct(http_socket * new) { new->next = HttpList; HttpList = new; #ifdef DEBUG show_list(); #endif } void remove_httpsock(http_socket * old) { extern void chat_quit(struct http_socket *hsock); register http_socket *tmp = HttpList; if (old->dbio) return; /* can't free yet.. there are other pointers * the that structure */ if (old->inbuf) zap_buffer(&old->inbuf); if (old->outbuf) zap_buffer(&old->outbuf); if (old->hook) free(old->hook); if (tmp == old) { HttpList = HttpList->next; free(old); } else { while (tmp->next != old) { tmp = tmp->next; if (tmp == NULL) { http_log("ERROR: remove_struct() tmp->next==NULL"); return; } } tmp->next = old->next; free(old); } #ifdef DEBUG show_list(); #endif } void open_http(void) { register http_socket *new; struct sockaddr_in myaddr; int opt = 1; new = new_struct(); new->fd = socket(AF_INET, SOCK_STREAM, 0); if (new->fd < 0) { http_log("ERROR: open_http() socket() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); free(new); return; } #ifdef SO_REUSEADDR if (setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt)) < 0) { http_log("ERROR: open_http() setsockopt() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); close(new->fd); free(new); return; } #endif if (fcntl(new->fd, F_SETFL, O_NONBLOCK) < 0) { http_log("ERROR: open_http() fcntl() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); close(new->fd); free(new); return; } memset(&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(HTTP_PORT); #ifdef BINDADDR myaddr.sin_addr.s_addr = inet_addr(BINDADDR); #else myaddr.sin_addr.s_addr = htonl(INADDR_ANY); #endif if (bind(new->fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { http_log("ERROR: open_http() bind() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); close(new->fd); free(new); /*return; */ /* Can't bind to local port.. exit! */ exit(0); } if (listen(new->fd, 10) < 0) { http_log("ERROR: open_http() listen() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); close(new->fd); free(new); return; } new->status = HTTP_LISTEN; add_struct(new); } void read_http_conf(char *source) { register struct http_deny *tmp; char buffer[80], ip[80], global[] = "*"; FILE *fp; if (*source && Access(global, source) < MASTER_ACCESS) { ReplyNotAccess(source, global); return; } while ((tmp = HttpDeny) != NULL) { HttpDeny = HttpDeny->next; free(tmp); } if ((fp = fopen(HTTP_DENY, "r")) != NULL) { while (fgets(buffer, 79, fp) != NULL) { if (*buffer == '#' || *buffer == '\n' || *buffer == '\0') continue; sscanf(buffer, "%s\n", ip); tmp = (struct http_deny *)MALLOC(sizeof(struct http_deny)); tmp->addr.s_addr = inet_addr(ip); tmp->next = HttpDeny; HttpDeny = tmp; } fclose(fp); if (*source) notice(source, "done."); } else { if (*source) notice(source, "Can't open file: " HTTP_DENY); } } static int check_http_deny(struct in_addr *addr) { char tmp[5]; register struct http_deny *scan = HttpDeny; tmp[4] = '\0'; while (scan != NULL) { /* Not sure which one is faster... */ /* tmp[0]=((char *)&(scan->addr.s_addr))[0]; */ /* tmp[1]=((char *)&(scan->addr.s_addr))[1]; */ /* tmp[2]=((char *)&(scan->addr.s_addr))[2]; */ /* tmp[3]=((char *)&(scan->addr.s_addr))[3]; */ memcpy((void *)tmp, (void *)&(scan->addr.s_addr), 4); if (!memcmp((void *)tmp, (void *)&(addr->s_addr), strlen(tmp))) return 1; scan = scan->next; } return 0; } void http_accept(int sock) { register http_socket *new; int size; struct in_addr addr; new = new_struct(); size = sizeof(new->peer); new->fd = accept(sock, (struct sockaddr *)&new->peer, &size); if (size != sizeof(new->peer)) { http_log("WARNING: uh huh.. size changed in accept()!" " %d != %d", size, (int)sizeof(new->peer)); } if (new->fd < 0) { http_log("ERROR: http_accept() accept() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); free(new); return; } if (fcntl(new->fd, F_SETFL, O_NONBLOCK) < 0) { http_log("ERROR: open_accept() fcntl() failed!"); http_log("%d: %s", errno, sys_errlist[errno]); close(new->fd); free(new); return; } new->status = HTTP_ACTIVE; add_struct(new); addr.s_addr = new->peer.sin_addr.s_addr; if (check_http_deny(&new->peer.sin_addr)) { http_log("Connection refused (%s)", inet_ntoa(addr)); sendto_http(new, HTTP_HEADER, "You're banned!"); sendto_http(new, HTTP_BODY); sendto_http(new, "

Due to abuse from users of your site " "(%s), connections are no longer accepted.

\n", inet_ntoa(addr)); sendto_http(new, "
%s\n\n", HTTP_FOOTER); new->status = HTTP_ENDING; return; } http_log("[%d] HTTP CONNECTION (%s)", new->fd, inet_ntoa(addr)); if (new->fd >= MAX_CONNECTIONS) { new->status = HTTP_ENDING; sendto_http(new, HTTP_HEADER "\n", "Too many connections!"); http_log("ERROR: reached MAX_CONNECTIONS!!"); } } static void http_userlist_callback(int *fd, off_t off, int action, void *hook1, void *hook2, dbuser * dbu, int count) { time_t t; int days, hours, mins, secs; if (dbu == NULL) { if (count == 0) sendto_http((http_socket *) hook1, "Userlist is empty on %s!

\n", mynick); sendto_http((http_socket *) hook1, "


%s\n", HTTP_FOOTER); sendto_http((http_socket *) hook1, "\n"); ((http_socket *) hook1)->status = HTTP_ENDING; ((http_socket *) hook1)->dbio = 0; free(hook2); } else { sendto_http((http_socket *) hook1, "USER: %s (%s) ACCESS: %d
\n", dbu->nick, dbu->match, dbu->access); sendto_http((http_socket *) hook1, "CHANNEL: %s -- AUTOOP: %s
\n", dbu->channel, (dbu->flags & UFL_AUTOOP) ? "ON" : "OFF"); if (dbu->suspend > now) { sendto_http((http_socket *) hook1, "SUSPEND EXP: %s
\n", time_remaining(dbu->suspend - now)); } t = now - dbu->lastseen; days = (int)t / 86400; t %= 86400; hours = (int)t / 3600; t %= 3600; mins = (int)t / 60; t %= 60; secs = (int)t; if (days > 0) sendto_http((http_socket *) hook1, "LAST SEEN: %d days, %02d:%02d:%02d ago
\n", days, hours, mins, secs); else sendto_http((http_socket *) hook1, "LAST SEEN: %02d:%02d:%02d ago
\n", hours, mins, secs); if (dbu->modif[0] == '\0') sendto_http((http_socket *) hook1, "LAST MODIF: unknown

\n"); else sendto_http((http_socket *) hook1, "LAST MODIF: %s

\n", dbu->modif); } } static void http_show_userlist(http_socket * hsock, char *channel, char *protocol) { char date[80]; struct tm *timeptr; int *hook; timeptr = gmtime(&now); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "HTTP/1.0 200 Document follows%c", 10); sendto_http(hsock, "Date: %s%c", date, 10); sendto_http(hsock, "Server: CS/1.0%c", 10); sendto_http(hsock, "Content-type: text/html%c%c", 10, 10); sendto_http(hsock, HTTP_HEADER, "User list"); sendto_http(hsock, HTTP_BODY); sendto_http(hsock, "\n

User list for channel %s

\n", channel); sendto_http(hsock, "%s

\n", date); if (!strcmp(channel, "*")) { sendto_http(hsock, "Userlist is empty on %s!

\n", mynick); sendto_http(hsock, "


%s\n", HTTP_FOOTER); sendto_http(hsock, "\n"); hsock->status = HTTP_ENDING; hsock->dbio = 0; } else { if (!strcmp(channel, "secret_admin_list")) { strcpy(channel, "*"); /* Enable us to see the * userlist via the web */ } hook = (int *)malloc(sizeof(int)); *hook = 0; db_fetch(channel, DBGETALLCMP, "", NULL, 0, hsock, hook, http_userlist_callback); hsock->dbio = 1; } } static void http_show_banlist(http_socket * hsock, char *channel, char *protocol) { char date[80]; register ShitUser *curr; struct tm *timeptr; int found = 0; timeptr = gmtime(&now); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "HTTP/1.0 200 Document follows%c", 10); sendto_http(hsock, "Date: %s%c", date, 10); sendto_http(hsock, "Server: CS/1.0%c", 10); sendto_http(hsock, "Content-type: text/html%c%c", 10, 10); sendto_http(hsock, HTTP_HEADER, "Ban list"); sendto_http(hsock, HTTP_BODY); sendto_http(hsock, "

Ban list for channel %s

\n", channel); sendto_http(hsock, "%s

\n", date); sendto_http(hsock, HTTP_BAN_DISCLAIMER); curr = ShitList[sl_hash(channel)]; while (curr) { if (!strcasecmp(channel, curr->channel)) { found++; sendto_http(hsock, "%s %s Level: %d
\n", curr->channel, curr->match, curr->level); sendto_http(hsock, "ADDED BY: %s (%s)
\n", curr->from, (*curr->reason) ? curr->reason : "No reason given"); timeptr = gmtime(&curr->time); sprintf(date, "%sUCT", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "SINCE: %s
\n", date); sendto_http(hsock, "EXP: %s

\n", time_remaining(curr->expiration - now)); } curr = curr->next; } if (!found) { sendto_http(hsock, "Ban list is empty!

\n"); } sendto_http(hsock, "


%s\n", HTTP_FOOTER); sendto_http(hsock, "\n"); hsock->status = HTTP_ENDING; } static void http_show_list(http_socket * hsock, char *keylist) { char date[80], top[512], *tok[16]; register adefchan *def; int found = 0, i = 0; struct tm *timeptr; timeptr = gmtime(&now); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "HTTP/1.0 200 Document follows\n\n"); sendto_http(hsock, HTTP_HEADER, "Channel list"); sendto_http(hsock, HTTP_BODY); if (*keylist) { sendto_http(hsock, "

Channel search result for [%s]

\n", keylist); } else { sendto_http(hsock, "

Channel search result: Whole list

\n"); } sendto_http(hsock, "%s

\n", date); tok[0] = strtok(keylist, " "); while (i < 15 && (tok[++i] = strtok(NULL, " ")) != NULL); tok[i] = NULL; def = DefChanList; while (def) { if ((!*keylist || key_match(def->name, tok) || key_match(def->topic, tok)) && !IsSet(def->name, 's', "") && !IsSet(def->name, 'p', "")) { found = 1; quote_html(def->topic, top); if (*def->url) sendto_http(hsock, "%s %s
\n", def->url, def->name, top); else sendto_http(hsock, "%s %s
\n", def->name, top); } def = def->next; } if (!found) { sendto_http(hsock, "No match!

\n"); } sendto_http(hsock, "


%s\n", HTTP_FOOTER); hsock->status = HTTP_ENDING; } static void http_chaninfo_callback(int *fd, off_t off, int action, void *hook1, void *hook2, dbuser * dbu, int count) { register adefchan *def; time_t t; if (count == 1 && dbu != NULL) { sendto_http((http_socket *) hook1, "%s is registered by:

\n", (char *)hook2); } if (dbu == NULL) { if (count == 0) { sendto_http((http_socket *) hook1, "Channel %s is not registered", (char *)hook2); } else { def = DefChanList; while (def && strcasecmp((char *)hook2, def->name)) def = def->next; if (def) { char top[512]; quote_html(def->topic, top); sendto_http((http_socket *) hook1, "Desc: %s
\n", top); sendto_http((http_socket *) hook1, "URL: %s
\n", def->url, def->url); } } sendto_http((http_socket *) hook1, "


%s\n", HTTP_FOOTER); ((http_socket *) hook1)->status = HTTP_ENDING; ((http_socket *) hook1)->dbio = 0; free(hook2); } else if (dbu->access >= 500) { t = now - dbu->lastseen; sendto_http((http_socket *) hook1, "%s (%s) last seen: %s ago
\n", dbu->nick, dbu->match, time_remaining(t)); } } static void http_show_chaninfo(http_socket * hsock, char *channel) { char date[80], *hook; struct tm *timeptr; timeptr = gmtime(&now); sprintf(date, "%sUCT", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, HTTP_HEADER, "Channel information"); sendto_http(hsock, HTTP_BODY); sendto_http(hsock, "

Channel information

\n"); sendto_http(hsock, "%s

", date); hook = (char *)malloc(strlen(channel) + 1); strcpy(hook, channel); db_fetch(channel, DBGETALLCMP, "", NULL, 0, hsock, hook, http_chaninfo_callback); hsock->dbio = 1; } static void http_show_whois(http_socket * hsock, char *nick) { register aluser *user; register achannelnode *chan; register auser *usr; char date[80]; struct tm *timeptr; timeptr = gmtime(&now); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; #ifdef DEBUG printf("HTTP WHOIS: \"%s\"\n", nick); #endif sendto_http(hsock, HTTP_HEADER, "WHOIS"); sendto_http(hsock, HTTP_BODY); sendto_http(hsock, "

WHOIS Information

\n"); sendto_http(hsock, "%s

\n", date); user = ToLuser(nick); if (user == NULL) { sendto_http(hsock, "*** %s: No such nick

\n", nick); } else { sendto_http(hsock, "*** %s is (%s@%s)
\n", user->nick, user->username, user->site); chan = user->channel; if (chan != NULL) { sendto_http(hsock, "*** on channels: "); while (chan != NULL) { if (!IsSet(chan->N->name, 's', "") && !IsSet(chan->N->name, 'p', "")) { usr = ToUser(chan->N->name, nick); if (usr->chanop) sendto_http(hsock, "@%s ", chan->N->name); else sendto_http(hsock, "%s ", chan->N->name); } chan = chan->next; } sendto_http(hsock, "
\n"); } sendto_http(hsock, "*** on irc via server %s
\n", user->server->name); if (user->mode & LFL_ISOPER) { sendto_http(hsock, "*** %s is an IRC Operator
\n", user->nick); } } sendto_http(hsock, "


%s\n", HTTP_FOOTER); hsock->status = HTTP_ENDING; } static int get_file_pipe(http_socket * hsock, int fd) { register http_file_pipe *new; new = (http_file_pipe *) malloc(sizeof(http_file_pipe)); if (new == NULL) return -1; new->fd = fd; new->hsock = hsock; new->next = FilePipes; FilePipes = new; new->hsock->status = HTTP_PIPE; #ifdef DEBUG show_list(); #endif return 0; } void destroy_file_pipe(http_file_pipe * old) { register http_file_pipe **tmp = &FilePipes; while (*tmp != NULL && *tmp != old) { tmp = &(*tmp)->next; } if (*tmp != NULL) { *tmp = old->next; free(old); } #ifdef DEBUG show_list(); #endif } void readfrom_file(http_file_pipe * fpipe) { char buffer[2048]; int length; if (fpipe->hsock->status == HTTP_ERROR) { close(fpipe->fd); fpipe->fd = -1; destroy_file_pipe(fpipe); return; } if ((length = read(fpipe->fd, buffer, 2047)) > 0) { copy_to_buffer(&fpipe->hsock->outbuf, buffer, length); } else if (length == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) { fpipe->hsock->status = HTTP_ENDING; close(fpipe->fd); fpipe->fd = -1; destroy_file_pipe(fpipe); } return; } static void http_send_file(http_socket * hsock, char *fname, char *protocol) { char file[256], date[80]; struct stat sbuf; struct tm *timeptr; register char *ptr; int fd, cnt; int tmpfd; #ifdef DEBUG printf("fname= \"%s\"\n", fname); #endif cnt = 0; for (ptr = fname; *ptr; ptr++) { if (*ptr == '.') cnt++; if ((!isalnum(*ptr) && !strchr("./_-", *ptr)) || cnt > 1) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } } sprintf(file, "HTTP/%s", fname); if ((fd = open(file, O_RDONLY)) < 0 || fstat(fd, &sbuf) < 0 || fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { hsock->status = HTTP_ERROR; if (fd >= 0) close(fd); if (hsock->fd >= 0) { close(hsock->fd); hsock->fd = -1; } return; } sprintf(file, "HTTP/%s.#", fname); if ((tmpfd = open(file, O_RDWR | O_CREAT, 0600)) >= 0) { char buf[80] = ""; cnt = 0; if (read(tmpfd, buf, 79) > 0) { sscanf(buf, "%d", &cnt); lseek(tmpfd, 0L, SEEK_SET); } sprintf(buf, "%d\n", ++cnt); write(tmpfd, buf, strlen(buf)); close(tmpfd); } sendto_http(hsock, "HTTP/1.0 200 Document follows%c", 10); timeptr = gmtime(&now); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "Date: %s%c", date, 10); sendto_http(hsock, "Server: CS/1.0%c", 10); sendto_http(hsock, "Mime-version: 1.0%c", 10); if (strstr(fname, ".gif")) { sendto_http(hsock, "Content-type: image/gif%c", 10); } else if (strstr(fname, ".jpg")) { sendto_http(hsock, "Content-type: image/jpeg%c", 10); } else if (strstr(fname, ".html")) { sendto_http(hsock, "Content-type: text/html%c", 10); } else if (strstr(fname, ".txt")) { sendto_http(hsock, "Content-type: text/plain%c", 10); } else { sendto_http(hsock, "Content-type: */*%c", 10); } timeptr = gmtime(&sbuf.st_mtime); sprintf(date, "%sUTC", asctime(timeptr)); *strchr(date, '\n') = ' '; sendto_http(hsock, "Last-modified: %s%c", date, 10); sendto_http(hsock, "Content-length: %ld\n\n", sbuf.st_size); if (get_file_pipe(hsock, fd) < 0) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; } } static void send_http_error(http_socket * hsock) { sendto_http(hsock, HTTP_HEADER, "ERROR"); sendto_http(hsock, HTTP_BODY); sendto_http(hsock, "

Error in request

\n"); sendto_http(hsock, "


%s\n", HTTP_FOOTER); } static void parse_get(http_socket * hsock, char *path, char *protocol) { extern void http_show_help(http_socket *, char *); char channel[80]; register char *ptr; #ifdef DEBUG printf("GET: %s\n", path); #endif if (*path != '/') { send_http_error(hsock); hsock->status = HTTP_ENDING; return; } if ((ptr = strchr(path + 1, '/')) == NULL) { ptr = path + strlen(path); } else { *(ptr++) = '\0'; } sprintf(channel, "#%s", ptr); if (!strcasecmp(path + 1, "USERLIST")) { http_show_userlist(hsock, channel, protocol); } else if (!strcasecmp(path + 1, "BANLIST")) { http_show_banlist(hsock, channel, protocol); } else if (!strcasecmp(path + 1, "CHANINFO")) { http_show_chaninfo(hsock, channel); } else if (!strcasecmp(path + 1, "LIST")) { http_show_list(hsock, channel); } else if (!strcasecmp(path + 1, "WHOIS")) { http_show_whois(hsock, ptr); } else if (!strcasecmp(path + 1, "FILES")) { http_send_file(hsock, ptr, protocol); } else if (!strcasecmp(path + 1, "HELP")) { http_show_help(hsock, ptr); } else { #ifdef HTTP_REDIRECT sendto_http(hsock, "HTTP/1.0 301 Document was moved\n"); sendto_http(hsock, "Location: " HTTP_REDIRECT "\n\n"); sendto_http(hsock, "Document has moved\n"); sendto_http(hsock, "

Document was moved to " "" HTTP_REDIRECT "

\n"); hsock->status = HTTP_ENDING; #else http_send_file(hsock, "index.html", protocol); #endif } } static int auth_raw(u_long addr) { FILE *fp; char buffer[80], *ptr; if ((fp = fopen("raw.auth", "r")) == NULL) return 0; while (fgets(buffer, 79, fp) != NULL) { if ((ptr = strpbrk(buffer, "\r\n")) != NULL) *ptr = '\0'; if (inet_addr(buffer) == addr) { fclose(fp); return 1; } } fclose(fp); return 0; } static void proc_raw(http_socket * hsock, char *line) { register http_raw *raw = (http_raw *) hsock->hook; register char *ptr; unsigned long key = 0; if ((ptr = strpbrk(line, "\r\n")) != NULL) *ptr = '\0'; if (raw == NULL) { if (!auth_raw(hsock->peer.sin_addr.s_addr)) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } hsock->hook = (void *)MALLOC(sizeof(http_raw)); ((http_raw *) hsock->hook)->key = (((unsigned long)hsock->hook % 0xFFFF) + (((HTTPTTLSENTBYTES) & 0xFFFF) << 16)) ^ now; sendto_http(hsock, "PING %lu\n", ((http_raw *) hsock->hook)->key); return; } if (raw->key != 0) { if (strncasecmp(line, "PONG ", 5)) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } sscanf(line + 5, "%lu", &key); if (key != raw->key) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } raw->key = 0; } else { char target[80], cmd[80]; GetWord(0, line, cmd); GetWord(1, line, target); if (!strcasecmp(cmd, "ISREG")) { struct stat st; if (stat(make_dbfname(target), &st) < 0) sendto_http(hsock, "NO\n"); else sendto_http(hsock, "YES\n"); } else if (!strcasecmp(cmd, "REG")) { char buf[256]; struct stat st; RegUser *reg; int bad = 0; if (stat(make_dbfname(target), &st) >= 0) bad = 1; if (!bad) { reg = UserList[ul_hash(target)]; while (reg != NULL && (strcasecmp(reg->channel, target) || reg->access == 0)) reg = reg->next; if (reg != NULL) bad = 1; } if (bad) { sendto_http(hsock, "ERROR Userlist not empty\n"); } else { char tmp[80]; reg = (RegUser *) MALLOC(sizeof(RegUser)); memset(reg, 0, sizeof(RegUser)); GetWord(2, line, tmp); reg->realname = (char *)MALLOC(strlen(tmp) + 1); strcpy(reg->realname, tmp); GetWord(3, line, tmp); reg->match = (char *)MALLOC(strlen(tmp) + 1); strcpy(reg->match, tmp); GetWord(4, line, tmp); reg->modif = (char *)MALLOC(strlen(tmp) + 1); strcpy(reg->modif, tmp); reg->channel = (char *)MALLOC(strlen(target) + 1); strcpy(reg->channel, target); GetWord(6, line, tmp); if (tmp && tmp[0] != '\0') { reg->passwd = (char *)MALLOC(strlen(tmp) + 1); strcpy(reg->passwd, tmp); } else { reg->passwd = (char *)MALLOC(1); reg->passwd[0] = '\0'; } reg->access = 500; reg->suspend = 0; reg->lastseen = now; reg->flags = 0; reg->offset = (off_t) - 1; reg->modified = 1; reg->next = UserList[ul_hash(target)]; UserList[ul_hash(target)] = reg; cold_save_one(reg); sendto_http(hsock, "DONE\n"); sprintf(buf, "%s registered %s to %s", reg->modif, reg->channel, reg->match); broadcast(buf, 0); } } hsock->status = HTTP_ENDING; } } static void parse_post(http_socket * hsock, char *line) { extern void http_show_help(http_socket *, char *); char buffer[512], tmp[10], *channel = NULL, *nick = NULL, *arg = NULL; register char *ptr1, *ptr2; int value; register http_post *post; post = (http_post *) hsock->hook; if (post->count++ > 30) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } #ifdef check_referer if (!strncasecmp(line, "Referer: ", 9) && check_referer(line + 9)) { sendto_http(hsock, "HTTP/1.0 302 Check there\n" "Location: %s\n\n", HTTP_BAD_REFERER); hsock->status = HTTP_ENDING; return; } #endif while ((ptr1 = strpbrk(line, "\r\n")) != NULL) *ptr1 = '\0'; if (!strcasecmp(line, "Content-Type: application/x-www-form-urlencoded")) { post->ready = 1; return; } if (*line == '\0') { post->ready = 2; return; } if (post->ready != 2) { return; } #ifdef DEBUG printf("line= \"%s\"\n", line); #endif for (ptr1 = line, ptr2 = buffer; *ptr1 && (ptr2 - buffer) < 511; ptr1++) { if (ptr1[0] == '%' && ptr1[1] && ptr1[2]) { tmp[0] = ptr1[1]; tmp[1] = ptr1[2]; tmp[2] = '\0'; sscanf(tmp, "%x", &value); *(ptr2++) = value; ptr1 += 2; } else if (ptr1[0] == '&') { *(ptr2++) = ' '; } else { *(ptr2++) = *ptr1; } } *ptr2 = '\0'; #ifdef DEBUG printf("LINE= \"%s\"\n", buffer); #endif http_log("LINE: %s", buffer); if (*post->path != '/') { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } if ((ptr1 = strchr(post->path + 1, '/')) != NULL) { *ptr1 = '\0'; } ptr1 = buffer; if ((channel = strstr(ptr1, "CHANNEL=")) != NULL) { channel += 8; if ((ptr1 = strchr(channel, ' ')) != NULL) { *(ptr1++) = '\0'; } } if (ptr1 && (nick = strstr(ptr1, "NICK=")) != NULL) { nick += 5; if ((ptr1 = strchr(nick, ' ')) != NULL) { *(ptr1++) = '\0'; } } if (ptr1 && (arg = strstr(ptr1, "ARG=")) != NULL) { arg += 4; if ((ptr1 = strchr(arg, ' ')) != NULL) { *(ptr1++) = '\0'; } } if (!strcasecmp(post->path + 1, "USERLIST")) { if (channel == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_userlist(hsock, channel, post->protocol); } else if (!strcasecmp(post->path + 1, "BANLIST")) { if (channel == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_banlist(hsock, channel, post->protocol); } else if (!strcasecmp(post->path + 1, "CHANINFO")) { if (channel == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_chaninfo(hsock, channel); } else if (!strcasecmp(post->path + 1, "LIST")) { if (channel == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_list(hsock, channel); } else if (!strcasecmp(post->path + 1, "WHOIS")) { if (nick == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_whois(hsock, nick); } else if (!strcasecmp(post->path + 1, "HELP")) { if (arg == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } http_show_help(hsock, arg); } else { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; return; } } void parse_http(http_socket * hsock, char *buf) { extern void parse_chat(struct http_socket *, char *); extern void chat_login(struct http_socket *, char *, char *); char method[80], path[80], protocol[80], *ptr; #ifdef DEBUG printf("#IN# %s\n", buf); #endif if (hsock->status == HTTP_RECV_POST) { parse_post(hsock, buf); return; } if (hsock->status == HTTP_CSRAW) { proc_raw(hsock, buf); return; } if (hsock->status == HTTP_CHAT) { parse_chat(hsock, buf); return; } if ((ptr = strpbrk(buf, "\r\n")) != NULL) *ptr = '\0'; GetWord(0, buf, method); GetWord(1, buf, path); GetWord(2, buf, protocol); if (*protocol == '\0') strcpy(protocol, "HTTP/1.0"); http_log("[%d] %s %s %s", hsock->fd, method, path, protocol); if (!strcasecmp(method, "GET")) { parse_get(hsock, path, protocol); } else if (!strcasecmp(method, "POST")) { hsock->status = HTTP_RECV_POST; hsock->hook = (void *)MALLOC(sizeof(http_post)); strcpy(((http_post *) hsock->hook)->path, path); strcpy(((http_post *) hsock->hook)->protocol, protocol); ((http_post *) hsock->hook)->count = 0; ((http_post *) hsock->hook)->ready = 0; } else if (!strcasecmp(method, "CSRAW")) { hsock->status = HTTP_CSRAW; proc_raw(hsock, buf + 6); } else if (!strcasecmp(method, "CHAT")) { if ((ptr = strchr(path, '/')) == NULL) { hsock->status = HTTP_ERROR; close(hsock->fd); hsock->fd = -1; } else { *(ptr++) = '\0'; hsock->status = HTTP_CHAT; chat_login(hsock, path, ptr); } } /* else{ hsock->status=HTTP_ERROR; close(hsock->fd); hsock->fd=-1; } */ } #endif