#include "request_handling.h" #include #include #include /** * Identical to strcpy, but strips a trailing '\r\n' * * @param dest Buffer to copy to * @param src Buffer to copy from * * @return The destination buffer */ static char *strcpy_no_crlf(char *dest, const char *src) { char *dest_cursor; const char *src_cursor; char *last_dest_cursor = NULL; const char *last_src_cursor = NULL; for (dest_cursor = dest, src_cursor = src; *src_cursor != '\0'; src_cursor++) { if (last_src_cursor != NULL && *last_src_cursor == '\r' && *last_src_cursor == '\n') { // Replace the \r with a null term. *last_dest_cursor = '\0'; return dest; } *dest_cursor = *src_cursor; last_dest_cursor = dest_cursor; last_src_cursor = src_cursor; dest_cursor++; } *dest_cursor = '\0'; return dest; } /** * Parse a request line into a request_line * * @param line The line to parse. * @param parsed_line A pointer to a request_line. Values must be freed by caller. * * @return -1 if malformed, 0 if well formed. */ int parse_request_line(const char *line, struct request_line *parsed_line) { int line_size = strlen(line) + 1; char *raw_line = malloc(line_size * sizeof(char)); strcpy(raw_line, line); char *method = strtok(raw_line, " "); if (method == NULL) { free(raw_line); return -1; } int method_size = strlen(method) + 1; parsed_line->method = malloc(method_size * sizeof(char)); strcpy_no_crlf(parsed_line->method, method); char *uri = strtok(NULL, " "); if (uri == NULL) { free(raw_line); free(parsed_line->method); return -1; } int uri_size = strlen(uri) + 1; parsed_line->uri = malloc(uri_size * sizeof(char)); strcpy_no_crlf(parsed_line->uri, uri); char *http_version = strtok(NULL, " "); if (http_version == NULL) { free(raw_line); free(parsed_line->method); free(parsed_line->uri); return -1; } int version_size = strlen(http_version) + 1; parsed_line->http_version = malloc(version_size * sizeof(char)); strcpy_no_crlf(parsed_line->http_version, http_version); free(raw_line); return 0; } /** * Gets a FILE from a given uri. * * @param uri The uri in the request line. * @param req_file A pointer to a requested_file struct. * * @return -1 For an I/O error, 0 if successful. */ int get_file_from_url(const char *uri, struct requested_file *req_file) { // If our uri starts with a slash, we can ignore it. if (*uri == '/') { uri++; } FILE *open_file = fopen(uri, "r"); if (open_file == NULL) { return -1; } int seek_result = fseek(open_file, 0, SEEK_END); if (seek_result != 0) { return -1; } long size = ftell(open_file); if (size == -1) { return -1; } rewind(open_file); req_file->size = size; req_file->file = open_file; return 0; }