Every time I input a query on the HTML form, I get a 404 Error even though the query appears in the URL, and printf seem to indicate that my Parse function is correctly extracting the right substring. My terminal output is as follows:
gege019@ide50:~/workspace/pset6 $ ./server public
Using /home/ubuntu/workspace/pset6/public for server's root
Listening on port 8080
GET / HTTP/1.1
Abs_path = /
HTTP/1.1 200 OK
GET /hello.html HTTP/1.1
Abs_path = /hello.html
path is /home/ubuntu/workspace/pset6/public/hello.html
type is text/html
Data: <!DOCTYPE html>
<html>
<head>
<title>hello</title>
</head>
<body>
<form action="hello.php" method="get">
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text"/>
<input type="submit" value="Say Hello"/>
</form>
</body>
</html>
Length: 316
HTTP/1.1 200 OK
GET /hello.php?name=gege019 HTTP/1.1
Query = name=gege019
Abs_path = /hello.php?name=gege019
HTTP/1.1 404 Not Found
Regardless, GDB seems to indicate the error is stemming from my parse function (below) but I'll paste my code for all the functions we had to work on just in case you guys have other ideas. I also looked at this previous question but couldn't determine if we're experiencing the same issue. I would sincerely appreciate any help and guidance on this you can provide. I've spent the past 2 months on this pset and would really like to be able to move on, but would feel terrible submitting it in it's current incomplete form. Thank you so much!!
Parse:
bool parse(const char* line, char* abs_path, char* query)
{
// TODO
//eg: GET /hello.php?name=test HTTP/1.1
//accept only GET as method
if (strncmp("GET ", line, 4) != 0)
{
error(405);
return false;
}
//check that only 2 spaces in request-line
char* space = strchr(line,' ');
if (space == NULL)
{
error(400);
return false;
}
int i = 0;
while (space != NULL)
{
//check for '/' after first space i.e. request-target starts with /
if (i == 0)
{
if (strncmp(" /", space, 2) != 0)
{
error(501);
return false;
}
//check for '"' in request-target and after 2nd space
if (strchr(space, '"') != NULL && (strchr(space+1,' ') != NULL && strchr(strchr(space+1,' '), '"') != NULL ))
{
error(400);
return false;
}
//assuming '?name=variable' can only come after ".php"
//"GET /hello.php?q=test HTTP/1.1\r\n"
int n = strlen(space+1) - strlen(strchr(space+1,' '));
char numq[n + 1];
// numq = "/hello.php?q=test"
strncpy(numq, space+1, n);
numq[n] = '\0';
if (strchr(numq, '?') != NULL)
{
// only ".php" can have query
if (strstr(numq, ".php") == NULL)
{
error(400);
return false;
}
//verify that '?'comes right after ".php"
char* numq3 = strstr(numq, ".php" );
// '.php?name=variable'
if (strncmp(".php?", numq3, 5) !=0)
{
error(400);
return false;
}
//store query "name=variable" in char* query
strcpy(query, (strchr(numq, '?' ) + 1));
printf("Query = %s\n",query);
}
//if ".php" file type but no query, then set query to " "
else if (strstr(numq, ".php") != NULL)
{
//set query to " " ie '\0'
strcpy(query, (strstr(numq, ".php" ) + 1));
printf("Query = %s\n",query);
}
}
if (i == 1)
{
//check for 'HTTP' after 2nd space
if (strncmp(" HTTP", space, 5) != 0)
{
error(400);
return false;
}
//check for CRLF
if (strstr(space,"\r\n\0") == NULL)
{
error(400);
return false;
}
//store abs path in abs_path
int p = strlen(strchr(line,' ') + 1) - strlen(space);
strncpy(abs_path, strchr(line,' ') + 1, p);
abs_path[p] = '\0';
printf("Abs_path = %s\n", abs_path);
}
i++;
space = strchr(space+1, ' ');
}
//check for at most 2 spaces
if (i != 2)
{
error(400);
return false;
}
return true;
}
Lookup:
const char* lookup(const char* path)
{
// TODO
//find the last 'dot'
char* dot = strrchr(path,'.');
if (path != NULL)
{
if (strcasecmp(dot,".css") == 0)
{
return "text/css";
}
if (strcasecmp(dot,".html") == 0)
{
return "text/html";
}
if (strcasecmp(dot,".gif") == 0)
{
return "image/gif";
}
if (strcasecmp(dot,".ico") == 0)
{
return "image/x-icon";
}
if (strcasecmp(dot,".jpg") == 0)
{
return "image/jpeg";
}
if (strcasecmp(dot,".js") == 0)
{
return "text/javascript";
}
if (strcasecmp(dot,".php") == 0)
{
return "text/x-php";
}
if (strcasecmp(dot,".png") == 0)
{
return "image/png";
}
}
return NULL;
}
Load:
bool load(FILE* file, BYTE** content, size_t* length)
{
if (*content == NULL)
{
return false;
}
char* buffer = malloc(sizeof(char));
if(buffer == NULL)
{
return false;
}
int counter = 0;
int c = fgetc(file);
while(c != EOF)
{
buffer[counter] = (char) c;
counter++;
buffer = (char*) realloc(buffer, counter+1);
c = fgetc(file);
*content = buffer; // stores the address of the first of those bytes
*length = counter; // stores the number of bytes
printf("Data: %s\n", *content); // debugging - this works
printf("Length: %zu\n", *length); // debugging - this works
return true;
}
Indexes
char* indexes(const char* path)
{
//malloc space to contain directory path + index file name + null terminator
char* buffer = malloc(sizeof(char) * (strlen(path) + strlen("/index.html") + 1));
strcpy(buffer, path);
strcat(buffer,"/index.php");
FILE* fp = (fopen(buffer, "r"));
if (fp != NULL)
{
return buffer;
}
strcpy(buffer, path);
strcat(buffer,"/index.html");
if (fp != NULL)
{
return buffer;
}
free(buffer);
return NULL;
}