📄 parsers.c
字号:
char *parsers_rcs = "$Id: parsers.c,v 1.26 1998/10/23 01:54:12 ACJC Exp $";/* Written and copyright 1997 Anonymous Coders and Junkbusters Corporation. * Distributed under the GNU General Public License; see the README file. * This code comes with NO WARRANTY. http://www.junkbusters.com/ht/en/gpl.html */#include <stdio.h>#include <sys/types.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#ifndef _WIN32#include <unistd.h>#endif#ifdef REGEX#include <gnu_regex.h>#endif#include "jcc.h"struct parsers client_patterns[] = { { "referer:", /* sic */ 8, client_referrer }, { "user-agent:", 11, client_uagent }, { "ua-", 3, client_ua }, { "from:", 5, client_from }, { "cookie:", 7, client_send_cookie }, { "x-forwarded-for:", 16, client_x_forwarded }, { "proxy-connection:", 17, crumble },/* { "if-modified-since:", 18, crumble }, */ { NULL, 0, NULL }};struct interceptors intercept_patterns[] = { { "show-proxy-args", 14, show_proxy_args }, { "ij-blocked-url", 14, ij_blocked_url }, { "ij-untrusted-url", 14, ij_untrusted_url }, { NULL, 0, NULL }};struct parsers server_patterns[] = { { "set-cookie:", 11, server_set_cookie }, { "connection:", 11, crumble }, { NULL, 0, NULL }};void (*add_client_headers[])() = { client_cookie_adder, client_x_forwarded_adder, client_xtra_adder, NULL};void (*add_server_headers[])() = { NULL};struct parsers *match(char *buf, struct parsers *pats){ struct parsers *v; if(buf == NULL) { /* hit me */ fprintf(logfp, "bingo!\n"); return(NULL); } for(v = pats; v->str ; v++) { if(strncmpic(buf, v->str, v->len) == 0) { return(v); } } return(NULL);}intflush_socket(int fd, struct client_state *csp){ struct iob *iob = csp->iob; int n = iob->eod - iob->cur; if(n <= 0) return(0); n = write_socket(fd, iob->cur, n); iob->eod = iob->cur = iob->buf; return(n);}intadd_to_iob(struct client_state *csp, char *buf, int n){ struct iob *iob = csp->iob; int have, need; char *p; have = iob->eod - iob->cur; if(n <= 0) return(have); need = have + n; if((p = malloc(need + 1)) == NULL) { fprintf(logfp, "%s: malloc() iob failed\n", prog); fperror(logfp, ""); return(-1); } if(have) { /* there is something in the buffer - save it */ memcpy(p, iob->cur, have); /* replace the buffer with the new space */ freez(iob->buf); iob->buf = p; /* point to the end of the data */ p += have; } else { /* the buffer is empty, free it and reinitialize */ freez(iob->buf); iob->buf = p; } /* copy the new data into the iob buffer */ memcpy(p, buf, n); /* point to the end of the data */ p += n ; /* null terminate == cheap insurance */ *p = '\0'; /* set the pointers to the new values */ iob->cur = iob->buf; iob->eod = p; return(need);}/* this (odd) routine will parse the csp->iob and return one of the following: * * 1) a pointer to a dynamically allocated string that contains a header line * 2) NULL indicating that the end of the header was reached * 3) "" indicating that the end of the iob was reached before finding * a complete header line. */char *get_header(struct client_state *csp){ struct iob *iob = csp->iob; char *p, *q, *ret; if((iob->cur == NULL) || ((p = strchr(iob->cur, '\n')) == NULL)) { return(""); /* couldn't find a complete header */ } *p = '\0'; ret = strdup(iob->cur); iob->cur = p+1; if((q = strchr(ret, '\r'))) *q = '\0'; /* is this a blank linke (i.e. the end of the header) ? */ if(*ret == '\0') { freez(ret); return(NULL); } return(ret);}/* h = pointer to list 'dummy' header * s = string to add to the list */voidenlist(struct list *h, char *s){ struct list *n = (struct list *)malloc(sizeof(*n)); struct list *l; if(n) { n->str = strdup(s); n->next = NULL; if((l = h->last)) { l->next = n; } else { h->next = n; } h->last = n; }}voiddestroy_list(struct list *h){ struct list *p, *n; for(p = h->next; p ; p = n) { n = p->next; freez(p->str); freez(p); } memset(h, '\0', sizeof(*h));}char *list_to_text(struct list *h){ struct list *p; char *ret = NULL; char *s; int size; size = 0; for(p = h->next; p ; p = p->next) { if(p->str) { size += strlen(p->str) + 2; } } if((ret = malloc(size + 1)) == NULL) { return(NULL); } ret[size] = '\0'; s = ret; for(p = h->next; p ; p = p->next) { if(p->str) { strcpy(s, p->str); s += strlen(s); *s++ = '\r'; *s++ = '\n'; } } return(ret);}/* sed(): add, delete or modify lines in the HTTP header streams. * on entry, it receives a linked list of headers space that was * allocated dynamically (both the list nodes and the header contents). * * it returns a single pointer to a fully formed header. * * as a side effect it frees the space used by the original header lines. * */char *sed(pats, more_headers, csp)struct parsers pats[];int (*more_headers[])();struct client_state *csp;{ struct list *p; struct parsers *v; char *hdr; int (**f)(); for(p = csp->headers->next; p ; p = p->next) { if(DEBUG(HDR)) fprintf(logfp, "scan: %s", p->str); if((v = match(p->str, pats))) { hdr = v->parser(v, p->str, csp); freez(p->str); p->str = hdr; } if(DEBUG(HDR)) fprintf(logfp, "\n"); } /* place any additional headers on the csp->headers list */ for(f = more_headers; *f ; f++) { (*f)(csp); } /* add the blank line at the end of the header */ enlist(csp->headers, ""); hdr = list_to_text(csp->headers); return(hdr);}voidfree_http_request(struct http_request *http){ freez(http->cmd); freez(http->gpc); freez(http->host); freez(http->hostport); freez(http->path); freez(http->ver);}/* parse out the host and port from the URL */voidparse_http_request(char *req, struct http_request *http, struct client_state *csp){ char *buf, *v[10], *url, *p; int n; memset(http, '\0', sizeof(*http)); http->cmd = strdup(req); buf = strdup(req); n = ssplit(buf, " \r\n", v, SZ(v), 1, 1); if(n == 3) { /* this could be a CONNECT request */ if(strcmpic(v[0], "connect") == 0) { http->ssl = 1; http->gpc = strdup(v[0]); http->hostport = strdup(v[1]); http->ver = strdup(v[2]); } /* or it could be a GET or a POST */ if((strcmpic(v[0], "get") == 0) || (strcmpic(v[0], "head") == 0) || (strcmpic(v[0], "post") == 0)) { http->ssl = 0; http->gpc = strdup(v[0]); url = v[1] ; http->ver = strdup(v[2]); if(strncmpic(url, "http://", 7) == 0) { url += 7; } else if(strncmpic(url, "https://", 8) == 0) { url += 8; } else { url = NULL; } if(url && (p = strchr(url, '/'))) { http->path = strdup(p); *p = '\0'; http->hostport = strdup(url); } } } freez(buf); if(http->hostport == NULL) { free_http_request(http); return; } buf = strdup(http->hostport); n = ssplit(buf, ":", v, SZ(v), 1, 1); if(n == 1) { http->host = strdup(v[0]); http->port = 80; } if(n == 2) { http->host = strdup(v[0]); http->port = atoi(v[1]); } freez(buf); if(http->host == NULL) { free_http_request(http); } if(http->path == NULL) { http->path = strdup(""); }}/* here begins the family of parser functions that reformat header lines */char *crumble(struct parsers *v, char *s, struct client_state *csp){ if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL);}char *client_referrer(struct parsers *v, char *s, struct client_state *csp){ csp->referrer = strdup(s); if(referrer == NULL) { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL); } if(*referrer == '.') { return(strdup(s)); } if(*referrer == '@') { if(csp->send_user_cookie) { return(strdup(s)); } else { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL); } } if(DEBUG(HDR)) fprintf(logfp, " modified"); s = strsav(NULL, "Referer: "); s = strsav(s, referrer ); return(s);}char *client_uagent(struct parsers *v, char *s, struct client_state *csp){ if(uagent == NULL) { if(DEBUG(HDR)) fprintf(logfp, " default"); return(strdup(DEFAULT_USER_AGENT)); } if(*uagent == '.') { return(strdup(s)); } if(*uagent == '@') { if(csp->send_user_cookie) { return(strdup(s)); } else { if(DEBUG(HDR)) fprintf(logfp, " default"); return(strdup(DEFAULT_USER_AGENT)); } } if(DEBUG(HDR)) fprintf(logfp, " modified"); s = strsav(NULL, "User-Agent: "); s = strsav(s, uagent ); return(s);}char *client_ua(struct parsers *v, char *s, struct client_state *csp){ if(uagent == NULL) { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL); } if(*uagent == '.') { return(strdup(s)); } if(*uagent == '@') { if(csp->send_user_cookie) { return(strdup(s)); } else { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL); } } if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL);}char *client_from(struct parsers *v, char *s, struct client_state *csp){ /* if not set, zap it */ if(from == NULL) { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); return(NULL); } if(*from == '.') { return(strdup(s)); } if(DEBUG(HDR)) fprintf(logfp, " modified"); s = strsav(NULL, "From: "); s = strsav(s, from ); return(s);}char *client_send_cookie(struct parsers *v, char *s, struct client_state *csp){ if(csp->send_user_cookie) { enlist(csp->cookie_list, s + v->len + 1); } else { if(DEBUG(HDR)) fprintf(logfp, " crunch!"); } /* always return NULL here. the cookie header will be sent * at the end of the header. */ return(NULL);}char *client_x_forwarded(struct parsers *v, char *s, struct client_state *csp){ if(add_forwarded) { csp->x_forwarded = strdup(s); } /* always return NULL, since this information * will be sent at the end of the header. */ return(NULL);}/* the following functions add headers directly to the header list */void client_cookie_adder(struct client_state *csp){ struct list *l; char *tmp = NULL; char *e; for(l = csp->cookie_list->next; l ; l = l->next) { if(tmp) { tmp = strsav(tmp, "; "); } tmp = strsav(tmp, l->str); } for(l = wafer_list->next; l ; l = l->next) { if(tmp) { tmp = strsav(tmp, "; "); } if((e = url_encode(cookie_code_map, l->str))) { tmp = strsav(tmp, e); freez(e); } } if(tmp) { char *ret; ret = strdup("Cookie: "); ret = strsav(ret, tmp); if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", ret); enlist(csp->headers, ret); freez(tmp); freez(ret); }}void client_xtra_adder(struct client_state *csp){ struct list *l; for(l = xtra_list->next; l ; l = l->next) { if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", l->str); enlist(csp->headers, l->str); }}void client_x_forwarded_adder(struct client_state *csp){ char *p = NULL; if(add_forwarded == 0) return; if(csp->x_forwarded) { p = strsav(p, csp->x_forwarded); p = strsav(p, ", "); p = strsav(p, csp->ip_addr_str); } else { p = strsav(p, "X-Forwarded-For: "); p = strsav(p, csp->ip_addr_str); } if(DEBUG(HDR)) fprintf(logfp, "addh: %s\r\n", p); enlist(csp->headers, p);}char *server_set_cookie(struct parsers *v, char *s, struct client_state *csp){ if(jar) fprintf(jar, "%s\t%s\n", csp->http->host, (s + v->len + 1)); if(csp->accept_server_cookie == 0) return(crumble(v, s, csp)); return(strdup(s));}/* case insensitive string comparison */int strcmpic(char *s1, char *s2){ while(*s1 && *s2) { if(( *s1 != *s2) && (tolower(*s1) != tolower(*s2))) { break; } s1++, s2++; } return(tolower(*s1) - tolower(*s2));}int strncmpic(char *s1, char *s2, size_t n){ if(n <= 0) return(0); while(*s1 && *s2) { if(( *s1 != *s2) && (tolower(*s1) != tolower(*s2))) { break; } if(--n <= 0) break; s1++, s2++; } return(tolower(*s1) - tolower(*s2));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -