#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
/*
BuggyServer v. 2.0
Copyright (c) , Matt Jacobson [mhj32]
All Rights Reserved.
*/
typedef unsigned char byte;
int main(int, char*[]);
char* handle(char*, int*);
int check_filename_length(byte);
void sigint(int);
void sigsegv(int);
char* port_arg;
int sock = 0;
const char* prefix = "GET /";
const char* resp_ok = "HTTP/1.1 200 OK\nServer: BuggyServer/1.0\n";
const char* resp_bad = "HTTP/1.1 404 Not Found\nServer: BuggyServer/1.0\n\n";
const char* content_html = "Content-type: text/html\n\n";
const char* content_text = "Content-type: text/plain\n\n";
const char* www_path = "./www/";
int main(int argc, char* argv[]) {
int port;
if (argc
< 2 || (port
= atoi(argv
[1])) < 1 || port
> 65535) {
printf("Usage: webserver port\n");
}
port_arg
= (char*) malloc(6*sizeof (char));
signal(SIGINT, &sigint);
signal(SIGSEGV, &sigsegv);
struct sockaddr_in socket_addr;
sock = socket(PF_INET, SOCK_STREAM, 0);
memset(&socket_addr
, 0, sizeof socket_addr
);
socket_addr.sin_family = PF_INET;
socket_addr.sin_port = htons(port);
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *) &socket_addr, sizeof socket_addr) < 0) {
}
listen(sock, 10);
while (1) {
int acceptsock = accept(sock, NULL, NULL);
char* input
= (char*) malloc(1024*sizeof (char));
recv(acceptsock, input, 1024, 0);
int is_html = 0;
char* contents = handle(input,&is_html);
if (contents != NULL) {
send
(acceptsock
, resp_ok
, strlen(resp_ok
), 0);
if (is_html)
send
(acceptsock
, content_html
, strlen(content_html
), 0);
else
send
(acceptsock
, content_text
, strlen(content_text
), 0);
send
(acceptsock
, contents
, strlen(contents
), 0);
send(acceptsock, "\n", 1, 0);
} else
send
(acceptsock
, resp_bad
, strlen(resp_bad
), 0);
shutdown(acceptsock, SHUT_RDWR); // fixed strange buffering issues (related to kernel or Firefox?)
close(acceptsock);
}
return 0;
}
char* handle(char* request, int* is_html) {
char filename[100];
memset(filename
, '\0', 100*sizeof (char));
if (strstr(request
, prefix
) == request
) {
char* start
= request
+ strlen(prefix
);
char* end
= strstr(start
, " HTTP");
if (end == NULL) {
printf("Unsupported command (malformed end).\n");
return NULL;
}
int len = (int) (end - start);
if (check_filename_length(len))
else
return NULL;
} else {
printf("BEGIN: Unsupported command (malformed beginning).\n");
return NULL;
}
if (strstr(filename
,"/") != NULL
)
return NULL;
strcpy(filename
,"index.html");
if (strstr(filename
,".html") != NULL
)
*is_html = 1;
struct stat file_status;
if (stat(path, &file_status) != 0)
{
return NULL;
}
char* contents
= (char*) malloc((file_status.
st_size+1)*sizeof (char));
memset(contents
, '\0', file_status.
st_size+1);
FILE
*readfile
= fopen(path
, "r");
int i;
for (i=0;i<file_status.st_size;i++)
contents
[i
] = fgetc(readfile
);
return contents;
}
int check_filename_length(byte len) {
if (len < 100)
return 1;
return 0;
}
void sigint(int arg) {
if (sock)
close(sock);
printf("Shutting down peacefully.\n");
}
void sigsegv(int arg) {
if (sock)
close(sock);
printf("Segmentation violation. Shutting down peacefully, then rebooting.\n");
sleep(2);
char* argv[3];
argv[0] = "./webserver";
argv[1] = port_arg;
argv[2] = NULL;
execv(argv[0], argv);
}