0

I'm almost through the end of debugging my Pset 6 (Server) code. The server now implements cat.jpg and cat.html properly, but I'm still facing trouble when I try to insert anything into hello.html. I don't get much info from Chrome since it says in the network tab that the status is 200. Anyway, when I try to put any name in hello.html, I get this error in Chrome:

enter image description here

And here's what I get in my terminal window:

GET /hello.html HTTP/1.1
HTTP/1.1 200 OK
GET /hello.php?name=Alice HTTP/1.1
PHP Notice:  Undefined index: name in /home/jharvard/Dropbox/pset6/public/hello.php on line 8
PHP Stack trace:
PHP   1. {main}() /home/jharvard/Dropbox/pset6/public/hello.php:0
HTTP/1.1 200 OK

Here's all the relevant code that I wrote:

            // TODO: validate request line

            // mark up white spaces in line string
            int first_space = 0, second_space = 0, extra_space = 0;
            for (int i = 0, length = strlen(line); i < length; i += 1)
            {
                if ((line[i] == ' ') && (first_space == 0))
                {
                    first_space = i;
                }
                else if ((line[i] == ' ') && (second_space == 0))
                {
                    second_space = i;
                }
                else if ((line[i] == ' ') && (second_space != 0) && (first_space != 0))
                {
                    extra_space = i;
                }
            }

            // test for error(400)
            if ((extra_space != 0) || (first_space == 0) || (second_space == 0) || (line[strlen(line) - 2] != '\r') || (line[strlen(line) - 1] != '\n'))
            {
                error(400);
            } 

            // make sure method is GET
            char method[first_space + 1];
            for (int i = 0; i < first_space; i += 1)
            {
                method[i] = line[i];
            }
            method[first_space] = '\0';
            if (strcmp(method, "GET") != 0)
            {
                error(405);
            }

            // make sure request-target begins with a /
            if (line[first_space + 1] != '/')
            {
                error(501);
            }

            // make sure request-target does not contain a "
            for (int i = first_space + 1; i < second_space; i += 1)
            {
                if (line[i] == '"')
                {
                    error(400);
                }
            }

            // make sure http version is 1.1
            char http_version[9];
            for (int i = second_space + 1, j = 0; j < 8; i += 1, j+= 1)
            {
                http_version[j] = line[i];
            }
            http_version[8] = '\0';
            if (strcmp(http_version, "HTTP/1.1") != 0)
            {
                error(505);
            }

            // make sure absolute-path contains a . (for the file extension)
            bool found_extension = false;
            int extension_index = 0;
            int start_of_query = 0;
            int length_absolute_path = 0;
            for (int i = first_space + 1; i < second_space; i += 1)
            {
                length_absolute_path += 1;
                if (line[i] == '.')
                {
                    extension_index = i;
                    found_extension = true;
                }
                else if (line[i] == '?')
                {
                    length_absolute_path -= 1;
                    start_of_query = i;
                    break;
                }
            }
            if (!found_extension)
            {
                error(501);
            }

            // TODO: extract query from request-target
            char query[second_space - start_of_query];
            if ((start_of_query != 0) || (start_of_query + 1 != second_space))
            {
                for (int i = start_of_query, j = 0; (i < second_space) && (i + 1 < second_space); i += 1, j += 1)
                {
                    query[j] = line[i];
                }
                query[second_space - start_of_query] = '\0';
            } 
            if ((start_of_query == 0) || (start_of_query + 1 == second_space))
            {
                query[0] = '\0';
            }

            // TODO: concatenate root and absolute-path
            char path[strlen(root) + length_absolute_path + 1];
            strcpy(path, root);
            for (int i = first_space + 1, j = strlen(root); i < first_space + length_absolute_path + 1; i++, j++)
            {
                path[j] = line[i];
            }
            path[strlen(root) + length_absolute_path] = '\0';

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

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

            // TODO: extract path's extension
            char extension[10];
            int markup_number;
            for (int i = first_space + (extension_index - first_space) + 1, j = 0; (line[i] != '?') && (i < second_space); i += 1, j += 1)
            {
                extension[j] = line[i];
                markup_number = j + 1;
            } 
            extension[markup_number] = '\0';

            // dynamic content
            if (strcasecmp("php", extension) == 0)
            {
                // open pipe to PHP interpreter
                char* format = "QUERY_STRING=\"%s\" REDIRECT_STATUS=200 SCRIPT_FILENAME=\"%s\" php-cgi";
                char command[strlen(format) + (strlen(path) - 2) + (strlen(query) - 2) + 1];
                sprintf(command, format, query, path);
                file = popen(command, "r");
                if (file == NULL)
                {
                    error(500);
                    continue;
                }

                // load file
                ssize_t size = load();
                if (size == -1)
                {
                    error(500);
                    continue;
                }

                // subtract php-cgi's headers from body's size to get content's length
                haystack = body;
                needle = memmem(haystack, size, "\r\n\r\n", 4);
                if (needle == NULL)
                {
                    error(500);
                    continue;
                }
                size_t length = size - (needle - haystack + 4);

                // respond to client
                if (dprintf(cfd, "HTTP/1.1 200 OK\r\n") < 0)
                {
                    continue;
                }
                if (dprintf(cfd, "Connection: close\r\n") < 0)
                {
                    continue;
                }
                if (dprintf(cfd, "Content-Length: %i\r\n", length) < 0)
                {
                    continue;
                }
                if (write(cfd, body, size) == -1)
                {
                    continue;
                }
            }

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

                // open file
                file = fopen(path, "r");
                if (file == NULL)
                {
                    error(500);
                    continue;
                }

                // load file
                ssize_t length = load();
                if (length == -1)
                {
                    error(500);
                    continue;
                }

                // TODO: respond to client
                if (dprintf(cfd, "HTTP/1.1 200 OK\r\n") < 0)
                {
                    continue;
                }
                if (dprintf(cfd, "Connection: close\r\n") < 0)
                {
                    continue;
                }
                if (dprintf(cfd, "Content-Length: %i\r\n", length) < 0)
                {
                    continue;
                }
                if (dprintf(cfd, "Content-Type: %s\r\n\r\n", type) < 0)
                {
                    continue;
                }
                if (write(cfd, body, length) == -1)
                {
                    continue;
                }
            }

            // announce OK
            printf("\033[32m");
            printf("HTTP/1.1 200 OK");
            printf("\033[39m\n");
        }
    }
}


/**
 * Returns MIME type for supported extensions, else NULL.
 */
const char* lookup(const char* extension)
{
    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("ico", extension) == 0)
    {
        return "image/x-icon";
    }
    else if (strcasecmp("jpg", extension) == 0)
    {
        return "image/jpeg";
    }
    else if (strcasecmp("js", extension) == 0)
    {
        return "text/javascript";
    }
    else if (strcasecmp("png", extension) == 0)
    {
        return "image/png";
    }
    else
    {
        return NULL;
    }
}

Thank you everyone in advance!

2
  • You should yourself remove any unnecessary code. It's to your advantage to post small snippets of code instead that huge sheet of code. It discourages anyone who wants to help you.
    – ChrisG
    Jul 19 '15 at 8:08
  • You're right Chris, sorry about that. I just thought I'd include the whole code so that it's all there in one place for anyone who doesn't have the rest of the code on them or something. Sorry again! :)
    – Xiggi
    Jul 19 '15 at 11:56
1

Ok, a friend helped me and I knew what the problem was. Turns out that when I extracted the query, I included the '?' symbol with it and that messed everything up, including the for loop and everything in that part of the code. Here's the code that I corrected in case someone is facing the same problem:

            // TODO: extract query from request-target
            char query[(second_space - start_of_query) + 1];
            if ((start_of_query != 0) && (start_of_query != second_space))
            {
                for (int i = start_of_query, j = 0; i < second_space; i += 1, j += 1)
                {
                    query[j] = line[i];
                }
                query[second_space - start_of_query] = '\0';
            } 
            if ((start_of_query == 0) || (start_of_query == second_space))
            {
                query[0] = '\0';
            }
-1

The problem lies in the hello.php. It wants to give a parameter name which is not in the get call to server. Just change hello.php htmlspecialchars($_GET["name"]) to htmlspecialchars($_GET["q"]) and everything works as described.

1
  • Sorry, I was frustrated. I asked the question on FB group and got the answer. The problem lies on the hello.php. It wants to give a parameter name which is not in the get call to server. Just change hello, <?= htmlspecialchars($_GET["name"]) ?> to hello, <?= htmlspecialchars($_GET["q"]) ?> and everything works as described. Sep 19 '15 at 10:22

You must log in to answer this question.

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