bug 153691: some HTTP 1.1 support; also, view.cgi now shows HTTP request

This commit is contained in:
erik%vanderpoel.org 2005-01-25 08:22:29 +00:00
Родитель bc3a3c68a0
Коммит 87af4e04dc
23 изменённых файлов: 953 добавлений и 485 удалений

Просмотреть файл

@ -47,11 +47,11 @@ PURIFY =
OBJS = \
addurl.$(OBJ) \
app.$(OBJ) \
buf.$(OBJ) \
file.$(OBJ) \
hash.$(OBJ) \
html.$(OBJ) \
http.$(OBJ) \
io.$(OBJ) \
mime.$(OBJ) \
net.$(OBJ) \
thread.$(OBJ) \
@ -60,13 +60,9 @@ OBJS = \
view.$(OBJ)
EXES = \
dnstest$(EXE) \
ftp$(EXE) \
grab$(EXE) \
httpd$(EXE) \
link$(EXE) \
pop$(EXE) \
proxy$(EXE) \
robot$(EXE) \
urltest$(EXE) \
view.cgi$(EXE)

Просмотреть файл

@ -47,11 +47,11 @@ PURIFY =
OBJS = \
addurl.$(OBJ) \
app.$(OBJ) \
buf.$(OBJ) \
file.$(OBJ) \
hash.$(OBJ) \
html.$(OBJ) \
http.$(OBJ) \
io.$(OBJ) \
mime.$(OBJ) \
net.$(OBJ) \
thread.$(OBJ) \
@ -60,13 +60,9 @@ OBJS = \
view.$(OBJ)
EXES = \
dnstest$(EXE) \
ftp$(EXE) \
grab$(EXE) \
httpd$(EXE) \
link$(EXE) \
pop$(EXE) \
proxy$(EXE) \
robot$(EXE) \
urltest$(EXE) \
view.cgi$(EXE)

Просмотреть файл

@ -58,6 +58,7 @@ Description of Files
addurl.c, addurl.h: adds URLs to a list
all.h: header that includes all the required headers
buf.c, buf.h: I/O routines
cgiview.c: the view.cgi tool
config*: autoconf-related files
dns.c: experimental DNS toy
@ -71,7 +72,6 @@ Description of Files
http.c, http.h: simple HTTP implementation
index.html: used with view.cgi tool
INSTALL: see this file for build instructions
io.c, io.h: I/O routines
link.c: the "link" tool
main.h: very simple callbacks, could be more object-oriented
Makefile, Makefile.in: to build everything

Просмотреть файл

@ -70,11 +70,11 @@ typedef struct App App;
#include "addurl.h"
#include "app.h"
#include "buf.h"
#include "file.h"
#include "hash.h"
#include "html.h"
#include "http.h"
#include "io.h"
#include "mime.h"
#include "net.h"
#include "thread.h"

Просмотреть файл

@ -30,52 +30,67 @@ appContentType(App *app, unsigned char *contentType)
}
static void
appHTML(App *app, Input *input)
appHTML(App *app, Buf *buf)
{
}
static void
appHTMLAttributeName(App *app, HTML *html, Input *input)
appHTMLAttributeName(App *app, HTML *html, Buf *buf)
{
}
static void
appHTMLAttributeValue(App *app, HTML *html, Input *input)
appHTMLAttributeValue(App *app, HTML *html, Buf *buf)
{
}
static void
appHTMLTag(App *app, HTML *html, Input *input)
appHTMLTag(App *app, HTML *html, Buf *buf)
{
}
static void
appHTMLText(App *app, Input *input)
appHTMLText(App *app, Buf *buf)
{
}
static void
appHTTP(App *app, Input *input)
appHTTPRequest(App *app, Buf *buf)
{
}
static void
appHTTPBody(App *app, Input *input)
appHTTPRequestHeaderName(App *app, Buf *buf)
{
}
static void
appHTTPCharSet(App *app, unsigned char *charset)
appHTTPRequestHeaderValue(App *app, Buf *buf)
{
}
static void
appHTTPHeaderName(App *app, Input *input)
appHTTPResponse(App *app, Buf *buf)
{
}
static void
appHTTPHeaderValue(App *app, Input *input, unsigned char *url)
appHTTPResponseBody(App *app, Buf *buf)
{
}
static void
appHTTPResponseCharSet(App *app, unsigned char *charset)
{
}
static void
appHTTPResponseHeaderName(App *app, Buf *buf)
{
}
static void
appHTTPResponseHeaderValue(App *app, Buf *buf, unsigned char *url)
{
}
@ -97,11 +112,14 @@ App appDefault =
appHTMLAttributeValue,
appHTMLTag,
appHTMLText,
appHTTP,
appHTTPBody,
appHTTPCharSet,
appHTTPHeaderName,
appHTTPHeaderValue,
appHTTPRequest,
appHTTPRequestHeaderName,
appHTTPRequestHeaderValue,
appHTTPResponse,
appHTTPResponseBody,
appHTTPResponseCharSet,
appHTTPResponseHeaderName,
appHTTPResponseHeaderValue,
appStatus,
appTime
};

Просмотреть файл

@ -23,7 +23,6 @@
* ***** END LICENSE BLOCK ***** */
#include "html.h"
#include "io.h"
#include "view.h"
enum {
@ -40,16 +39,28 @@ enum {
struct App
{
void (*contentType)(App *app, unsigned char *contentType);
void (*html)(App *app, Input *input);
void (*htmlAttributeName)(App *app, HTML *html, Input *input);
void (*htmlAttributeValue)(App *app, HTML *html, Input *input);
void (*htmlTag)(App *app, HTML *html, Input *input);
void (*htmlText)(App *app, Input *input);
void (*http)(App *app, Input *input);
void (*httpBody)(App *app, Input *input);
void (*httpCharSet)(App *app, unsigned char *charset);
void (*httpHeaderName)(App *app, Input *input);
void (*httpHeaderValue)(App *app, Input *input, unsigned char *url);
void (*html)(App *app, Buf *buf);
void (*htmlAttributeName)(App *app, HTML *html, Buf *buf);
void (*htmlAttributeValue)(App *app, HTML *html, Buf *buf);
void (*htmlTag)(App *app, HTML *html, Buf *buf);
void (*htmlText)(App *app, Buf *buf);
void (*httpRequest)(App *app, Buf *buf);
void (*httpRequestHeaderName)(App *app, Buf *buf);
void (*httpRequestHeaderValue)(App *app, Buf *buf);
/* pieces of http response other than header names and values */
void (*httpResponse)(App *app, Buf *buf);
/* called when Content-Type != text/html or Content-Type missing */
void (*httpResponseBody)(App *app, Buf *buf);
void (*httpResponseCharSet)(App *app, unsigned char *charset);
void (*httpResponseHeaderName)(App *app, Buf *buf);
void (*httpResponseHeaderValue)(App *app, Buf *buf,
unsigned char *url);
void (*status)(App *app, char *message, char *file, int line);
void (*time)(App *app, int task, struct timeval *theTime);

256
webtools/web-sniffer/buf.c Normal file
Просмотреть файл

@ -0,0 +1,256 @@
#include "all.h"
#define bufBlock 2048
struct Buf
{
unsigned char *buf;
unsigned long alloc;
unsigned long curr;
unsigned long endData;
unsigned long markBegin;
unsigned long markEnd;
int fd;
int error;
};
static int bufGrow(Buf *buf, int size);
Buf *
bufAlloc(int fd)
{
Buf *buf;
buf = calloc(1, sizeof(Buf));
if (!buf)
{
return NULL;
}
buf->alloc = 1;
buf->buf = malloc(buf->alloc);
if (!buf->buf)
{
free(buf);
return NULL;
}
buf->fd = fd;
return buf;
}
unsigned char *
bufCopy(Buf *buf)
{
return copySizedString(&buf->buf[buf->markBegin],
buf->markEnd - buf->markBegin);
}
unsigned char *
bufCopyLower(Buf *buf)
{
return lowerCase(copySizedString(&buf->buf[buf->markBegin],
buf->markEnd - buf->markBegin));
}
unsigned char *
bufCopyMemory(Buf *buf, unsigned long *len)
{
unsigned char *ret;
*len = buf->markEnd - buf->markBegin;
ret = malloc(*len);
if (!ret)
{
fprintf(stderr, "cannot calloc block\n");
exit(0);
}
memcpy(ret, &buf->buf[buf->markBegin], *len);
return ret;
}
unsigned long
bufCurrent(Buf *buf)
{
return buf->curr;
}
int
bufError(Buf *buf)
{
return buf->error;
}
void
bufFree(Buf *buf)
{
free(buf->buf);
free(buf);
}
unsigned short
bufGetByte(Buf *buf)
{
int n;
if (buf->curr < buf->endData)
{
return buf->buf[buf->curr++];
}
if (!bufGrow(buf, bufBlock))
{
buf->curr++;
return 256;
}
n = recv(buf->fd, &buf->buf[buf->endData], bufBlock, 0);
if (n < 0)
{
buf->curr++;
return 256;
}
else if (n == 0)
{
buf->curr++;
return 256;
}
buf->endData += n;
return buf->buf[buf->curr++];
}
static int
bufGrow(Buf *buf, int size)
{
int need;
need = buf->curr + size;
if (buf->alloc >= need)
{
return 1;
}
while (buf->alloc < need)
{
buf->alloc *= 2;
}
buf->buf = realloc(buf->buf, buf->alloc);
if (!buf->buf)
{
buf->error = 1;
return 0;
}
return 1;
}
void
bufMark(Buf *buf, int offset)
{
buf->markBegin = buf->markEnd;
buf->markEnd = buf->curr + offset;
}
void
bufPutChar(Buf *buf, unsigned char c)
{
if (buf->error)
{
return;
}
if (buf->curr >= buf->alloc)
{
if (!bufGrow(buf, 1))
{
return;
}
}
buf->buf[buf->curr++] = c;
buf->endData = buf->curr;
}
void
bufPutString(Buf *buf, unsigned char *str)
{
int len;
if (buf->error)
{
return;
}
len = strlen((char *) str);
if (buf->curr + len >= buf->alloc)
{
if (!bufGrow(buf, len))
{
return;
}
}
while (*str)
{
buf->buf[buf->curr++] = *str++;
}
buf->endData = buf->curr;
}
void
bufSend(Buf *buf)
{
if (buf->error)
{
fprintf(stderr, "bufSend error\n");
return;
}
send(buf->fd, buf->buf, buf->curr, 0);
}
void
bufSet(Buf *buf, unsigned long offset)
{
buf->curr = offset;
}
void
bufSetFD(Buf *buf, int fd)
{
buf->fd = fd;
}
unsigned short
bufTrimTrailingWhiteSpace(Buf *buf)
{
unsigned char c;
buf->curr -= 2;
do
{
c = buf->buf[buf->curr--];
} while
(
(c == ' ') ||
(c == '\t') ||
(c == '\r') ||
(c == '\n')
);
buf->curr += 2;
return buf->buf[buf->curr++];
}
void
bufUnGetByte(Buf *buf)
{
if (buf->curr > 0)
{
buf->curr--;
}
}
void
bufWrite(Buf *buf)
{
write(buf->fd, &buf->buf[buf->curr], buf->endData - buf->curr);
}

Просмотреть файл

@ -0,0 +1,24 @@
#ifndef _BUF_H_
#define _BUF_H_
typedef struct Buf Buf;
Buf *bufAlloc(int fd);
unsigned char *bufCopy(Buf *buf);
unsigned char *bufCopyLower(Buf *buf);
unsigned char *bufCopyMemory(Buf *buf, unsigned long *len);
unsigned long bufCurrent(Buf *buf);
int bufError(Buf *buf);
void bufFree(Buf *buf);
unsigned short bufGetByte(Buf *buf);
void bufMark(Buf *buf, int offset);
void bufPutChar(Buf *buf, unsigned char c);
void bufPutString(Buf *buf, unsigned char *str);
void bufSend(Buf *buf);
void bufSet(Buf *buf, unsigned long offset);
void bufSetFD(Buf *buf, int fd);
unsigned short bufTrimTrailingWhiteSpace(Buf *buf);
void bufUnGetByte(Buf *buf);
void bufWrite(Buf *buf);
#endif /* _BUF_H_ */

Просмотреть файл

@ -28,27 +28,36 @@ static char *me = NULL;
static char *passThese[] =
{
"HTTP_USER_AGENT=",
"HTTP_ACCEPT=",
"HTTP_ACCEPT_CHARSET=",
"HTTP_ACCEPT_LANGUAGE=",
"HTTP_ACCEPT",
"HTTP_ACCEPT_CHARSET",
"HTTP_ACCEPT_LANGUAGE",
"HTTP_USER_AGENT",
/*
"HTTP_ACCEPT_ENCODING",
"HTTP_CONNECTION",
"HTTP_HOST",
"HTTP_KEEP_ALIVE",
"HTTP_REFERER",
*/
NULL
};
static void
cgiviewHTML(App *app, Input *input)
cgiviewHTML(App *app, Buf *buf)
{
viewHTML(app, input);
viewHTML(app, buf);
}
static void
cgiviewHTMLAttributeName(App *app, HTML *html, Input *input)
cgiviewHTMLAttributeName(App *app, HTML *html, Buf *buf)
{
viewHTMLAttributeName(app, input);
viewHTMLAttributeName(app, buf);
}
static void
cgiviewHTMLAttributeValue(App *app, HTML *html, Input *input)
cgiviewHTMLAttributeValue(App *app, HTML *html, Buf *buf)
{
unsigned char *referer;
URL *url;
@ -68,7 +77,7 @@ cgiviewHTMLAttributeValue(App *app, HTML *html, Input *input)
free(referer);
urlFree(url);
}
viewHTMLAttributeValue(app, input);
viewHTMLAttributeValue(app, buf);
if (html->currentAttributeIsURL)
{
fprintf(view->out, "</a>");
@ -76,37 +85,55 @@ cgiviewHTMLAttributeValue(App *app, HTML *html, Input *input)
}
static void
cgiviewHTMLTag(App *app, HTML *html, Input *input)
cgiviewHTMLTag(App *app, HTML *html, Buf *buf)
{
viewHTMLTag(app, input);
viewHTMLTag(app, buf);
}
static void
cgiviewHTMLText(App *app, Input *input)
cgiviewHTMLText(App *app, Buf *buf)
{
viewHTMLText(app, input);
viewHTMLText(app, buf);
}
static void
cgiviewHTTP(App *app, Input *input)
cgiviewHTTPRequest(App *app, Buf *buf)
{
viewHTTP(app, input);
viewHTTP(app, buf);
}
static void
cgiviewHTTPBody(App *app, Input *input)
cgiviewHTTPRequestHeaderName(App *app, Buf *buf)
{
viewHTTP(app, input);
viewHTTPHeaderName(app, buf);
}
static void
cgiviewHTTPHeaderName(App *app, Input *input)
cgiviewHTTPRequestHeaderValue(App *app, Buf *buf)
{
viewHTTPHeaderName(app, input);
viewHTTPHeaderValue(app, buf);
}
static void
cgiviewHTTPHeaderValue(App *app, Input *input, unsigned char *url)
cgiviewHTTPResponse(App *app, Buf *buf)
{
viewHTTP(app, buf);
}
static void
cgiviewHTTPResponseBody(App *app, Buf *buf)
{
viewHTTP(app, buf);
}
static void
cgiviewHTTPResponseHeaderName(App *app, Buf *buf)
{
viewHTTPHeaderName(app, buf);
}
static void
cgiviewHTTPResponseHeaderValue(App *app, Buf *buf, unsigned char *url)
{
unsigned char *urlstring;
View *view;
@ -119,34 +146,29 @@ cgiviewHTTPHeaderValue(App *app, Input *input, unsigned char *url)
fprintf(view->out, "<a href=\"%s%s\">", me, urlstring);
free(urlstring);
}
viewHTTPHeaderValue(app, input);
viewHTTPHeaderValue(app, buf);
if (url)
{
fprintf(view->out, "</a>");
}
}
unsigned char **
getHTTPRequestHeaders(App *app, char *host, char *referer, char *verbose)
static HTTPNameValue *
cgiviewGetEnv(App *app, char *referer, char *verbose, char **version)
{
char **e;
extern char **environ;
char *equals;
int firstLetter;
char **h;
char *p;
char *q;
char **r;
char **ret;
HTTPNameValue *r;
HTTPNameValue *ret;
char *scriptName;
char *str;
scriptName = "view.cgi";
e = environ;
while (*e)
{
e++;
}
ret = malloc((e - environ + 2) * sizeof(*e));
ret = malloc((NELEMS(passThese) + 1) * sizeof(HTTPNameValue));
if (!ret)
{
return NULL;
@ -161,13 +183,20 @@ getHTTPRequestHeaders(App *app, char *host, char *referer, char *verbose)
e = environ;
r = ret;
viewReport(app, "will send these HTTP Request headers:");
viewReport(app, "will ignore these:");
while (*e)
{
equals = strchr(*e, '=');
if (!equals)
{
e++;
continue;
}
*equals = 0;
h = passThese;
while (*h)
{
if (!strncmp(*e, *h, strlen(*h)))
if (!strcmp(*e, *h))
{
break;
}
@ -175,14 +204,14 @@ getHTTPRequestHeaders(App *app, char *host, char *referer, char *verbose)
}
if (*h)
{
str = malloc(strlen(*e) - 5 + 1 + 1);
if (!str)
r->name = malloc(strlen(*e) - 5 + 1);
if (!r->name)
{
continue;
return NULL;
}
p = *e + 5;
q = str;
while (*p && (*p != '='))
q = (char *) r->name;
while (*p)
{
firstLetter = 1;
while (*p && (*p != '=') && (*p != '_'))
@ -204,45 +233,42 @@ getHTTPRequestHeaders(App *app, char *host, char *referer, char *verbose)
p++;
}
}
if (*p == '=')
*q = 0;
r->value = (unsigned char *) strdup(equals + 1);
if (!r->value)
{
p++;
*q++ = ':';
*q++ = ' ';
while (*p)
{
*q++ = *p++;
}
*q = 0;
*r++ = str;
viewReport(app, str);
return NULL;
}
r++;
}
else if (!strncmp(*e, "HTTP_", 5))
{
viewReport(app, *e);
}
else if (!strcmp(*e, "SERVER_PROTOCOL"))
{
*version = strdup(equals + 1);
}
e++;
}
str = malloc(6 + strlen(host) + 1);
if (str)
{
strcpy(str, "Host: ");
strcat(str, host);
/* *r++ = str; */ /* http.c will do Host header */
viewReport(app, str);
}
if (referer)
{
str = malloc(9 + strlen(referer) + 1);
if (str)
r->name = (unsigned char *) strdup("Referer");
if (!r->name)
{
strcpy(str, "Referer: ");
strcat(str, referer);
*r++ = str;
viewReport(app, str);
return NULL;
}
r->value = (unsigned char *) strdup(referer);
if (!r->value)
{
return NULL;
}
r++;
}
r->name = NULL;
viewReportHTML(app, "<hr>");
*r = NULL;
return (unsigned char **) ret;
return ret;
}
int
@ -251,6 +277,7 @@ main(int argc, char *argv[])
char *ampersand;
App *app;
unsigned char *equals;
HTTPNameValue *headers;
char *name;
unsigned char *newURL;
char *p;
@ -259,6 +286,7 @@ main(int argc, char *argv[])
URL *u;
unsigned char *url;
char *verbose;
char *version;
View *view;
if (!netInit())
@ -282,10 +310,13 @@ main(int argc, char *argv[])
app->htmlAttributeValue = cgiviewHTMLAttributeValue;
app->htmlTag = cgiviewHTMLTag;
app->htmlText = cgiviewHTMLText;
app->http = cgiviewHTTP;
app->httpBody = cgiviewHTTPBody;
app->httpHeaderName = cgiviewHTTPHeaderName;
app->httpHeaderValue = cgiviewHTTPHeaderValue;
app->httpRequest = cgiviewHTTPRequest;
app->httpRequestHeaderName = cgiviewHTTPRequestHeaderName;
app->httpRequestHeaderValue = cgiviewHTTPRequestHeaderValue;
app->httpResponse = cgiviewHTTPResponse;
app->httpResponseBody = cgiviewHTTPResponseBody;
app->httpResponseHeaderName = cgiviewHTTPResponseHeaderName;
app->httpResponseHeaderValue = cgiviewHTTPResponseHeaderValue;
view = &app->view;
view->out = stdout;
freopen("/dev/null", "w", stderr);
@ -337,12 +368,9 @@ main(int argc, char *argv[])
}
if (url && (*url))
{
fprintf
(
view->out,
"<html><head><title>View %s</title></head><body><pre>",
url
);
fprintf(view->out,
"<html><head><title>View %s</title></head><body>\n"
"<pre>", url);
viewReport(app, "input url:");
viewReport(app, (char *) url);
viewReportHTML(app, "<hr>");
@ -399,9 +427,14 @@ main(int argc, char *argv[])
viewReportHTML(app, "<hr>");
if (!strcmp((char *) u->scheme, "http"))
{
httpProcess(app, u,
getHTTPRequestHeaders(app, (char *) u->host,
(char *) referer, verbose));
version = NULL;
headers = cgiviewGetEnv(app, (char *) referer,
verbose, &version);
if (!headers)
{
return 1;
}
httpFree(httpProcess(app, u, version, headers));
}
else
{

Просмотреть файл

@ -29,7 +29,7 @@ fileProcess(void *a, URL *url)
{
char *dot;
FILE *file;
Input *input;
Buf *buf;
/* XXX temporary? */
if (!url->file)
@ -55,7 +55,12 @@ fileProcess(void *a, URL *url)
fprintf(stderr, "cannot open file %s\n", url->path);
return;
}
input = readStream(fileno(file), url->url);
htmlRead(a, input, url->url);
inputFree(input);
buf = bufAlloc(fileno(file));
if (!buf)
{
fprintf(stderr, "cannot alloc buf\n");
return;
}
htmlRead(a, buf, url->url);
bufFree(buf);
}

Просмотреть файл

@ -107,11 +107,9 @@ grab(char *dir, unsigned char *url, HTTP *http)
fprintf(stderr, "cannot open file %s for writing\n", str);
exit(0);
}
if (fwrite(http->body, 1, http->bodyLen, file) != http->bodyLen)
{
fprintf(stderr, "did not write %ld bytes\n", http->bodyLen);
exit(0);
}
bufSetFD(http->in, fileno(file));
bufSet(http->in, http->body);
bufWrite(http->in);
fclose(file);
free(str);
}
@ -198,7 +196,7 @@ main(int argc, char *argv[])
while (url)
{
appDefault.data = url;
http = httpProcess(&appDefault, url, NULL);
http = httpProcess(&appDefault, url, NULL, NULL);
if (http)
{
switch (http->status)

Просмотреть файл

@ -332,7 +332,7 @@ htmlRegisterTagHandler(HTMLHandler handler)
}
static unsigned short
htmlGetByte(Input *input, HTMLState *state)
htmlGetByte(Buf *buf, HTMLState *state)
{
unsigned short c;
unsigned short ret;
@ -345,21 +345,21 @@ htmlGetByte(Input *input, HTMLState *state)
return tmp;
}
c = getByte(input);
c = bufGetByte(buf);
if (c == 256)
{
ret = c;
}
else if (c == 0x1b)
{
c = getByte(input);
c = bufGetByte(buf);
if (c == 256)
{
ret = c;
}
else if (c == '$')
{
c = getByte(input);
c = bufGetByte(buf);
if (c == 256)
{
ret = c;
@ -367,9 +367,9 @@ htmlGetByte(Input *input, HTMLState *state)
else if (c == '(')
{
/* throw away 4th byte in ESC sequence */
getByte(input);
bufGetByte(buf);
state->mask = 0x80;
c = getByte(input);
c = bufGetByte(buf);
if (c == 256)
{
ret = c;
@ -382,7 +382,7 @@ htmlGetByte(Input *input, HTMLState *state)
else
{
state->mask = 0x80;
c = getByte(input);
c = bufGetByte(buf);
if (c == 256)
{
ret = c;
@ -397,12 +397,12 @@ htmlGetByte(Input *input, HTMLState *state)
{
state->mask = 0;
/* throw away 3rd byte in ESC sequence */
getByte(input);
ret = getByte(input);
bufGetByte(buf);
ret = bufGetByte(buf);
}
else
{
unGetByte(input);
bufUnGetByte(buf);
ret = 0x1b;
}
}
@ -423,7 +423,7 @@ htmlUnGetByte(HTMLState *state)
}
static unsigned short
eatWhiteSpace(Input *input, HTMLState *state, unsigned short c)
eatWhiteSpace(Buf *buf, HTMLState *state, unsigned short c)
{
while
(
@ -433,7 +433,7 @@ eatWhiteSpace(Input *input, HTMLState *state, unsigned short c)
(c == '\n')
)
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
}
return c;
@ -458,13 +458,13 @@ htmlFreeAttributes(HTMLState *state)
}
static unsigned short
readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
readAttribute(App *app, Buf *buf, HTMLState *state, unsigned short c)
{
HTMLAttribute *attr;
unsigned short quote;
mark(input, -1);
app->html(app, input);
bufMark(buf, -1);
app->html(app, buf);
while
(
(c != 256) &&
@ -476,9 +476,9 @@ readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
(c != '\n')
)
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
}
mark(input, -1);
bufMark(buf, -1);
attr = calloc(sizeof(HTMLAttribute), 1);
if (!attr)
{
@ -498,15 +498,15 @@ readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
state->html->attributes = attr;
}
state->html->currentAttribute = attr;
attr->name = copyLower(input);
app->htmlAttributeName(app, state->html, input);
attr->name = bufCopyLower(buf);
app->htmlAttributeName(app, state->html, buf);
if ((c == 256) || (c == '>'))
{
return c;
}
if (c != '=')
{
c = eatWhiteSpace(input, state, c);
c = eatWhiteSpace(buf, state, c);
}
if ((c == 256) || (c == '>'))
{
@ -514,30 +514,30 @@ readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
}
if (c == '=')
{
c = eatWhiteSpace(input, state, htmlGetByte(input, state));
c = eatWhiteSpace(buf, state, htmlGetByte(buf, state));
if ((c == '"') || (c == '\''))
{
quote = c;
mark(input, 0);
app->html(app, input);
bufMark(buf, 0);
app->html(app, buf);
do
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
} while ((c != 256) && (c != quote));
if (c == 256)
{
diag(__LINE__, state, c);
}
mark(input, -1);
attr->value = copy(input);
bufMark(buf, -1);
attr->value = bufCopy(buf);
htmlCheckAttribute(state->html);
app->htmlAttributeValue(app, state->html, input);
c = htmlGetByte(input, state);
app->htmlAttributeValue(app, state->html, buf);
c = htmlGetByte(buf, state);
}
else
{
mark(input, -1);
app->html(app, input);
bufMark(buf, -1);
app->html(app, buf);
while
(
(c != 256) &&
@ -552,12 +552,12 @@ readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
{
diag(__LINE__, state, c);
}
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
}
mark(input, -1);
attr->value = copy(input);
bufMark(buf, -1);
attr->value = bufCopy(buf);
htmlCheckAttribute(state->html);
app->htmlAttributeValue(app, state->html, input);
app->htmlAttributeValue(app, state->html, buf);
}
callHandler(app, state->html);
if (c == '>')
@ -565,112 +565,114 @@ readAttribute(App *app, Input *input, HTMLState *state, unsigned short c)
return c;
}
}
return eatWhiteSpace(input, state, c);
return eatWhiteSpace(buf, state, c);
}
static int
caseCompare(char *str, Input *input, HTMLState *state, unsigned short *ret)
caseCompare(char *str, Buf *buf, HTMLState *state, unsigned short *ret)
{
unsigned short c;
int i;
for (i = 0; str[i]; i++)
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (tolower(c) != tolower(str[i]))
{
*ret = c;
return 0;
}
}
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
*ret = c;
return 1;
}
static unsigned short
endTag(App *app, Input *input, HTMLState *state)
endTag(App *app, Buf *buf, HTMLState *state)
{
unsigned short c;
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == 256)
{
mark(input, -1);
app->html(app, input);
bufMark(buf, -1);
app->html(app, buf);
}
return c;
}
static unsigned short
readTag(App *app, Input *input, HTMLState *state)
readTag(App *app, Buf *buf, HTMLState *state)
{
unsigned short c;
mark(input, -1);
app->html(app, input);
bufMark(buf, -1);
app->html(app, buf);
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '!')
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '-')
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '-')
{
const unsigned char *beginningOfComment =
current(input);
unsigned long beginningOfComment =
bufCurrent(buf);
while (1)
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '-')
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '-')
{
c = htmlGetByte(input,
c = htmlGetByte(buf,
state);
if (c == '>')
{
return endTag(app, input, state);
return endTag(app,
buf, state);
}
else if (c == '-')
{
do
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
} while (c == '-');
if (c == '>')
{
return endTag(app, input, state);
return endTag(app,
buf, state);
}
}
}
}
if (c == 256)
{
set(input, beginningOfComment);
bufSet(buf, beginningOfComment);
while (1)
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
if (c == '>')
{
return endTag(app, input, state);
return endTag(app, buf, state);
}
else if (c == 256)
{
fprintf(stderr,
"bad comment\n");
mark(input, -1);
bufMark(buf, -1);
FREE(state->html->tag);
state->html->tag =
copyString((unsigned
char *) "!--");
state->html->tagIsKnown = 1;
app->htmlTag(app,
state->html, input);
state->html, buf);
return c;
}
}
@ -694,7 +696,7 @@ readTag(App *app, Input *input, HTMLState *state)
do
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
}
while
(
@ -705,9 +707,9 @@ readTag(App *app, Input *input, HTMLState *state)
(c != '\r') &&
(c != '\n')
);
mark(input, -1);
bufMark(buf, -1);
FREE(state->html->tag);
state->html->tag = copyLower(input);
state->html->tag = bufCopyLower(buf);
if (hashLookup(knownTagTable, (*state->html->tag == '/') ?
state->html->tag + 1 : state->html->tag))
{
@ -717,27 +719,27 @@ readTag(App *app, Input *input, HTMLState *state)
{
state->html->tagIsKnown = 0;
}
app->htmlTag(app, state->html, input);
app->htmlTag(app, state->html, buf);
if (c == 256)
{
return c;
}
else if (c == '>')
{
return endTag(app, input, state);
return endTag(app, buf, state);
}
c = eatWhiteSpace(input, state, c);
c = eatWhiteSpace(buf, state, c);
if (c == 256)
{
return c;
}
else if (c == '>')
{
return endTag(app, input, state);
return endTag(app, buf, state);
}
do
{
c = readAttribute(app, input, state, c);
c = readAttribute(app, buf, state, c);
} while ((c != 256) && (c != '>'));
state->html->currentAttribute = NULL;
if (tagHandler)
@ -746,31 +748,31 @@ readTag(App *app, Input *input, HTMLState *state)
}
if (c == '>')
{
return endTag(app, input, state);
return endTag(app, buf, state);
}
return c;
}
static unsigned short
readText(App *app, Input *input, HTMLState *state)
readText(App *app, Buf *buf, HTMLState *state)
{
unsigned short c;
mark(input, -1);
app->html(app, input);
bufMark(buf, -1);
app->html(app, buf);
do
{
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
} while ((c != 256) && (c != '<'));
mark(input, -1);
app->htmlText(app, input);
bufMark(buf, -1);
app->htmlText(app, buf);
return c;
}
static unsigned short
dealWithScript(Input *input, HTMLState *state, unsigned short c)
dealWithScript(Buf *buf, HTMLState *state, unsigned short c)
{
if (state->html->tag &&
(!strcasecmp((char *) state->html->tag, "script")))
@ -783,13 +785,13 @@ dealWithScript(Input *input, HTMLState *state, unsigned short c)
}
if (c == '<')
{
if (caseCompare("/script>", input, state, &c))
if (caseCompare("/script>", buf, state, &c))
{
FREE(state->html->tag);
break;
}
}
c = htmlGetByte(input, state);
c = htmlGetByte(buf, state);
}
}
@ -797,7 +799,7 @@ dealWithScript(Input *input, HTMLState *state, unsigned short c)
}
void
htmlRead(App *app, Input *input, unsigned char *base)
htmlRead(App *app, Buf *buf, unsigned char *base)
{
unsigned short c;
HTML html;
@ -819,12 +821,12 @@ htmlRead(App *app, Input *input, unsigned char *base)
state.unGotten = 256;
state.html = &html;
c = htmlGetByte(input, &state);
c = htmlGetByte(buf, &state);
while (c != 256)
{
if (c == '<')
{
c = htmlGetByte(input, &state);
c = htmlGetByte(buf, &state);
htmlUnGetByte(&state);
if
(
@ -834,22 +836,23 @@ htmlRead(App *app, Input *input, unsigned char *base)
(c == '!')
)
{
c = readTag(app, input, &state);
c = dealWithScript(input, &state, c);
c = readTag(app, buf, &state);
c = dealWithScript(buf, &state, c);
}
else
{
diag(__LINE__, &state, c);
c = readText(app, input, &state);
c = readText(app, buf, &state);
}
}
else
{
c = readText(app, input, &state);
c = readText(app, buf, &state);
}
}
FREE(html.base);
FREE(html.url);
FREE(html.tag);
htmlFreeAttributes(&state);
}

Просмотреть файл

@ -25,7 +25,7 @@
#ifndef _HTML_H_
#define _HTML_H_
#include "io.h"
#include "buf.h"
typedef struct HTMLAttribute
{
@ -47,7 +47,7 @@ typedef struct HTML
typedef void (*HTMLHandler)(App *app, HTML *html);
void htmlRead(App *app, Input *input, unsigned char *base);
void htmlRead(App *app, Buf *buf, unsigned char *base);
void htmlRegister(char *tag, char *attributeName, HTMLHandler handler);
void htmlRegisterTagHandler(HTMLHandler handler);
void htmlRegisterURLHandler(HTMLHandler handler);

Просмотреть файл

@ -33,41 +33,57 @@ static int nonEmptyHTTPResponseCount = 0;
static int http10OrGreaterCount = 0;
static unsigned short
readLine(Input *input, unsigned short c)
readLine(Buf *buf, unsigned short c)
{
while ((c != 256) && (c != '\r') && (c != '\n'))
{
c = getByte(input);
c = bufGetByte(buf);
}
if (c == '\r')
{
c = getByte(input);
c = bufGetByte(buf);
if (c == '\n')
{
c = getByte(input);
c = bufGetByte(buf);
}
}
else if (c == '\n')
{
c = getByte(input);
c = bufGetByte(buf);
}
return c;
}
static unsigned short
readSpaceTab(Input *input, unsigned short c)
readNumber(Buf *buf, unsigned short c, int *num)
{
int n;
n = 0;
while ((c != 256) && (c >= '0') && (c <= '9'))
{
n = ((n * 10) + (c - '0'));
c = bufGetByte(buf);
}
*num = n;
return c;
}
static unsigned short
readSpaceTab(Buf *buf, unsigned short c)
{
while ((c == ' ') || (c == '\t'))
{
c = getByte(input);
c = bufGetByte(buf);
}
return c;
}
static unsigned short
readNonWhiteSpace(Input *input, unsigned short c)
readNonWhiteSpace(Buf *buf, unsigned short c)
{
while
(
@ -78,14 +94,15 @@ readNonWhiteSpace(Input *input, unsigned short c)
(c != '\n')
)
{
c = getByte(input);
c = bufGetByte(buf);
}
return c;
}
static unsigned char *
httpReadHeaders(HTTP *http, App *app, Input *input, unsigned char *url)
static unsigned short
httpReadHeaders(HTTP *http, App *app, Buf *buf, unsigned char *url,
unsigned char **ct, int *chunked)
{
unsigned short c;
unsigned char *charset;
@ -95,42 +112,59 @@ httpReadHeaders(HTTP *http, App *app, Input *input, unsigned char *url)
URL *rel;
ContentType *type;
unsigned char *value;
char *version;
contentType = NULL;
locationFound = 0;
if (!*current(input))
bufMark(buf, 0);
c = bufGetByte(buf);
if (c == 256)
{
return emptyHTTPResponse;
*ct = emptyHTTPResponse;
return c;
}
nonEmptyHTTPResponseCount++;
if (strncmp((char *) current(input), "HTTP/", 5))
c = readNonWhiteSpace(buf, c);
bufMark(buf, -1);
app->httpResponse(app, buf);
version = (char *) bufCopy(buf);
if (!strcmp(version, "HTTP/1.0"))
{
}
else if (!strcmp(version, "HTTP/1.1"))
{
}
else if (!strncmp(version, "HTTP/", 5))
{
}
else
{
/* XXX deal with HTTP/0.9? */
return http09Response;
*ct = http09Response;
return c;
}
free(version);
http10OrGreaterCount++;
mark(input, 0);
c = readNonWhiteSpace(input, getByte(input));
c = readSpaceTab(input, c);
sscanf((char *) current(input) - 1, "%d", &http->status);
c = readLine(input, c);
c = readSpaceTab(buf, c);
c = readNumber(buf, c, &http->status);
c = readLine(buf, c);
while (1)
{
if (c == 256)
{
mark(input, 0);
app->http(app, input);
bufMark(buf, 0);
app->httpResponse(app, buf);
break;
}
mark(input, -1);
app->http(app, input);
bufMark(buf, -1);
app->httpResponse(app, buf);
if ((c == '\r') || (c == '\n'))
{
readLine(input, c);
unGetByte(input);
mark(input, 0);
app->http(app, input);
readLine(buf, c);
bufUnGetByte(buf);
bufMark(buf, 0);
app->httpResponse(app, buf);
break;
}
while
@ -141,73 +175,86 @@ httpReadHeaders(HTTP *http, App *app, Input *input, unsigned char *url)
(c != ':')
)
{
c = getByte(input);
c = bufGetByte(buf);
}
if (c != ':')
{
mark(input, -1);
bufMark(buf, -1);
fprintf(stderr, "no colon in HTTP header \"%s\": %s\n",
copy(input), url);
return NULL;
bufCopy(buf), url);
*ct = NULL;
return c;
}
mark(input, -1);
app->httpHeaderName(app, input);
name = copyLower(input);
c = readSpaceTab(input, getByte(input));
mark(input, -1);
app->http(app, input);
c = readLine(input, c);
bufMark(buf, -1);
app->httpResponseHeaderName(app, buf);
name = bufCopyLower(buf);
c = readSpaceTab(buf, bufGetByte(buf));
bufMark(buf, -1);
app->httpResponse(app, buf);
c = readLine(buf, c);
if ((c == ' ') || (c == '\t'))
{
do
{
c = readLine(input, c);
c = readLine(buf, c);
} while ((c == ' ') || (c == '\t'));
}
c = trimTrailingWhiteSpace(input);
mark(input, -1);
value = copy(input);
c = bufTrimTrailingWhiteSpace(buf);
bufMark(buf, -1);
value = bufCopy(buf);
if (!strcasecmp((char *) name, "content-type"))
{
app->httpHeaderValue(app, input, NULL);
app->httpResponseHeaderValue(app, buf, NULL);
type = mimeParseContentType(value);
contentType = mimeGetContentType(type);
charset = mimeGetContentTypeParameter(type, "charset");
if (charset)
{
app->httpCharSet(app, charset);
app->httpResponseCharSet(app, charset);
free(charset);
}
mimeFreeContentType(type);
}
else if (!strcasecmp((char *) name, "location"))
{
app->httpHeaderValue(app, input, value);
app->httpResponseHeaderValue(app, buf, value);
/* XXX supposed to be absolute URL */
rel = urlRelative(url, value);
addURL(app, rel->url);
urlFree(rel);
locationFound = 1;
}
else if (!strcasecmp((char *) name, "transfer-encoding"))
{
app->httpResponseHeaderValue(app, buf, NULL);
if (!strcasecmp((char *) value, "chunked"))
{
*chunked = 1;
}
}
else
{
app->httpHeaderValue(app, input, NULL);
app->httpResponseHeaderValue(app, buf, NULL);
}
free(name);
free(value);
c = readLine(input, c);
mark(input, -1);
app->http(app, input);
c = readLine(buf, c);
bufMark(buf, -1);
app->httpResponse(app, buf);
}
if (!contentType)
{
if (locationFound)
{
return locationURLWasAdded;
*ct = locationURLWasAdded;
return c;
}
}
return contentType;
*ct = contentType;
return c;
}
void
@ -215,13 +262,13 @@ httpParseRequest(HTTP *http, App *app, char *url)
{
unsigned short c;
mark(http->input, 0);
bufMark(http->in, 0);
do
{
c = getByte(http->input);
c = bufGetByte(http->in);
} while (c != 256);
mark(http->input, -1);
app->http(app, http->input);
bufMark(http->in, -1);
app->httpResponse(app, http->in);
}
static void
@ -231,23 +278,77 @@ httpDefaultType(HTTP *http, App *app)
do
{
c = getByte(http->input);
c = bufGetByte(http->in);
}
while (c != 256);
mark(http->input, -1);
app->httpBody(app, http->input);
bufMark(http->in, -1);
app->httpResponseBody(app, http->in);
}
void
httpParseStream(HTTP *http, App *app, unsigned char *url)
{
const unsigned char *begin;
unsigned char *contentType;
Buf *buf;
unsigned short c;
unsigned char *contentType;
int chunked;
int i;
unsigned char *line;
unsigned int size;
chunked = 0;
c = httpReadHeaders(http, app, http->in, url, &contentType, &chunked);
if (chunked)
{
buf = bufAlloc(-1);
while (1)
{
bufMark(http->in, 0);
c = bufGetByte(http->in);
c = readLine(http->in, c);
bufMark(http->in, -1);
line = bufCopy(http->in);
size = 0;
sscanf((char *) line, "%x", &size);
free(line);
if (!size)
{
break;
}
bufUnGetByte(http->in);
for (i = 0; i < size; i++)
{
c = bufGetByte(http->in);
if (c == 256)
{
break;
}
else
{
bufPutChar(buf, c);
}
}
c = bufGetByte(http->in);
if (c != '\r')
{
break;
}
c = bufGetByte(http->in);
if (c != '\n')
{
break;
}
}
bufSet(buf, 0);
bufMark(buf, 0);
}
else
{
buf = http->in;
}
http->body = bufCurrent(buf);
begin = current(http->input);
contentType = httpReadHeaders(http, app, http->input, url);
http->body = current(http->input);
http->bodyLen = inputLength(http->input) - (http->body - begin);
if (contentType)
{
if
@ -260,7 +361,7 @@ httpParseStream(HTTP *http, App *app, unsigned char *url)
app->contentType(app, contentType);
if (!strcasecmp((char *) contentType, "text/html"))
{
htmlRead(app, http->input, url);
htmlRead(app, buf, url);
}
else
{
@ -273,95 +374,100 @@ httpParseStream(HTTP *http, App *app, unsigned char *url)
{
httpDefaultType(http, app);
}
}
void
httpRead(HTTP *http, App *app, int sock, unsigned char *url)
{
struct timeval theTime;
app->status(app, "readStream", __FILE__, __LINE__);
gettimeofday(&theTime, NULL);
http->input = readStream(sock, url);
app->time(app, appTimeReadStream, &theTime);
app->status(app, "readStream done", __FILE__, __LINE__);
httpParseStream(http, app, url);
}
static int
countOrCopy(char **p, char *str)
{
char *orig;
char *q;
orig = str;
if (*p)
if (chunked)
{
q = *p;
while ((*q++ = *str++));
*p = --q;
bufFree(buf);
}
else
{
while (*str++);
}
return --str - orig;
}
static void
httpGetObject(HTTP *http, App *app, int sock, URL *url, unsigned char **headers)
httpRead(App *app, HTTP *http, int sock)
{
unsigned char **h;
char *p;
int len;
int i;
char *buf;
struct timeval theTime;
p = NULL;
buf = NULL;
for (i = 0; i < 2; i++)
app->status(app, "httpRead", __FILE__, __LINE__);
gettimeofday(&theTime, NULL);
http->in = bufAlloc(sock);
httpParseStream(http, app, http->url->url);
app->time(app, appTimeReadStream, &theTime);
app->status(app, "httpRead done", __FILE__, __LINE__);
}
static void
httpPutHeader(App *app, Buf *buf, char *name, char *value)
{
bufPutString(buf, (unsigned char *) name);
bufMark(buf, 0);
app->httpRequestHeaderName(app, buf);
bufPutString(buf, (unsigned char *) ": ");
bufMark(buf, 0);
app->httpRequest(app, buf);
bufPutString(buf, (unsigned char *) value);
bufMark(buf, 0);
app->httpRequestHeaderValue(app, buf);
bufPutString(buf, (unsigned char *) "\r\n");
bufMark(buf, 0);
app->httpRequest(app, buf);
}
static void
httpGetObject(App *app, HTTP *http, int sock)
{
Buf *buf;
HTTPNameValue *h;
buf = bufAlloc(sock);
bufMark(buf, 0);
bufPutString(buf, (unsigned char *) "GET ");
if (http->url->path)
{
len = countOrCopy(&p, "GET ");
if (url->path)
bufPutString(buf, http->url->path);
}
if (http->url->params)
{
bufPutString(buf, http->url->params);
}
if (http->url->query)
{
bufPutString(buf, http->url->query);
}
bufPutChar(buf, ' ');
bufPutString(buf, http->version);
bufPutString(buf, (unsigned char *) "\r\n");
bufMark(buf, 0);
app->httpRequest(app, buf);
h = http->headers;
if (h)
{
while (h->name)
{
len += countOrCopy(&p, (char *) url->path);
}
if (url->params)
{
len += countOrCopy(&p, (char *) url->params);
}
if (url->query)
{
len += countOrCopy(&p, (char *) url->query);
}
len += countOrCopy(&p, " HTTP/1.0\n");
h = headers;
if (h)
{
while (*h)
{
len += countOrCopy(&p, (char *) *h);
len += countOrCopy(&p, "\n");
h++;
}
}
len += countOrCopy(&p, "Host: ");
len += countOrCopy(&p, (char *) url->host);
len += countOrCopy(&p, "\n\n");
if (!buf)
{
buf = malloc(len + 1);
if (!buf)
{
return;
}
p = buf;
httpPutHeader(app, buf, (char *) h->name,
(char *) h->value);
h++;
}
}
send(sock, buf, len, 0);
httpRead(http, app, sock, url->url);
httpPutHeader(app, buf, "Connection", "close");
httpPutHeader(app, buf, "Host", (char *) http->url->host);
bufPutString(buf, (unsigned char *) "\r\n");
bufMark(buf, 0);
app->httpRequest(app, buf);
if (bufError(buf))
{
return;
}
bufSend(buf);
bufFree(buf);
httpRead(app, http, sock);
}
HTTP *
@ -384,13 +490,13 @@ httpFree(HTTP *http)
{
if (http)
{
inputFree(http->input);
bufFree(http->in);
free(http);
}
}
HTTP *
httpProcess(App *app, URL *url, unsigned char **headers)
httpProcess(App *app, URL *url, char *version, HTTPNameValue *headers)
{
HTTP *http;
int port;
@ -418,8 +524,18 @@ httpProcess(App *app, URL *url, unsigned char **headers)
}
http = httpAlloc();
http->url = url;
if (version)
{
http->version = (unsigned char *) version;
}
else
{
http->version = (unsigned char *) "HTTP/1.0";
}
http->headers = headers;
httpGetObject(http, app, sock, url, headers);
httpGetObject(app, http, sock);
close(sock);

Просмотреть файл

@ -25,24 +25,32 @@
#ifndef _HTTP_H_
#define _HTTP_H_
#include "io.h"
#include "url.h"
typedef struct HTTPNameValue HTTPNameValue;
typedef struct HTTP
{
const unsigned char *body;
unsigned long bodyLen;
Input *input;
int status;
unsigned long body;
HTTPNameValue *headers;
Buf *in;
int status;
URL *url;
unsigned char *version;
} HTTP;
struct HTTPNameValue
{
unsigned char *name;
unsigned char *value;
};
HTTP *httpAlloc(void);
void httpFree(HTTP *http);
int httpGetHTTP10OrGreaterCount(void);
int httpGetNonEmptyHTTPResponseCount(void);
void httpParseRequest(HTTP *http, App *app, char *url);
void httpParseStream(HTTP *http, App *app, unsigned char *url);
HTTP *httpProcess(App *app, URL *url, unsigned char **headers);
void httpRead(HTTP *http, App *app, int fd, unsigned char *url);
HTTP *httpProcess(App *app, URL *url, char *version, HTTPNameValue *headers);
#endif /* _HTTP_H_ */

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -68,7 +68,7 @@ main(int argc, char *argv[])
while (url)
{
appDefault.data = url;
http = httpProcess(&appDefault, url, NULL);
http = httpProcess(&appDefault, url, NULL, NULL);
if (http)
{
switch (http->status)

Просмотреть файл

@ -46,15 +46,15 @@ typedef struct Arg
View *view;
} Arg;
static void proxyHTML(App *app, Input *input);
static void proxyHTMLAttributeName(App *app, HTML *html, Input *input);
static void proxyHTMLAttributeValue(App *app, HTML *html, Input *input);
static void proxyHTMLTag(App *app, HTML *html, Input *input);
static void proxyHTMLText(App *app, Input *input);
static void proxyHTTP(App *app, Input *input);
static void proxyHTTPBody(App *app, Input *input);
static void proxyHTTPHeaderName(App *app, Input *input);
static void proxyHTTPHeaderValue(App *app, Input *input, unsigned char *url);
static void proxyHTML(App *app, Buf *buf);
static void proxyHTMLAttributeName(App *app, HTML *html, Buf *buf);
static void proxyHTMLAttributeValue(App *app, HTML *html, Buf *buf);
static void proxyHTMLTag(App *app, HTML *html, Buf *buf);
static void proxyHTMLText(App *app, Buf *buf);
static void proxyHTTP(App *app, Buf *buf);
static void proxyHTTPBody(App *app, Buf *buf);
static void proxyHTTPHeaderName(App *app, Buf *buf);
static void proxyHTTPHeaderValue(App *app, Buf *buf, unsigned char *url);
static fd_set fdSet;
static int id = 0;
@ -193,10 +193,10 @@ proxyApp(FD *f)
app->htmlAttributeValue = proxyHTMLAttributeValue;
app->htmlTag = proxyHTMLTag;
app->htmlText = proxyHTMLText;
app->http = proxyHTTP;
app->httpBody = proxyHTTPBody;
app->httpHeaderName = proxyHTTPHeaderName;
app->httpHeaderValue = proxyHTTPHeaderValue;
app->httpResponse = proxyHTTP;
app->httpResponseBody = proxyHTTPBody;
app->httpResponseHeaderName = proxyHTTPHeaderName;
app->httpResponseHeaderValue = proxyHTTPHeaderValue;
app->view.backslash = 1;
app->view.out = f->logFile;
@ -204,7 +204,7 @@ proxyApp(FD *f)
}
static int
logRequest(FD *f, Input *input)
logRequest(FD *f, Buf *buf)
{
App *app;
HTTP *http;
@ -212,7 +212,7 @@ logRequest(FD *f, Input *input)
if
(
(table[fileno(f->logFile)]->suspend) ||
(strstr((char *) current(input), suspendStr))
(strstr((char *) current(buf), suspendStr))
)
{
table[f->writeFD]->suspend = 1;
@ -232,7 +232,7 @@ logRequest(FD *f, Input *input)
f->id
);
http = httpAlloc();
http->input = input;
http->in = buf;
app = proxyApp(f);
httpParseRequest(http, app, "logRequest");
free(app);
@ -247,21 +247,21 @@ static int
readClientRequest(int fd)
{
FD *f;
Input *input;
Buf *buf;
f = table[fd];
input = readAvailableBytes(fd);
send(f->writeFD, current(input), inputLength(input), 0);
if (!logRequest(f, input))
buf = readAvailableBytes(fd);
send(f->writeFD, current(buf), inputLength(buf), 0);
if (!logRequest(f, buf))
{
inputFree(input);
bufFree(buf);
}
return 0;
}
static int
logResponse(FD *f, Input *input)
logResponse(FD *f, Buf *buf)
{
App *app;
HTTP *http;
@ -280,7 +280,7 @@ logResponse(FD *f, Input *input)
f->id
);
http = httpAlloc();
http->input = input;
http->in = buf;
app = proxyApp(f);
httpParseStream(http, app, (unsigned char *) "readProxyResponse");
free(app);
@ -295,14 +295,14 @@ static int
readProxyResponse(int fd)
{
FD *f;
Input *input;
Buf *buf;
f = table[fd];
input = readStream(fd, (unsigned char *) "readProxyResponse");
send(f->writeFD, current(input), inputLength(input), 0);
if (!logResponse(f, input))
buf = readStream(fd, (unsigned char *) "readProxyResponse");
send(f->writeFD, current(buf), inputLength(buf), 0);
if (!logResponse(f, buf))
{
inputFree(input);
bufFree(buf);
}
removeFD(f->writeFD);
removeFD(fd);
@ -365,7 +365,7 @@ acceptNewClient(int fd)
static int
readLoggerRequest(int fd)
{
char buf[10240];
char b[10240];
int bytesRead;
int doSuspend;
FD *f;
@ -380,7 +380,7 @@ readLoggerRequest(int fd)
char *suspend;
int suspendPort;
bytesRead = recv(fd, buf, sizeof(buf) - 1, 0);
bytesRead = recv(fd, b, sizeof(b) - 1, 0);
if (bytesRead < 0)
{
if (errno != ECONNRESET)
@ -395,11 +395,11 @@ readLoggerRequest(int fd)
removeFD(fd);
return 0;
}
buf[bytesRead] = 0;
b[bytesRead] = 0;
resume = "/resume";
suspend = "/suspend";
if (strstr(buf, "/exit"))
if (strstr(b, "/exit"))
{
char *goodbye =
"HTTP/1.0 200 OK\n"
@ -411,9 +411,9 @@ readLoggerRequest(int fd)
removeFD(fd);
return 1;
}
else if ((strstr(buf, resume)) || (strstr(buf, suspend)))
else if ((strstr(b, resume)) || (strstr(b, suspend)))
{
if (strstr(buf, resume))
if (strstr(b, resume))
{
str = resume;
doSuspend = 0;
@ -423,7 +423,7 @@ readLoggerRequest(int fd)
str = suspend;
doSuspend = 1;
}
p = strstr(buf, str);
p = strstr(b, str);
p += strlen(str);
if (*p != '/')
{
@ -470,7 +470,7 @@ readLoggerRequest(int fd)
return 0;
}
/* XXX send(1, buf, bytesRead, 0); */
/* XXX send(1, b, bytesRead, 0); */
file = fdopen(fd, "w");
if (!file)
@ -537,57 +537,57 @@ acceptNewLogger(int fd)
}
static void
proxyHTML(App *app, Input *input)
proxyHTML(App *app, Buf *buf)
{
viewHTML(app, input);
viewHTML(app, buf);
}
static void
proxyHTMLAttributeName(App *app, HTML *html, Input *input)
proxyHTMLAttributeName(App *app, HTML *html, Buf *buf)
{
viewHTMLAttributeName(app, input);
viewHTMLAttributeName(app, buf);
}
static void
proxyHTMLAttributeValue(App *app, HTML *html, Input *input)
proxyHTMLAttributeValue(App *app, HTML *html, Buf *buf)
{
viewHTMLAttributeValue(app, input);
viewHTMLAttributeValue(app, buf);
}
static void
proxyHTMLTag(App *app, HTML *html, Input *input)
proxyHTMLTag(App *app, HTML *html, Buf *buf)
{
viewHTMLTag(app, input);
viewHTMLTag(app, buf);
}
static void
proxyHTMLText(App *app, Input *input)
proxyHTMLText(App *app, Buf *buf)
{
viewHTMLText(app, input);
viewHTMLText(app, buf);
}
static void
proxyHTTP(App *app, Input *input)
proxyHTTP(App *app, Buf *buf)
{
viewHTTP(app, input);
viewHTTP(app, buf);
}
static void
proxyHTTPBody(App *app, Input *input)
proxyHTTPBody(App *app, Buf *buf)
{
viewHTTP(app, input);
viewHTTP(app, buf);
}
static void
proxyHTTPHeaderName(App *app, Input *input)
proxyHTTPHeaderName(App *app, Buf *buf)
{
viewHTTPHeaderName(app, input);
viewHTTPHeaderName(app, buf);
}
static void
proxyHTTPHeaderValue(App *app, Input *input, unsigned char *url)
proxyHTTPHeaderValue(App *app, Buf *buf, unsigned char *url)
{
viewHTTPHeaderValue(app, input);
viewHTTPHeaderValue(app, buf);
}
int

Просмотреть файл

@ -263,57 +263,57 @@ addURLFunc(App *app, URL *url)
}
static void
robotHTTP(App *app, Input *input)
robotHTTP(App *app, Buf *buf)
{
Robot *robot;
robot = app->data;
viewHTTP(app, input);
viewHTTP(app, buf);
}
static void
robotHTTPBody(App *app, Input *input)
robotHTTPBody(App *app, Buf *buf)
{
}
static void
robotHTTPHeaderName(App *app, Input *input)
robotHTTPHeaderName(App *app, Buf *buf)
{
Robot *robot;
unsigned char *name;
robot = app->data;
name = copyLower(input);
name = bufCopyLower(buf);
addEntry(httpHeaderTable, robot, robot->url->url, name);
free(name);
viewHTTPHeaderName(app, input);
viewHTTPHeaderName(app, buf);
}
static void
robotHTTPHeaderValue(App *app, Input *input, unsigned char *url)
robotHTTPHeaderValue(App *app, Buf *buf, unsigned char *url)
{
Robot *robot;
robot = app->data;
viewHTTPHeaderValue(app, input);
viewHTTPHeaderValue(app, buf);
}
static void
robotHTML(App *app, Input *input)
robotHTML(App *app, Buf *buf)
{
Robot *robot;
robot = app->data;
viewHTML(app, input);
viewHTML(app, buf);
}
static void
robotHTMLText(App *app, Input *input)
robotHTMLText(App *app, Buf *buf)
{
Robot *robot;
unsigned char *p;
@ -321,9 +321,9 @@ robotHTMLText(App *app, Input *input)
robot = app->data;
viewHTMLText(app, input);
viewHTMLText(app, buf);
str = copy(input);
str = bufCopy(buf);
p = str;
while (*p)
{
@ -352,7 +352,7 @@ robotHTMLText(App *app, Input *input)
}
static void
robotHTMLTag(App *app, HTML *html, Input *input)
robotHTMLTag(App *app, HTML *html, Buf *buf)
{
Robot *robot;
HashEntry *tagEntry;
@ -375,11 +375,11 @@ robotHTMLTag(App *app, HTML *html, Input *input)
}
}
viewHTMLTag(app, input);
viewHTMLTag(app, buf);
}
static void
robotHTMLAttributeName(App *app, HTML *html, Input *input)
robotHTMLAttributeName(App *app, HTML *html, Buf *buf)
{
Robot *robot;
@ -391,17 +391,17 @@ robotHTMLAttributeName(App *app, HTML *html, Input *input)
html->currentAttribute->name);
#endif
}
viewHTMLAttributeName(app, input);
viewHTMLAttributeName(app, buf);
}
static void
robotHTMLAttributeValue(App *app, HTML *html, Input *input)
robotHTMLAttributeValue(App *app, HTML *html, Buf *buf)
{
Robot *robot;
robot = app->data;
viewHTMLAttributeValue(app, input);
viewHTMLAttributeValue(app, buf);
}
static void
@ -669,7 +669,7 @@ processURL(App *app)
app->status(app, "processURL", __FILE__, __LINE__);
openViewFile(app);
httpFree(httpProcess(app, robot->url, NULL));
httpFree(httpProcess(app, robot->url, NULL, NULL));
closeViewFile(app);
app->status(app, "processURL done", __FILE__, __LINE__);
@ -688,17 +688,17 @@ startHere(void *a)
app = appAlloc();
app->status = robotStatus;
app->time = robotTime;
app->http = robotHTTP;
app->httpBody = robotHTTPBody;
app->httpHeaderName = robotHTTPHeaderName;
app->httpHeaderValue = robotHTTPHeaderValue;
app->httpResponse = robotHTTP;
app->httpResponseBody = robotHTTPBody;
app->httpResponseHeaderName = robotHTTPHeaderName;
app->httpResponseHeaderValue = robotHTTPHeaderValue;
app->html = robotHTML;
app->htmlText = robotHTMLText;
app->htmlTag = robotHTMLTag;
app->htmlAttributeName = robotHTMLAttributeName;
app->htmlAttributeValue = robotHTMLAttributeValue;
app->contentType = robotContentType;
app->httpCharSet = robotHTTPCharSet;
app->httpResponseCharSet = robotHTTPCharSet;
app->data = &robot;
while (1)
@ -841,12 +841,12 @@ compareStatusEntries(const void *e1, const void *e2)
static void
readClientRequest(int fd)
{
unsigned char buf[10240];
unsigned char b[10240];
int bytesRead;
FILE *file;
int i;
bytesRead = recv(fd, buf, sizeof(buf) - 1, 0);
bytesRead = recv(fd, b, sizeof(b) - 1, 0);
if (bytesRead < 0)
{
if (errno != ECONNRESET)
@ -861,7 +861,7 @@ readClientRequest(int fd)
removeFD(fd);
return;
}
buf[bytesRead] = 0;
b[bytesRead] = 0;
file = fdopen(fd, "w");
if (!file)
@ -874,7 +874,7 @@ readClientRequest(int fd)
table[fd]->file = file;
if (strstr((char *) buf, "/exit"))
if (strstr((char *) b, "/exit"))
{
char *goodbye =
"HTTP/1.0 200 OK\n"
@ -886,7 +886,7 @@ readClientRequest(int fd)
removeFD(fd);
exit(0);
}
else if (strstr((char *) buf, "/times"))
else if (strstr((char *) b, "/times"))
{
char *begin =
"HTTP/1.0 200 OK\n"

Просмотреть файл

@ -30,6 +30,8 @@
#endif
#define FREE(p) do { if (p) { free(p); (p) = NULL; } } while (0)
#define NELEMS(array) (sizeof(array) / sizeof((array)[0]))
unsigned char *appendString(const unsigned char *str1,
const unsigned char *str2);
unsigned char *copySizedString(const unsigned char *str, int size);

Просмотреть файл

@ -32,7 +32,7 @@
static int verbose = 0;
static void
print(View *view, Input *input)
print(View *view, Buf *b)
{
char buf[1024];
char *hex;
@ -47,7 +47,7 @@ print(View *view, Input *input)
unsigned char *str;
hex = "0123456789ABCDEF";
str = copyMemory(input, &inLen);
str = bufCopyMemory(b, &inLen);
buf[1] = 0;
len = 0;
@ -61,7 +61,7 @@ print(View *view, Input *input)
switch (str[j])
{
case '\r':
if (str[j + 1] == '\n')
if (((j + 1) < inLen) && (str[j + 1] == '\n'))
{
j++;
replacement = CONTROL("CRLF") NL;
@ -154,62 +154,62 @@ print(View *view, Input *input)
}
void
viewHTML(App *app, Input *input)
viewHTML(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#009900>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
void
viewHTMLAttributeName(App *app, Input *input)
viewHTMLAttributeName(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#FF6600>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
void
viewHTMLAttributeValue(App *app, Input *input)
viewHTMLAttributeValue(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#3333FF>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
void
viewHTMLTag(App *app, Input *input)
viewHTMLTag(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#CC33CC>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
void
viewHTMLText(App *app, Input *input)
viewHTMLText(App *app, Buf *buf)
{
print(&app->view, input);
print(&app->view, buf);
}
void
viewHTTP(App *app, Input *input)
viewHTTP(App *app, Buf *buf)
{
print(&app->view, input);
print(&app->view, buf);
}
void
viewHTTPHeaderName(App *app, Input *input)
viewHTTPHeaderName(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#FF6600>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
void
viewHTTPHeaderValue(App *app, Input *input)
viewHTTPHeaderValue(App *app, Buf *buf)
{
fprintf(app->view.out, "<font color=#3333FF>");
print(&app->view, input);
print(&app->view, buf);
fprintf(app->view.out, "</font>");
}
@ -222,10 +222,13 @@ viewVerbose(void)
void
viewReport(App *app, char *str)
{
unsigned char *esc;
if (verbose)
{
fprintf(app->view.out, (char *) escapeHTML((unsigned char *) str));
fprintf(app->view.out, "<br>");
esc = escapeHTML((unsigned char *) str);
fprintf(app->view.out, "%s\n", (char *) esc);
free(esc);
fflush(app->view.out);
}
}
@ -235,8 +238,7 @@ viewReportHTML(App *app, char *str)
{
if (verbose)
{
fprintf(app->view.out, str);
fprintf(app->view.out, "<br>");
fprintf(app->view.out, "%s\n", str);
fflush(app->view.out);
}
}

Просмотреть файл

@ -25,7 +25,7 @@
#ifndef _VIEW_H_
#define _VIEW_H_
#include "io.h"
#include "buf.h"
typedef struct View
{
@ -33,14 +33,14 @@ typedef struct View
FILE *out;
} View;
void viewHTML(App *app, Input *input);
void viewHTMLAttributeName(App *app, Input *input);
void viewHTMLAttributeValue(App *app, Input *input);
void viewHTMLTag(App *app, Input *input);
void viewHTMLText(App *app, Input *input);
void viewHTTP(App *app, Input *input);
void viewHTTPHeaderName(App *app, Input *input);
void viewHTTPHeaderValue(App *app, Input *input);
void viewHTML(App *app, Buf *buf);
void viewHTMLAttributeName(App *app, Buf *buf);
void viewHTMLAttributeValue(App *app, Buf *buf);
void viewHTMLTag(App *app, Buf *buf);
void viewHTMLText(App *app, Buf *buf);
void viewHTTP(App *app, Buf *buf);
void viewHTTPHeaderName(App *app, Buf *buf);
void viewHTTPHeaderValue(App *app, Buf *buf);
void viewReport(App *app, char *str);
void viewReportHTML(App *app, char *str);
void viewVerbose(void);