1

@curiouskiwi, Thanks a lot....your response helped a lot. I wonder why I missed out such little detail. However guys, I have another problem which I believe am missing out something but can not seem to figure out what am missing out. The problem is that I am getting "HTTP/1.1 501 Not Implemented" when I run 192.#.#.#:port#/cat.jpg. I am trying to implement the question "if absolute-path does not contain a . (and thus a file extension), respond to the browser with 501 Not Implemented." and below is my code. I am VERY certain that check_request[1] is "/cat.jpg " as I have used printf to poke around my code but I still keep getting the 501 not implemented error message. Please another help would be much appreciated.

            if(strchr(check_request[1], '?') != NULL)
            {
                check_request[1] = strtok(check_request[1], "?");

                if(strstr(check_request[1], ".") == NULL)
                {
                    error(501);
                    continue;
                }   
            }

            else if(strstr(check_request[1], ".") == NULL)
            {

                error(501);
                continue;
            }

@Cliff B, I had to abandon this pset and move on to pset7 but am done and am back and still experiencing the same issue but can't seem to figure out what were the error is coming from. I have spent hours poking around with printf but still no luck. Below is my code as requested please help look through as i may be missing out something but can seem to figure out what is missing. PLEASE any one out there with a helping answer can please help as am loosing steam

// TODO: validate request-line

            char* check_request[5] = {NULL};
            int i = 1;

            //store the method type
            check_request[0] = strtok(line, " ");

            //store the request-target and http version
            while(i < 4)
            {
                check_request[i] = strtok(NULL, " ");
                i++;
            }

            char temp[strlen(check_request[1])]; //declared to store absolute path            
            strcpy(temp, check_request[1]); // Storing absolute

            //Ensure the method type is get
            if(strcasecmp(check_request[0], "GET") != 0)
            {
                error(405);
                continue;
            }
            //Check if the request target begins with "/" character
            if(strstr(&line[4], "/") == NULL)
            {
                error(501);
                continue;     
            }
            //Check if the request-target contains '"'
            if(strchr(check_request[1], '"') != NULL)
            {
                error(400);
                continue;         
            }

            char http_version[9];

            for(int i = 0; i < 8; i++) //copy the http version into memory
            {
                http_version[i] = check_request[2][i];
            }

            http_version[8] = '\0'; //Add the required NULL to terminate the copied string

            //Now is to check if the http version is "HTTP/1.1"
            if(strncasecmp(check_request[2], http_version, 8) != 0)
            {
                error(505);
                continue;     
            }

            if(strchr(check_request[1], '?') != NULL)
            {
                check_request[1] = strtok(check_request[1], "?");

                if(strstr(check_request[1], ".") == NULL)
                {
                    error(501);
                    continue;
                }   
            }

            else if(strstr(check_request[1], ".") == NULL)
            {

                error(501);
                continue;
            }

        // TODO: extract query from request-target

        check_request[3] = strtok(check_request[1], "?");
        check_request[4] = strchr(temp, '?');
        char query[1];

        if((strchr(check_request[1], '?') == NULL) || (strstr(check_request[3], ".php") == NULL))
        {
            query[0] = '\0';
        }

        if(check_request[4] != NULL)
        {
            char query[strlen(check_request[4]) + 1];
            strcpy(query, check_request[4]);
        }

        // TODO: concatenate root and absolute-path 

        strcat(root, check_request[3]);   
        char path[strlen(temp)];
        strcpy(path, root);

        // TODO: ensure path exists
        if(access(path, F_OK) != 0)
        {
            error(404);
            continue;
        }

        // TODO: ensure path is readable
        if(access(path, R_OK) != 0)
        {
            error(403);
            continue;
        }

        // TODO: extract path's extension
        check_request[1] = strrchr(path, '.');
        check_request[2] = strtok(check_request[1], ".");
        char extension[strlen(check_request[1])];
        strcpy(extension, check_request[1]);
4
  • Any one with an answer? please help me out I really need to get pass this stage and move on to other psets
    – nezechi
    Commented Aug 19, 2015 at 6:27
  • is it working with .html? I'm also stuck.
    – Mustaghees
    Commented Aug 29, 2015 at 16:10
  • There are several conditions in the code that will cause a 501 to be returned. Have you isolated with certainty which one is being executed in your code? Also, could you post all of the related code to this - anything that sets or changes check_request? I assume from the usage that check_request[] is an array of strings, not just a string array?
    – Cliff B
    Commented Sep 8, 2015 at 0:08
  • The good news is that you are not far from a working server!
    – Sam Gerber
    Commented Sep 21, 2015 at 5:21

1 Answer 1

0

Using GDB, I found three problem areas in the code.

1.) root is updated to entire filepath, and memory issues

        // TODO: concatenate root and absolute-path 
        strcat(root, check_request[3]);   
        char path[strlen(temp)];
        strcpy(path, root);

You have concatenated the path onto the end of root, thereby altering root to: /home/jharvard/Dropbox/pset6/public/cat.jpg, for example. By doing this, you break the root for any further iterations. As a result, if you make a second request it will return 404 as it cannot find the file, which would by that time read something like /home/jharvard/Dropbox/pset6/public/cat.jpg/cat.jpg.

You may also end up with a memory issue, because when start() executes this line: root = realpath(path, NULL);, it only reserves enough memory for the length of root, so if you make it longer, you might be writing bytes that are allocated to something else.

To resolve this issue, first copy the root into the path, then concatenate the path and the absolute-path.

        // Concatenate strings
        char path[ /*TODO*/ ]; //see comment below
        strcpy ( path, root);
        strcat ( path, check_request[3]);

While we're thinking about it, though, we should make sure we have allotted enough space in path to hold the root and the absolute path, so we don't end up with another memory issue. Above you had declared path to have strlen(temp) elements. Looking back at temp:

        char temp[strlen(check_request[1])]; //declared to store absolute path 

you declared it to have strlen(check_request[1]) elements at a time when check_request[1] contained "/cat.jpg". strlen("/cat.jpg") is 8, and so, temp and path are only allocated 8 bytes each. It's fine for temp to be the same number of bytes as check_request[1], because that's all you ever put into it, but you need to allocate enough space in path to fit "/home/jharvard/Dropbox/pset6/public/cat.jpg". You should be able to do that if you know the length of root.

PS- on one run-through of the code, something was assigned memory just next to check_request, and check_request[0] was overwritten with "lic/cat.jpg"

(gdb) p check_request
$1 = {0xbfffeef0 "lic/cat.jpg", 0xbfffeef4 "cat.jpg", 0xbfffeefd "HTTP/1.1\r\n", 0xbfffeef4 "cat.jpg", 0x0}

2.) extension includes "." while literals do not (".jpg" vs "jpg" )

        // TODO: extract path's extension
        check_request[1] = strrchr(path, '.');
        check_request[2] = strtok(check_request[1], ".");
        char extension[strlen(check_request[1])];
        strcpy(extension, check_request[1]);

it looks like you just forgot to update your indices:

        // TODO: extract path's extension
        check_request[1] = strrchr(path, '.');
        check_request[2] = strtok(check_request[1], ".");
        char extension[strlen(check_request[2])];
        strcpy(extension, check_request[2]);

This will store "jpg" in extension, instead of ".jpg".

As it is, I suspect lookup() is returning NULL (when I ran your validation with my implementation of lookup, it did, anyway). It would do this if you are comparing ".jpg" to "jpg". As a result, this code in main will throw your 501:

            // look up file's MIME type
            const char* type = lookup(extension);
            if (type == NULL)
            {
                error(501);
                continue;
            }

3.) Query extraction fails - Variable scope & "?name=Alice" vs "name=Alice"

When we first enter your code, we can see from GDB:

(gdb) p check_request
$2 = {0xbfffeee0 "GET", 0xbfffeee4 "/hello.php?name=1", 0xbfffeef6 "HTTP/1.1\r\n", 0x0, 0x0}

Then you hit this code:

        if(strchr(check_request[1], '?') != NULL)
        {
            check_request[1] = strtok(check_request[1], "?");

            if(strstr(check_request[1], ".") == NULL)
            {
                error(501);
                continue;
            }   
        }

Which updates check_request to:

(gdb) p check_request
$8 = {0xbfffeee0 "GET", 0xbfffeee4 "/hello.php", 0xbfffeef6 "HTTP/1.1\r\n", 0x0, 0x0}

Then we hit these three lines:

        // TODO: extract query from request-target

        check_request[3] = strtok(check_request[1], "?");
        check_request[4] = strchr(temp, '?');
        char query[1];

Luckily, temp still has the query information, so now:

(gdb) p check_request
$10 = {0xbfffeee0 "GET", 0xbfffeee4 "/hello.php", 0xbfffeef6 "HTTP/1.1\r\n", 0xbfffeee4 "/hello.php", 0xbfffeeca "?name=1"}

So, now check_request[4] contains your query.

I'm not sure what the if statement below checks for, but it looks like it will evaluate to TRUE unless the file isn't php AND there's more than one '?' in the request-target.

        if((strchr(check_request[1], '?') == NULL) || (strstr(check_request[3], ".php") == NULL))
        {
            query[0] = '\0';
        }

The second if statement below will execute if there's a question mark in the request-target. It defines a new query string and writes "?name=Alice" into it. if(check_request[4] != NULL) { char query[strlen(check_request[4]) + 1]; strcpy(query, check_request[4]); }

On exiting the if statement, the local query, which you defined inside the if statement, is lost, and any subsequent calls to query go to the one-character null one that was declared inside if(connected() scope).

237  
(gdb) p query
$16 = ""

Also, be sure to remove the '?' from the beginning of query, once you've sorted out the above issues. Use something like what you did to get rid of the '.' in front of "jpg".

There's still some room for implementation and clean up here, so I'm not going to dig any deeper on this iteration. If you need any help on using GDB, let me know; you'll likely get more mileage out of it than printf.

HTH


If this answers your question please accept it by clicking the gray check-mark to the left, so that it becomes green. You can also vote it up by pressing the up arrow above the check-mark

0

You must log in to answer this question.

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