I have implemented all four of the functions required but I am confused because my code doesn't seem to pass many of the check50 tests.
Check50 Results: https://sandbox.cs50.net/checks/f221eea6031b4cdfa88bdc8ba67447a3
EDIT:
I have repeatedly gone through the code with gdb and I have discovered some important things.
- I found that my abs_path and query weren't null terminating properly so I had to loop from the end of the abs_path or query until the end string and add '\0' characters to fill in any space.
- Now, my Parse Function appears to be handling the request line properly.
- cat.html doesn't seem to load, and hello.php doesn't seem to load properly when going from hello.html. I get a lot of favicons displayed on the screen instead.
- Load definitely loads something, it stores it in my buffer variable and *content gets assigned its address.
- Indexes seems to work now, as I am immediately redirected to index.html, but the html doesn't get displayed (same favicons error as before).
- All request lines are met with the 200 OK code.
From here, I'm guessing that the error lies within my lookup function or my load function.
Lookup:
const char* lookup(const char* path)
{
if (access(path, R_OK) == -1)
{
error(403);
return NULL;
}
char* mime = calloc(12, 1);
if (strcasestr(path, ".html") == 0)
{
mime = "text/html";
}
else if (strcasestr(path, ".css") == 0)
{
mime = "text/css";
}
else if (strcasestr(path, ".gif") == 0)
{
mime = "image/gif";
}
else if (strcasestr(path, ".ico") == 0)
{
return "image/x-icon";
}
else if (strcasestr(path, ".jpg") == 0)
{
mime = "image/jpeg";
}
else if (strcasestr(path, ".js") == 0)
{
mime = "text/javascript";
}
else if (strcasestr(path, ".php") == 0)
{
mime = "text/x-php";
}
else if (strcasestr(path, ".png") == 0)
{
mime = "image/png";
}
else
{
mime = NULL;
}
return mime;
}
Load:
bool load(FILE* file, BYTE** content, size_t* length)
{
// checks if file was successfully opened.
if (file == NULL)
{
return false;
}
BYTE* buffer = malloc(BYTES * sizeof(char));
int size = 0;
while (fread(buffer, sizeof(BYTE), 1, file) == 1)
{
size++;
if ((size + 1) % BYTES == 0)
{
buffer = realloc(buffer, sizeof(buffer) * (size + 1));
}
}
*content = buffer;
*length = size;
return true;
}
Parse (Just in Case):
bool parse(const char* line, char* abs_path, char* query)
{
//no errors in parse.
int length = strlen(line);
int space_count = 0;
for (int i = 0; i < length; i++)
{
if (line[i] == (char) 32)
{
space_count++;
}
}
if (space_count != 2)
{
error(400);
return false;
}
char* method = malloc(5 * sizeof(char));
strncpy(method, line, 4);
if (strstr(method, "GET ") == NULL)
{
error(405);
return false;
}
free(method);
if (line[4] != '/')
{
error(501);
return false;
}
char* question_mark = strchr(line, '?');
char* slash = strchr(line, '/');
char* HTTP = strstr(line, "HTTP/1.1");
if (question_mark != NULL)
{
strncpy(abs_path, slash, question_mark - slash);
for (int i = question_mark - slash; i < strlen(abs_path + 1); i++)
{
abs_path[i] = '\0';
}
if (question_mark + 1 == NULL)
{
query[0] = '\0';
}
else
{
strncpy(query, question_mark + 1, (HTTP - question_mark - 2));
query[HTTP - 2 - question_mark] = '\0';
}
}
else
{
strncpy(abs_path, slash, HTTP - slash - 1);
for (int i = HTTP - slash - 1; i < strlen(abs_path + 1); i++)
{
abs_path[i] = '\0';
}
}
char* quot_mark = strchr(line, '\"');
if (quot_mark != NULL)
{
error(400);
return false;
}
//if another version of HTTP is used, the server can't handle it.
if (HTTP == NULL)
{
error(505);
return false;
}
return true;
}
Indexes (Just in Case):
char* indexes(const char* path)
{
if (access(path, R_OK) == -1)
{
error(403);
return NULL;
}
char* new_path = malloc(sizeof(char) * (strlen(path) + 12));
strcpy(new_path, path);
strcat(new_path, "/index.php");
if (access(new_path, R_OK) != -1)
{
return new_path;
}
free(new_path);
new_path = malloc(sizeof(char) * (strlen(path) + 12));
strcpy(new_path, path);
strcat(new_path, "/index.html");
if (access(new_path, R_OK) != -1)
{
return new_path;
}
free(new_path);
return NULL;
}
Hopefully this makes my problem a bit clearer. Sorry if it still sounds too general, but using gdb in a webserver proved to be quite challenging and confusing.