0

I just finished with the newest pset6 (2016), but I ran into a couple of problems that I don't know how to solve. My server seems to be working properly except the following errors I get on check50 server2 and on submit.

For the first of these four errors, my server returns the cat.jpg page, but it doesn't print the GET request and server response as it does for all the other tests. Any idea what is going on here?

Also, a file called cat.gif doesn't exist anywhere in my public directory. Do I have to add that file to make this work?

For the third, the server properly returns the hello.php page, but for some reason the program is triggering an exit code of 0. Not sure what is happening with this either, the only returning I did is true/false for the bool functions and a string for the char* function.

Finally, I'm not sure why the final test is failing. My server returns one page after the other when I test it in the browser?

Can anyone tell me why I am getting these errors?

:( Requesting cat.jpg returns 200, image/jpeg, and correct image
:( Requesting cat.gif returns 200, image/gif, and correct file
:( Requesting hello.php? returns 200, text/html, and correct output
    \ expected output, not an exit code of 0
:( Requesting two files in a row (cat.html then cat.jpg) succeeds

Here is my code:

Lookup:

const char* lookup(const char* path)
{
    if (strcasestr(path, ".css") != NULL)
    {
        return "text/css";
    }

    else if (strcasestr(path, ".html") != NULL)
    {
        return "text/html";
    }

    else if (strcasestr(path, ".gif") != NULL)
    {
        return "image/gif";
    }

    else if (strcasestr(path, ".ico") != NULL)
    {
        return "image/x-icon";
    }

    else if (strcasestr(path, ".jpg") != NULL)
    {
        return "image/jpeg";
    }

    else if (strcasestr(path, ".js") != NULL)
    {
        return "text/javascript";
    }

    else if (strcasestr(path, ".php") != NULL)
    {
        return "text/x-php";
    }

    else if (strcasestr(path, ".png") != NULL)
    {
        return "image/png";
    }

    else
        return NULL;
}

Parse:

bool parse(const char* line, char* abs_path, char* query)
{
    // get substrings ready
    char method[25];
    char version[25];

    // get pointers ready
    const char* version_ptr = NULL;
    const char* request_target_ptr = NULL;
    const char* qptr = NULL;

    // iterate through line to first space
    int i;
    for (i = 0; line[i] != ' '; i++)
    {
        method[i] = line[i];
    }

    // terminate string
    method[i] = '\0';

    // request target begins after this space
    request_target_ptr = &line[i + 1];

    // ensure that method is get
    if (strcasecmp(method, "get") != 0)
    {
        error(405);
        return false;
    }

    // ensure that request target begins with /
    if (*request_target_ptr != '/')
    {
        error(501);
        return false;
    }

    // we're good so far
    // begin iterating through request_target
    for (i = 0; request_target_ptr[i] != ' '; i++)
    {
        // watch for quote mark
        if (request_target_ptr[i] == '\"')
        {
            error(400);
            return false; 
        }

        // watch for "?"
        else if (request_target_ptr[i] == '?')
        {
            // we've possibly hit a query
            // let's save this space...
            qptr = &request_target_ptr[i + 1];
            break;
        }

        else
        {
            // we're still in abs_path
            abs_path[i] = request_target_ptr[i];
        }
    }

    // terminate abs_path
    abs_path[i] = '\0';

    // if we exited the loop because of a space, then html version starts here
    // this will change if there was a query
    version_ptr = &request_target_ptr[i + 1];

    // now we can see about that query...
    if (qptr != NULL)
    {
        // no query, terminate it
        if (*(qptr) == ' ')
        {
            query[0] = '\0';
        }

        // there's a query
        else
        {
            // get size
            for (i = 0; qptr[i] != ' '; i++)
            {
                // watch for quote mark again
                if (qptr[i] == '\"')
                {
                    error(400);
                    return false;
                }

                query[i] = qptr[i];
            }

            query[i] = '\0';

            // the html version begins after this space
            version_ptr = &qptr[i + 1]; 
        }   
    }

    // last thing that remains is to check the html version
    // so let's get the length of this thing
    for (i = 0; version_ptr[i] != '\r'; i++)
    {
        version[i] = version_ptr[i]; 
    }

    version[i] = '\0';

    // check version
    if (strcasecmp(version, "http/1.1") != 0)
    {
        error(505);
        return false;
    }

    return true;
}

Load:

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

    // create some space for the content
    content[0] = malloc(sizeof(BYTE) * BYTES);

    // keep track of the amount we're adding to this block of memory
    int size = 0;

    // keep track of substrings
    int substr = 0;

    char c;
    while((c = fgetc(file)) != EOF)
    {
        size++;
        if (size == 512)
        {
            substr++;
            content[substr] = realloc(*content, sizeof(BYTE) * BYTES);
            size = 0;
        }

        content[substr][size - 1] = c;
    }

    *length = size;
    return true;
}

Indexes:

char* indexes(const char* path)
{
    DIR* dir;
    struct dirent *ent;

    char* new_path = NULL;

    if ((dir = opendir (path)) != NULL) 
    {
        while ((ent = readdir(dir)) != NULL) 
        {
            if (strcmp(ent -> d_name, "index.php") == 0)
            {
                new_path = malloc(sizeof(BYTE) * strlen(path) + strlen("/index.php") + 1);
                new_path = strcpy(new_path, path);
                new_path = strcat(new_path, "/index.php");
            }

            else if (strcmp(ent -> d_name, "index.html") == 0)
            {
                new_path = malloc(sizeof(BYTE) * strlen(path) + strlen("/index.html") + 1);
                new_path = strcpy(new_path, path);
                new_path = strcat(new_path, "/index.html");
            }
        }

        closedir(dir);
    }

    return new_path;
}

1 Answer 1

1

load(). Scope. Pointers. Remember, when you return to the caller (main), you don't expect the address of content to be different, only the contents of content. Since &content is passed to load, this line content[0] = malloc(sizeof(BYTE) * BYTES); changes that address (and the reallocs change it again). This line from the spec applies:

  1. stores the address of the first of those bytes in *content, and

Bottom line, you should only be changing the contents of content, not the address of content.

As an aside, I would venture to say that this syntax content[0] is wrong. content is an address, after all, not string data or array data. Also, a line like this buffer[substr] = realloc(*buffer, sizeof(BYTE) * BYTES); is sticking a pointer in the middle of a buffer, not allocating more memory to the buffer pointer.

There may be other problems in other functions, but this explains at least the first two check50 fails.

You do not need to add cat.gif to your directory, check50 uses its own data.

8
  • 1
    Thanks! This is precisely the advise I needed. I have a hard time seeing these types of errors. I'll take a spin through my code and watch closely for the problems with scope and pointers you have pointed out. Thanks again!
    – LeviJames
    Commented Apr 13, 2016 at 16:49
  • Wait - looking at this more closely, isn't content[0] dereferencing content the same as *content would? I get what you are saying that it is the wrong syntax, but still, isn't it just changing the value at &content rather than the address of content itself?
    – LeviJames
    Commented Apr 13, 2016 at 20:30
  • It is the value of &content (the one in main), not the value at &content. Sorta like a linked list? content->address->data. load needs to change the data that address points to. content[0] is the first byte of address. But *content is a pointer to the data. I hope that didn't make it worse : ) Commented Apr 13, 2016 at 20:57
  • YES. That made total sense and I figured it out. Also, I found it's a lot easier to get the length of the file first then read to contents to an appropriately sized buffer, then just make *content point to that new data. Thanks for helping me figure this one out. I am still getting this error: :( Requesting hello.php? returns 200, text/html, and correct output \ expected output, not an exit code of 0 And don't know what to make of it.
    – LeviJames
    Commented Apr 13, 2016 at 21:49
  • is check50 server1 clean? Commented Apr 13, 2016 at 22:08

You must log in to answer this question.

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