0

I fixed some issues in this but I am still getting errors and can't figure out what is causing them.

:( Requesting cat.exe returns error code 501
Expecting the following on standard out ... 501 NOT IMPLEMENTED
... but received the following on standard out instead —
HTTP/1.1 200 OK Content-Type: image/png

I ran cat.exe through GDB and didn't get what this check suggests.

:( Two spaces after GET returns error code

I'm not sure whether I am meant to search for multiple spaces then return error because I didn't see this on the specs or whether something else is causing this.

:( Requesting /test/ outputs /test/index.html

When running /test/ it seems to return the path to index.html. It says "todo".

:( Requesting directory containing index.php outputs index.php

Not at all sure what I need to do to fix this.

INDEXES

char* indexes(const char* path)
{
    char* temp_path = malloc(strlen(path) + 1);
    memcpy(temp_path, path, strlen(path) + 1);

    char* php_index = "/index.php";
    char* html_index = "/index.html";

    char* php_path = malloc(strlen(path) + strlen(php_index) + 1);
    char* html_path = malloc(strlen(path) + strlen(html_index) + 1);

    memcpy(php_path, temp_path, strlen(path) + 1);
    memcpy(html_path, temp_path, strlen(path) + 1);

    strcat(php_path, php_index);
    strcat(html_path, html_index);

    if(access(php_path, F_OK) != -1)
    {
        return php_path;
    }
    else if(access(html_path, F_OK) != -1)
    {
        return html_path;
    }
    else
    {
        return NULL;
    }
}

LOAD

bool load(FILE* file, BYTE** content, size_t* length)
{
    if(file == NULL)
    {
        return false;
    }

    int expand = 2;
    char* storage = malloc(sizeof(char) * expand);   // Begin with a small amount of memory.
    int c;
    int byte_count = 0;

    while(( c = fgetc(file)) != EOF)      // Get one char at a time from file.
    {
        storage[byte_count] = c;         // Store contents of file in storage.
        byte_count++;

        if(byte_count == expand - 1)      // Expand exponentially if we only have one byte of memory left.
        {
            expand *= expand;
            storage = realloc(storage, sizeof(char) * expand);
        }
    }
    storage = realloc(storage, (sizeof(char) * byte_count) + 1); // Realloc correct size once reading is complete.
    *content = storage;      // Store pointer to 
    *length = byte_count;    // Store number of bytes

    return true;
}

LOOKUP

const char* lookup(const char* path)
{
    char extension[6];

    char* css = ".css";
    char* html = ".html";
    char* gif = ".gif";
    char* xicon = ".ico";
    char* jpeg = ".jpg";
    char* java = ".js";
    char* php = ".php";
    char* png = ".png";

    char* location = strrchr(path, '.');
    int i = 0;

    while(location[i] != '\0')
    {
        extension[i] = location[i];
        i++;
    }

    if(strcasecmp(css, extension) == 0)
    {
        return "text/css";
    }
    else if(strcasecmp(html, extension) == 0)
    {
        return "text/html";
    }
    else if(strcasecmp(gif, extension) == 0)
    {
        return "image/gif";
    }
    else if(strcasecmp(xicon, extension) == 0)
    {
        return "image/x-icon";
    }
    else if(strcasecmp(jpeg, extension) == 0)
    {
        return "image/jpeg";
    }
    else if(strcasecmp(java, extension) == 0)
    {
        return "text/javascript";
    }
    else if(strcasecmp(php, extension) == 0)
    {
        return "text/x-php";
    }
    else if(strcasecmp(png, extension))
    {
        return "image/png";
    }
    else
    {
        return NULL;
    }
}

PARSE

bool parse(const char* line, char* abs_path, char* query)
{

    char line_copy[LimitRequestLine + 1];
    strcpy(line_copy, line);                       // Copy line for manipulation
    char* method = strtok(line_copy, " ");    // Parse at first space to get method

    if(strcmp(method, "GET") != 0)     // Check method is 'GET'. If not return error.
    {
        error(405);
        return false;
    }

    char* req_target = strtok(NULL, " ");            // Parse at second space to get abs_path

    if(req_target[0] != '/')
    {
        error(501);
        return false;
    }

    if(strchr(req_target, '"') != NULL)
    {
        error(400);
        return false;
    }

    char* version = strtok(NULL, "");            

    if(strncmp(version, "HTTP/1.1", 8) != 0)
    {
        error(505);
        return false;
    }

    if(strchr(req_target, '?') != NULL)
    {
        char* temp = strtok(req_target, "?");
        strcpy(abs_path, temp);

        temp = strtok(NULL, "");
        if(temp != NULL)
        {
            strcpy(query, temp);
        }
    }

    else
    {
        strcpy(abs_path, req_target);
        query = "";
    }
    return true;
}
1

:( Requesting cat.exe returns error code 501
This HTTP/1.1 200 OK Content-Type: image/png (the png part) is probably a great clue, and points to lookup. Do you get a 404 when you run with gdb? That would be expected because you do not have a cat.exe file. Meanwhile, check50 does. Create a cat.exe file (simply copy cat.html to cat.exe). Then you should get the same result in gdb, which should help you find the problem.

:( Two spaces after GET returns error code

This is implicit in the spec.

Per 3.1.1 of http://tools.ietf.org/html/rfc7230, a request-line is defined as
method SP request-target SP HTTP-version CRLF

A valid request line has at most 2 non-consecutive spaces. strtok is usually involved when this test fails because it treats consecutive delimiters as one. Your approach to search for multiple spaces sounds good. strstr might be just the thing.

:( Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php

TODO is the response from check50. Green means passed, red means failed. Indexes looks solid. (Full disclosure: I ran my server with your indexes and it passed check50). These failures could indicate a memory allocation problem somewhere else in the program. Of course, I'm immediately drawn to this storage = realloc(storage, sizeof(char) * expand);. If file is bigger than 255 bytes, storage will be allocated for 65535, at least temporarily. Not saying good, bad or indifferent. Just got my attention.

I can only offer a troubleshooting strategy. First, copy hello.html to index.html. (hello.html is 316 bytes). If indexes is working properly, "hello.html" should be returned when you contact the web server, instead of the directory listing. (It looks like hello.html, but it will show index.html in the address bar). If that isn't the case, you might need gdb. Otherwise, restart server under valgrind. This command line valgrind -v --leak-check=full --show-leak-kinds=all --track-origins=yes is handy because it gives lots of feedback. You might want to send a curl request (curl -i http://localhost:8080) instead of a browser request so favicon isn't a factor. ctrl-C to end server, and see if the valgrind report sheds any light on this problem.

4
  • Thank you again for your help I have all smiling faces now :) But I would like to learn from the errors I made as I am still not 100% sure what caused them. The png error was simple, I left out "== 0". The last two errors were actually in parse. Valgrind helped me find them using the line you give me. It was the char array extension[] that I used caused the problem. I realised I didn't need that anyway but why did it fail on that? The two blank spaces I used a bad method to get around that. I'm not sure I understand how I would use strstr along with strtok to fix that issue? Sep 14 '16 at 23:17
  • My idea for strstr was if (strstr(line," ") != NULL {give error} nothing to do with strtok, really, just an additional test. I could see extension giving errors in valgrind because it is not null-terminated, and used in a string function. I cannot immediately see how that would cause the index failures in check50. I only see extension in the lookup function, so your comment "the last two errors were actually in parse" confuses me. Sep 14 '16 at 23:36
  • I wasn't able to work out how to do it that way because strstr(line, " ") would return a pointer to the first space which is legal. If I called it again it would find a second space anyway because two spaces are allowed in the request so I wasn't sure how to use it that way. I managed to fix it by changing if(req_target[0] != '/') to line[4] instead which made sure no extra characters were in-between. And sorry I apologise yes the last two errors were in lookup. Sep 15 '16 at 0:05
  • I knew it was a tough visual. I meant strstr(line,"spacespace") Sep 15 '16 at 0:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .