. Added referer, user_agent to struct connection

. Moved xrealloc() to top of file
. Added parse_field()
. parse_request() calls parse_field() for referer, ua
. Logfile is opened in append mode, not write mode
. strip_endslash() calls xrealloc(), not realloc()
This commit is contained in:
Emil Mikulic 2003-03-07 08:10:03 +00:00
parent aa2245e867
commit 7c29be2b7d

View File

@ -19,7 +19,7 @@
* . Chroot, set{uid|gid}. * . Chroot, set{uid|gid}.
* . Port to Win32. * . Port to Win32.
* . Content-Type * . Content-Type
* . Log Referer, User-Agent * x Log Referer, User-Agent
* . Ensure URIs requested are safe * . Ensure URIs requested are safe
*/ */
@ -70,7 +70,7 @@ struct connection
char *request; char *request;
unsigned int request_length; unsigned int request_length;
char *method, *uri; char *method, *uri, *referer, *user_agent;
char *header; char *header;
unsigned int header_sent, header_length; unsigned int header_sent, header_length;
@ -113,6 +113,18 @@ static int want_chroot = 0;
/* ---------------------------------------------------------------------------
* realloc() that errx()s if it can't allocate.
*/
static void *xrealloc(void *original, const size_t size)
{
void *ptr = realloc(original, size);
if (ptr == NULL) errx(1, "can't reallocate %u bytes", size);
return ptr;
}
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Initialize the sockin global. This is the socket that we accept * Initialize the sockin global. This is the socket that we accept
* connections from. * connections from.
@ -168,7 +180,7 @@ static void usage(void)
"\t\tSpecifies how many concurrent connections to accept.\n" "\t\tSpecifies how many concurrent connections to accept.\n"
"\n" "\n"
"\t--log filename (default: no logging)\n" "\t--log filename (default: no logging)\n"
"\t\tSpecifies which file to log requests to.\n" "\t\tSpecifies which file to append the request log to.\n"
"\n" "\n"
"\t--chroot (default: don't chroot)\n" "\t--chroot (default: don't chroot)\n"
"\t\tLocks server into wwwroot directory for added security.\n" "\t\tLocks server into wwwroot directory for added security.\n"
@ -220,7 +232,7 @@ static void strip_endslash(char **str)
if ((*str)[strlen(*str)-1] != '/') return; if ((*str)[strlen(*str)-1] != '/') return;
(*str)[strlen(*str)-1] = 0; (*str)[strlen(*str)-1] = 0;
*str = (char*) realloc(*str, strlen(*str)+1); *str = (char*) xrealloc(*str, strlen(*str)+1);
} }
@ -303,6 +315,7 @@ static struct connection *new_connection(void)
conn->last_active = time(NULL); conn->last_active = time(NULL);
conn->request = NULL; conn->request = NULL;
conn->method = conn->uri = NULL; conn->method = conn->uri = NULL;
conn->referer = conn->user_agent = NULL;
conn->request_length = 0; conn->request_length = 0;
conn->header = NULL; conn->header = NULL;
conn->header_sent = conn->header_length = 0; conn->header_sent = conn->header_length = 0;
@ -361,23 +374,14 @@ static void free_connection(struct connection *conn)
if (conn->request != NULL) free(conn->request); if (conn->request != NULL) free(conn->request);
if (conn->method != NULL) free(conn->method); if (conn->method != NULL) free(conn->method);
if (conn->uri != NULL) free(conn->uri); if (conn->uri != NULL) free(conn->uri);
if (conn->referer != NULL) free(conn->referer);
if (conn->user_agent != NULL) free(conn->user_agent);
if (conn->header != NULL && !conn->header_dont_free) free(conn->header); if (conn->header != NULL && !conn->header_dont_free) free(conn->header);
if (conn->reply != NULL && !conn->reply_dont_free) free(conn->reply); if (conn->reply != NULL && !conn->reply_dont_free) free(conn->reply);
if (conn->reply_file != NULL) fclose(conn->reply_file); if (conn->reply_file != NULL) fclose(conn->reply_file);
} }
/* ---------------------------------------------------------------------------
* realloc() that errx()s if it can't allocate.
*/
static void *xrealloc(void *original, const size_t size)
{
void *ptr = realloc(original, size);
if (ptr == NULL) errx(1, "can't reallocate %u bytes", size);
return ptr;
}
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Uppercasify all characters in a string of given length. * Uppercasify all characters in a string of given length.
@ -502,9 +506,39 @@ static void default_reply(struct connection *conn,
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Parse an HTTP request like "GET / HTTP/1.1" to get the method (GET) and the * Parses a single HTTP request field. If the specified field doesn't exist,
* url (/). Remember to deallocate the method and url buffers. The method * returns NULL. Otherwise, you need to remember to deallocate the result.
* will be returned in uppercase. *
* eg. "Referer: moo" with field="Referer: " returns "moo"
*/
static char *parse_field(const struct connection *conn, const char *field)
{
unsigned int bound1, bound2;
char *pos, *buf;
/* find start */
pos = strstr(conn->request, field);
if (pos == NULL) return NULL;
bound1 = pos - conn->request + strlen(field);
/* find end */
for (bound2 = bound1;
conn->request[bound2] != '\r' &&
bound2 < conn->request_length; bound2++);
/* copy to buffer */
buf = (char*) xmalloc(bound2 - bound1 + 1);
memcpy(buf, conn->request+bound1, bound2-bound1);
buf[bound2-bound1] = 0;
return buf;
}
/* ---------------------------------------------------------------------------
* Parse an HTTP request like "GET / HTTP/1.1" to get the method (GET), the
* url (/), the referer (if given) and the user-agent (if given). Remember to
* deallocate all these buffers. The method will be returned in uppercase.
*/ */
static void parse_request(struct connection *conn) static void parse_request(struct connection *conn)
{ {
@ -528,6 +562,10 @@ static void parse_request(struct connection *conn)
conn->uri = (char*)xmalloc(bound2 - bound1); conn->uri = (char*)xmalloc(bound2 - bound1);
memcpy(conn->uri, conn->request + bound1 + 1, bound2 - bound1 - 1); memcpy(conn->uri, conn->request + bound1 + 1, bound2 - bound1 - 1);
conn->uri[bound2 - bound1 - 1] = 0; conn->uri[bound2 - bound1 - 1] = 0;
/* parse referer, user_agent */
conn->referer = parse_field(conn, "Referer: ");
conn->user_agent = parse_field(conn, "User-Agent: ");
} }
@ -793,16 +831,17 @@ static void log_connection(const struct connection *conn)
if (logfile == NULL) return; if (logfile == NULL) return;
/* Separated by tabs: /* Separated by tabs:
* time client method uri http_code bytes_sent * time client method uri http_code bytes_sent "referer" "user-agent"
*/ */
/* FIXME: Referer, User-Agent */
inaddr.s_addr = conn->client; inaddr.s_addr = conn->client;
fprintf(logfile, "%lu\t%s\t%s\t%s\t%d\t%u\n", fprintf(logfile, "%lu\t%s\t%s\t%s\t%d\t%u\t\"%s\"\t\"%s\"\n",
time(NULL), inet_ntoa(inaddr), conn->method, conn->uri, time(NULL), inet_ntoa(inaddr), conn->method, conn->uri,
conn->http_code, conn->total_sent); conn->http_code, conn->total_sent,
(conn->referer == NULL)?"":conn->referer,
(conn->user_agent == NULL)?"":conn->user_agent
);
fflush(logfile); fflush(logfile);
} }
@ -918,7 +957,7 @@ int main(int argc, char *argv[])
/* open logfile */ /* open logfile */
if (logfile_name != NULL) if (logfile_name != NULL)
{ {
logfile = fopen(logfile_name, "wb"); logfile = fopen(logfile_name, "ab");
if (logfile == NULL) err(1, "fopen(\"%s\")", logfile_name); if (logfile == NULL) err(1, "fopen(\"%s\")", logfile_name);
} }