0

i've been struggling with the pset6, i got everything to work, but my server dosn't correctly send cat.jpg and cat.gif, my check50 fails at :

  • Requesting cat.jpg returns 200, image/jpeg, and correct image
  • Requesting cat.gif returns 200, image/gif, and correct file
  • Requesting two files in a row (cat.html then cat.jpg) succeeds

It might have something to do with the fact that i'm reallocating every 512 bytes, and the cat images are the only files larger than 512 bytes, but can't figure out why my realloc wouldn't work if it's the case

Here are the 3 relevant functions to these problems if anyone can point me to what i missed, thank you

The load function :

bool load(FILE* file, BYTE** content, size_t* length)
{
    int size = 0;
    int buffer = BYTES;
    if (ferror(file))
        return false;
    *content = malloc(buffer);

    for (BYTE b = fgetc(file); b != EOF; b = fgetc(file))
    {
        if (size == buffer)
        {
            buffer += BYTES;
            *content = realloc(*content, buffer);
        }
        *(*content +size) = b;
        size++;
    }
    *length = size;
    return true;
}

The lookup function:

const char* lookup(const char* path)
{
    char* extension = strrchr(path, '.');

    if (strcasecmp(extension, ".css") == 0)
        return "text/css";
    else if (strcasecmp(extension, ".html") == 0)
        return "text/html";
    else if (strcasecmp(extension, ".gif") == 0)
        return "image/gif";
    else if (strcasecmp(extension, ".ico") == 0)
        return "image/x-icon";
    else if (strcasecmp(extension, ".jpg") == 0)
        return "image/jpeg";
    else if (strcasecmp(extension, ".js") == 0)
        return "text/javascript";
    else if (strcasecmp(extension, ".php") == 0)
        return "text/x-php";
    else if (strcasecmp(extension, ".png") == 0)
        return "image/png";
    else
        return NULL;
}

the parse function :

bool parse(const char* line, char* abs_path, char* query)
{
    int i = 0;                                        // the char index we're reading from the line
    int len = strlen(line);        
    char method[len];                                 // we store the method in here
    char target[len];                                 // we store the request-target here
    char version[len];                                // we store the http version here
    int SP = 0;                                       // number of spaces found from the start to the ith char
    int index = 0;                                    // the index we're at from the start or from the first char after the last space
    while(line[i] != '\0')
    {
        if (line[i] == '\r' && line[i+1] == '\n')
        {
            if (SP != 2)
            {
                error(400);
                return false;
            }
            else
            {
                version[index] = '\0';
                break;
            }
        }
        if (line[i] == ' ')
        {
            if (SP == 0)
                method[index] = '\0';
            else if (SP == 1)
                target[index] = '\0';

            i++;
            SP++;
            index = 0;
            if (SP > 2)
            {
                error(400);
                return false;
            }
            continue;
        }
        if (SP == 0)
        {
            method[index] = line[i];
        }
        else if (SP == 1)
        {
            target[index] = line[i];
        }
        else 
        {
            version[index] = line[i];
        }
        i++;
        index++;
    }
    if (strcmp(method, "GET") != 0)
    {
        error(405);
        return false;
    }
    else if (target[0] != '/')
    {
        error(501);
        return false;
    }
    else if (strchr(target, '\"') != NULL)
    {
        error(400);
        return false;
    }
    else if (strcmp(version, "HTTP/1.1") != 0)
    {
        error(505);
        return false;
    }

    char* qry = strrchr(target, '?');
    if (qry != NULL)
    {
        strcpy(query, qry + 1);
        strncpy(abs_path, target, strlen(target) - strlen(qry));
        abs_path[strlen(target) - strlen(qry)] = '\0';
    }
    else
    {
        strcpy(query, "");
        strcpy(abs_path, target);
    }
    return true;
}
1

I solved my problems by replacing

for (BYTE b = fgetc(file); b != EOF; b = fgetc(file))

by

BYTE b;
while(fread(&b, sizeof(BYTE), 1, file)==1)

can anyone tell me what's the difference? it's supposed to do the same thing, read one byte (char) at a time. Especially that both work for less than 512 bytes files, but only the second worked for larger files (cat.jpg)

2
  • In the above for-loop, you check for EOF after you read from fgetc which will throw an error. But with fread, you read a byte and check if it's the EOF marker, and continue with the loop. Read the manual page for fread manual page for the return values. May 31 '16 at 12:38
  • The fgetc does not work on image files because the defined constant EOF is -1. Since image data can contain a byte that is -1, it is detecting a "false eof". It has nothing to do with file size, that is coincidence. It has to do with file type. Apr 8 '17 at 15:18

You must log in to answer this question.

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