1

Need HELP!

I've nearly done pset6 but there are some bugs. I can't figure out what's wrong.I think there might be some bugs in load and parse functions. Maybe somethink with Segmentation fault.

Server.c compiles without errors.

check50 2015.fall.pset6.server1 server.c
:) server.c exists
:) server compiles
:) HTTP/1.0 returns error code 505
:) Method of 'abcGET' returns error code 405
:) Method of 'GETabc' returns error code 405
:) request-target without starting '/' returns error code 501
:) request-target of abc/hello.php returns error code 501
:) Requesting cat.exe returns error code 501
:) Requesting non-existant file returns error code 404
:) Requesting request-target with " returns error code 400
:) Two spaces after GET returns error code
:) A space within the request target returns error code
:) Two spaces before HTTP/1.1 returns error code
[https://sandbox.cs50.net/checks/c6ae33faed714fbbae57dc8f77f1f0ea][1]

check50 2015.fall.pset6.server2 server.c
:) server.c exists
:) server compiles
:) Requesting cat.jpg returns 200, image/jpeg, and correct image
:) Requesting cat.html returns 200, text/html, and correct file
:) Requesting cat2.HTML returns 200, text/html, and correct file
:) Requesting cat3.HtMl returns 200, text/html, and correct file
:) Requesting cat.gif returns 200, image/gif, and correct file
:) Requesting favicon.ico returns 200, image/x-icon, and correct file
:) Requesting test.css returns 200, text/css, and correct file
:) Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:) Requesting hello.php? returns 200, text/html, and correct output
:( Requesting hello.php?name=Alice returns 200, text/html, and correct output
   \ killed by server
:) Requesting /test redirects to /test/
:) Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php
   \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
:) Requesting two files in a row (cat.html then cat.jpg) succeeds
[https://sandbox.cs50.net/checks/7715525226c342f2b48d5d4fdfa0f855][1]

When I run valgrind and curl sometimes it says segmentation fault.

curl http://localhost:8080/hello.php
curl: (52) Empty reply from server
--------
Starting program: /home/ubuntu/workspace/pset6/server -p8080 public
Using /home/ubuntu/workspace/pset6/public for server's root
Listening on port 8080
GET /hello.html HTTP/1.1
HTTP/1.1 200 OK
GET /hello.html HTTP/1.1
HTTP/1.1 200 OK
GET /hello.html HTTP/1.1
HTTP/1.1 200 OK
GET /hello.html HTTP/1.1
HTTP/1.1 200 OK
GET /hello.php HTTP/1.1

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7780b6e in _IO_getc (fp=0x607150) at getc.c:39
39      getc.c: No such file or directory.
(gdb) q
A debugging session is active.
Inferior 1 [process 5320] will be killed.

Here are functions: indexes

char* indexes(const char* path)
{
    // TODO
    //1. create tmp strings for indexes
    //2. create tmp links from path
    //3. copy indexes to links
    //4. check wether link exists if true respond 
    //else return NULL

    char* result = NULL;
    char indexphp[] = "/index.php";
    char indexhtml[] = "/index.html";

    int path_lenght = strlen(path) + 1;

    char* linkphp = malloc(path_lenght + strlen(indexphp) + 1);
    strcpy(linkphp, path);
    strcat(linkphp, indexphp);

    char* linkhtml = malloc(path_lenght + strlen(indexhtml) + 1);
    strcpy(linkhtml, path);
    strcat(linkhtml, indexhtml);

    result = (access(linkphp, F_OK) != -1) ? linkphp : NULL;
    if (result != linkphp)
        free(linkphp);

    result = (access(linkhtml, F_OK) != -1) ? linkhtml : NULL;
    if (result != linkhtml)
        free(linkhtml);

    return result;
}

load

bool load(FILE* file, BYTE** content, size_t* length)
{
    // TODO

    BYTE* buffer = NULL;
    size_t byte_length = 0;
    size_t count_length = 0;

    //get the length of file in bytes
    fseek(file, 0, SEEK_END);
    byte_length = ftell(file);
    fseek(file, 0, SEEK_SET);

    //allocating memory for buffer
    buffer = malloc(byte_length + 1);

    //and now read file
    //fread(buffer, 1, byte_length, file);

    for(int i = 0; i < byte_length; i++)
    {

        buffer[i] = fgetc(file);

        count_length++;
    }

    *length = count_length;
    *content = buffer;

    return true;

}

parse

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

    if(strncmp(line, "GET ", 4) != 0)
    {
        error(405);
        return false;
    }

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

    //point haystack to the start of request_target and needle to the end
    char* haystack = strchr(line, '/');
    char* needle = strchr(haystack, ' ');
    char* http_vers = needle;

    if(strncmp(http_vers, " HTTP/1.1\r\n", 10) != 0)
    {
        error(505);
        return false;
    }

    //copy request target and create var for query
    char request_target[needle - haystack + 1];
    strncpy(request_target, haystack, needle - haystack);
    request_target[needle - haystack] = '\0';

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

    //if query not exist in request_target then copy only request_target to abs_path else copy query and abs_path
    haystack = request_target;
    needle = strchr(haystack, '?');
    if(needle == NULL)
    {
        strcpy(abs_path, haystack);
        query[0] = '\0';
    }
    else if(strlen(needle) == 1)
    {
        strncpy(abs_path, haystack, needle - haystack);
        query[0] = '\0';
    }
    else if (needle != NULL && strlen(needle) > 1)
    {
        //copy abs_path
        char path[needle - haystack + 1];
        strncpy(path, haystack, needle - haystack);
        path[needle - haystack] = '\0';
        strcpy(abs_path, path);
        //copy query
        strcpy(query, needle + 1);
        printf("test\n");
    }

    return true;
}

lookup

const char* lookup(const char* path)
{

    // TODO
    //search for . in the string if found copy last three letters to fyletype

    char* filetype;
    const char dot = '.';

    filetype = strrchr(path, dot);
    if (filetype == NULL)
        {
            return NULL;
        }

    //using strcasecmp() to compare two strings ignoring case and assign return value to result
    if(strcasecmp(filetype, ".css") == 0)
    {
        return "text/css";
    }
    else if(strcasecmp(filetype, ".html") == 0)
    {
        return "text/html";
    }
    else if(strcasecmp(filetype, ".gif") == 0)
    {
        return "image/gif";
    }
    else if(strcasecmp(filetype, ".ico") == 0)
    {
        return "image/x-icon";
    }
    else if(strcasecmp(filetype, ".jpg") == 0)
    {
        return "image/jpeg";
    }
    else if(strcasecmp(filetype, ".js") == 0)
    {
        return "text/javascript";
    }
    else if(strcasecmp(filetype, ".php") == 0)
    {
        return "text/x-php";
    }
    else if(strcasecmp(filetype, ".png") == 0)
    {
        return "image/png";
    }
    else 
    {
        return NULL;
    }
}
1

I can tell you one problem right away. This part won't work with pipe streams like php files:

//get the length of file in bytes
    fseek(file, 0, SEEK_END);
    byte_length = ftell(file);
    fseek(file, 0, SEEK_SET);

To get the load() function working correctly 100% of the time, one usually needs to read from the stream progressively and use realloc() when needed.

DinoCoderSaurus gave some advice about it here: pset6 (webserver) - hello.php not loading properly


EDIT to tackle index.php problem:

Look what's happening here:

result = (access(linkphp, F_OK) != -1) ? linkphp : NULL;
if (result != linkphp)
    free(linkphp);

result = (access(linkhtml, F_OK) != -1) ? linkhtml : NULL;
if (result != linkhtml)
    free(linkhtml);

return result;

Now suppose there is a file called index.php inside the directory. That first part of the code will make the variable result point to linkphp, but you don't return it, so the computer proceeds to analyze the rest of the code.

What comes next? Well, it checks for the existence of index.html... and let's suppose it doesn't exist. result will now point to NULL.

At the end of the function, NULL will be returned, even though the correct answer would be to return linkphp. See the problem there?

3
  • Thank you for advice! I,ve changed code to use fgetc. Now I have only one error, but there is now index.php in any directory. :( Requesting directory containing index.php outputs index.php \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
    – N. Kat
    Nov 7 '16 at 10:07
  • Ok @N.Kat. I have updated the answer to give some hints about the final problem. And know this: check50 is not testing YOUR directories. It's testing THE STAFF's directories using your server.c file Nov 7 '16 at 11:00
  • YES! Thank you very much. Now it works! Before reading your second comment I've wrote second indexes funtion. The other thing I've discovered using GDB is that in first function I didn't check for extra slash '/'. So my paths looked like this linkphp = 0x6070e0 "/home/ubuntu/workspace/pset6/public/test//index.php" linkhtml = 0x607120 "/home/ubuntu/workspace/pset6/public/test//index.html" Even if they have double slashes '//' it still works. In second function I've implemented that check. I'll post them in my second answer. Both functions work for me.
    – N. Kat
    Nov 7 '16 at 13:16
1

I've changed load function now it looks like this:

load

bool load(FILE* file, BYTE** content, size_t* length)
{
    // TODO

    BYTE* buffer = NULL;
    size_t count_length = 0;
    int character = 0;

    //allocating memory for buffer
    buffer = malloc(sizeof(BYTE));

    while((character = fgetc(file)) != EOF)
   {
      buffer[count_length] = (char)character;
      count_length++;
      buffer = (char *) realloc(buffer, (count_length + 1) * sizeof(BYTE));
   }

    *length = count_length;
    *content = buffer;

    return true;
}

I think files are loaded correctly but I still get one error with index.php file.

check50 2015.fall.pset6.server2 server.c
:) server.c exists
:) server compiles
:) Requesting cat.jpg returns 200, image/jpeg, and correct image
:) Requesting cat.html returns 200, text/html, and correct file
:) Requesting cat2.HTML returns 200, text/html, and correct file
:) Requesting cat3.HtMl returns 200, text/html, and correct file
:) Requesting cat.gif returns 200, image/gif, and correct file
:) Requesting favicon.ico returns 200, image/x-icon, and correct file
:) Requesting test.css returns 200, text/css, and correct file
:) Requesting test.js returns 200, text/javascript, and correct file
:) Requesting hello.php returns 200, text/html, and correct output
:) Requesting hello.php? returns 200, text/html, and correct output
:) Requesting hello.php?name=Alice returns 200, text/html, and correct output
:) Requesting /test redirects to /test/
:) Requesting /test/ outputs /test/index.html
:( Requesting directory containing index.php outputs index.php
   \ expected output, but not "HTTP/1.1 200 OK\r\nContent-Type: text/h..."
:) Requesting two files in a row (cat.html then cat.jpg) succeeds
https://sandbox.cs50.net/checks/560d485896e94b528b04e88585d29304.

But there is no index.php in my public and test directory.

UPDATE

Now it works!

char* indexes(const char* path)
{
    //**first**
    char* result = NULL;
    char indexphp[] = "/index.php";
    char indexhtml[] = "/index.html";

    int path_lenght = strlen(path) + 1;
    char* linkphp = malloc(path_lenght + strlen(indexphp) + 1);
    strcpy(linkphp, path);
    strcat(linkphp, indexphp);

    char* linkhtml = malloc(path_lenght + strlen(indexhtml) + 1);
    strcpy(linkhtml, path);
    strcat(linkhtml, indexhtml);

    result = (access(linkphp, F_OK) != -1) ? linkphp : NULL;
    if (result == linkphp)
    {
        return linkphp;
    }
    else
    {
        free(linkphp);
    }

    result = (access(linkhtml, F_OK) != -1) ? linkhtml : NULL;
    if (result == linkhtml)
    {
        return linkhtml;
    }
    else
    {
        free(linkhtml);
    }

    return NULL;


    // **Second**
    char indexphp[] = "/index.php";
    char indexhtml[] = "/index.html";
    char directory[strlen(path) + 1];
    int path_lenght = 0;

    //copy path 
    strcpy(directory, path);
    path_lenght = strlen(directory) + 1;

    //and check if last cahr of path for "/" and if so delete "/"

    if(directory[strlen(directory) - 1] == '/')
    {
        for(int i = 0; (i + 1) < strlen(indexphp); i++)
        {
            indexphp[i] = indexphp[i + 1];
        }
        indexphp[strlen(indexphp) - 1] = '\0';

        for(int i = 0; (i + 1) < strlen(indexhtml); i++)
        {
            indexhtml[i] = indexhtml[i + 1];
        }
        indexhtml[strlen(indexhtml) - 1] = '\0';
    }
    //malloc space for php
    char* phppath = malloc(path_lenght + strlen(indexphp) + 1);
    if(phppath == NULL)
    {
        return NULL;
    }
    strcpy(phppath, directory);
    strcat(phppath, indexphp);
    if(access(phppath, F_OK) != -1)
    {
        return phppath;
    }
    else
    {
        free(phppath);
    }
    //malloc space for html
    char* htmlpath = malloc(path_lenght + strlen(indexhtml) + 1); 
    if(htmlpath == NULL)
    {
        return NULL;
    }

    strcpy(htmlpath, directory);
    strcat(htmlpath, indexhtml);
    if(access(htmlpath, F_OK) != -1)
    {
        return htmlpath;
    }
    else
    {
        free(htmlpath);
    }
    return NULL;
}

In second try I've also checked for extra slash in paths '//' Otherwise paths would look like this:

linkphp = 0x6070e0 "/home/ubuntu/workspace/pset6/public/test//index.php"
linkhtml = 0x607120 "/home/ubuntu/workspace/pset6/public/test//index.html"

But it still works with '//'.

2
  • I forgot to add that your code doesn't need to check for "/index.php" etc as you did. You can use just "index.php" and "index.html", because earlier in the code of server.c, the staff makes sure the path ALWAYS gets to the indexes function with a "/" as the last character. Check server.c from this line on: // redirect from absolute-path to absolute-path/ .... Nov 7 '16 at 13:46
  • @Yuri Laguardia OK thank you!
    – N. Kat
    Nov 7 '16 at 14:02

You must log in to answer this question.

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