From 7fd1bbc1abafee0f1db19118d127c5bd744f1b67 Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Sun, 28 Nov 2021 01:16:40 +0100 Subject: Refactoring: 2nd step and a working state. --- cgi.c | 26 +++++++++----- http_parser.c | 109 +++++++++++++++++++++++++++++----------------------------- main.c | 14 ++++---- 3 files changed, 80 insertions(+), 69 deletions(-) diff --git a/cgi.c b/cgi.c index 128eae7..81149af 100644 --- a/cgi.c +++ b/cgi.c @@ -42,12 +42,16 @@ static const char * line1 = NULL, * line2 = NULL; int print_on_correct_printer(void * user_data, unsigned flags, cups_dest_t * dest) { if(!strstr(dest->name, user_data)) { - printf("> Wrong name: %s continue search\n", dest->name); + // DEBUG("> Wrong printer name: '%s'; try next printer...\n", dest->name); return 1; } - if(!dest || !line1 || !line2) { - printf("FAILED: %p %p %p\n", dest, line1, line2); + DEBUG("> Correct printer found: %s\n", dest->name); + + if(!dest + || !line1 + || !line2) { + DEBUG("> Nothing to print or printer not found: %p %p %p\n", dest, line1, line2); return 1; } @@ -63,20 +67,22 @@ int print_on_correct_printer(void * user_data, unsigned flags, cups_dest_t * des cups_dinfo_t * info = cupsCopyDestInfo(CUPS_HTTP_DEFAULT, dest); if (cupsCreateDestJob(CUPS_HTTP_DEFAULT, dest, info, &job_id, "My Document", num_options, options) == IPP_STATUS_OK) - printf("Created job: %d\n", job_id); + DEBUG("> Created job: %d\n", job_id); else - printf("Unable to create job: %s\n", cupsLastErrorString()); + DEBUG("> Unable to create job: %s\n", cupsLastErrorString()); if (cupsStartDestDocument(CUPS_HTTP_DEFAULT, dest, info, job_id, "filename.pdf", CUPS_FORMAT_TEXT, num_options, options, 1) == HTTP_STATUS_CONTINUE) { + DEBUG("> printing label:\n>\t%s\n>\t%s\n", line1, line2); + cupsWriteRequestData(CUPS_HTTP_DEFAULT, line1, strlen(line1)); cupsWriteRequestData(CUPS_HTTP_DEFAULT, "\n", 1); cupsWriteRequestData(CUPS_HTTP_DEFAULT, line2, strlen(line2)); if (cupsFinishDestDocument(CUPS_HTTP_DEFAULT, dest, info) == IPP_STATUS_OK) - puts("Document send succeeded."); + DEBUG("> Document send succeeded."); else - printf("Document send failed: %s\n", cupsLastErrorString()); + DEBUG("> Document send failed: %s\n", cupsLastErrorString()); } return 0; } @@ -116,16 +122,18 @@ void send_answer(Http_Header * http_header, FILE * f) { print_on_correct_printer, printer_name ); + line1 = NULL; line2 = NULL; send_answer_file(http_header, f); } - void next_part(Http_Header * http_header, const char * content, size_t content_size) { - if(!http_header->content_disposition) + if(!http_header->content_disposition) { + DEBUG("> No Content-Disposition header found\n"); return; + } if(strstr(http_header->content_disposition, "name=\"line1\"")) { line1 = content; diff --git a/http_parser.c b/http_parser.c index 30e74c8..03d8d91 100644 --- a/http_parser.c +++ b/http_parser.c @@ -54,7 +54,7 @@ static inline char * handle_colon(char ** start, char ** end, char ** search) { return *start; // remember, where name starts, will be important in the newline case } -static inline void handle_semicolon(char ** start, char ** end, char ** search) { +static inline char * handle_semicolon(char ** start, char ** end, char ** search) { // find the form-data boundary in the main header *start += strspn(*start, "; "); // remove spaces and semicolons (boundary check implicit; also stops at '\0') @@ -63,10 +63,15 @@ static inline void handle_semicolon(char ** start, char ** end, char ** search) { *end = *end + sizeof(s_multipart_form_data) + 1; *end += strspn(*end, "-"); + *start = *end; DEBUG("> Boundary found, now looking where it ends...\n"); + + *end += strcspn(*end, "\r\n "); + *end[0] = '\0'; } *search = "\r\n"; // do not search further semicolons + return *start; } void parse_http(size_t new_socket, char * request, size_t request_length) { @@ -90,12 +95,11 @@ void parse_http(size_t new_socket, char * request, size_t request_length) { size_t matchlen = strspn(end, search); switch(end[0]) { case ':': - handle_colon(&start, &end, &search); - name = start; + name = handle_colon(&start, &end, &search); break; case ';': - handle_semicolon(&start, &end, &search); - http_header.boundary = end; + http_header.boundary = handle_semicolon(&start, &end, &search); + http_header.boundary_size = end - start; break; case '\r': // fallthrough case '\n': @@ -123,62 +127,59 @@ void parse_http(size_t new_socket, char * request, size_t request_length) { if (0 == strcasecmp("Content-Disposition", name)) { http_header.content_disposition = start; } } // }}} - DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start); - // {{{ check if a http header ended (e.g. two newlines) - if(matchlen > http_header.newline_length) { - DEBUG("> END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n", matchlen / http_header.newline_length, http_header.boundary, http_header.boundary_size); - end += matchlen; - - // if it was the first header, we calculate the boundary size and expect more headers to come after a boundary - if(http_header.boundary && http_header.boundary_size == 0) { - DEBUG("================================================================================\n"); - http_header.boundary_size = strlen(http_header.boundary); - // skip the first header and boundary... - start = end; - start += strspn(start, "-"); - start += http_header.boundary_size; - start += http_header.newline_length; - continue; - } else { - char * content_start = end; - while(1) - { - size_t size_remaining = (size_t) request_length - (end - request) - 1; - DEBUG("%ld remaining.\n", size_remaining); - - if(size_remaining <= 0) { - DEBUG("> not even the boundary would fit in that what is left.\n"); - break; - } - - if(NULL == (end = memchr((void*) end, '-', size_remaining))) { - DEBUG("no further '-' found\n"); - break; - } - - char * content_end = end - http_header.newline_length; - - end += strspn(end, "-"); - if(0 == strncmp(end, http_header.boundary, http_header.boundary_size)) { - size_t file_size = content_end - content_start; - DEBUG("> Content ends here, size of the last file is %ld\n", file_size); - content_start[file_size + 1] = '\0'; - next_part(&http_header, content_start, file_size); - - end += http_header.boundary_size; - matchlen = strspn(end, "\r\n"); - DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); + // {{{ DEBUG + DEBUG("\033[32m[%ld]> '% 20s' = '%s'\033[0m\n", matchlen, name, start); + // }}} - search = ":"; + // check if a http header ended (e.g. two newlines) + if(matchlen > http_header.newline_length) { + end += matchlen; // go behind the double line break... + + //{{{ DEBUG + DEBUG("> END HEADERS, because there were %d newlines; boundary='%s'[%ld]\n", + matchlen / http_header.newline_length, + http_header.boundary, + http_header.boundary_size + ); // }}} + + start = end; + for(; ; ) + { + size_t size_remaining = (size_t) request_length - (end - request) - 1; + + // {{{ DEBUG + DEBUG("%ld remaining.\n", size_remaining); + // }}} + + matchlen = strspn(end, "-"); + if(0 == strncmp(end + matchlen, http_header.boundary, http_header.boundary_size)) { + size_t file_size = end - http_header.newline_length - start; + DEBUG("> Content ends here, size of the last file is %ld\n", file_size); + start[file_size + 1] = '\0'; + + next_part(&http_header, start, file_size); + + end += http_header.boundary_size + matchlen; + matchlen = http_header.newline_length; + DEBUG("> end is at %p, matchlen is %ld\n", end, matchlen); + search = ":"; + break; + } else { + + if(!http_header.boundary + || size_remaining <= 0 + || NULL == (end = memchr((void*) end, '-', size_remaining))) { + // {{{ DEBUG + DEBUG("EOF reached or no further '-' found\n"); + // }}} break; - } else { - end = end + 1; } + // end++; } } break; - } // }}} if condition after a header + } // if condition after a header } // switch if(NULL == end) diff --git a/main.c b/main.c index 906be15..96cfa67 100644 --- a/main.c +++ b/main.c @@ -46,7 +46,7 @@ static int read_everything(FILE * f_r, FILE * output) { continue; } - fwrite(read_buffer, read_buffer_length, 1, output); + fwrite(read_buffer, 1, size, output); if (read_buffer_length > POST_DATA_MAX_LENGTH) return EXIT_FAILURE; @@ -67,7 +67,10 @@ static void * answer_request(size_t new_socket) { FILE * output = open_memstream(&output_buffer, &output_buffer_length); read_everything(f_r, output); // TODO: catch return value and error handling - shutdown(new_socket, SHUT_RD); // shutdown the reading half of the connection + fflush(output); + // shutdown(new_socket, SHUT_RD); // shutdown the reading half of the connection + + DEBUG("output buffer has a length of %ld bytes\n", output_buffer_length); // TODO: make parsing function abstract (e.g. parse(...) function point with dlsym) parse_http(new_socket, output_buffer, output_buffer_length); @@ -80,8 +83,8 @@ static void * answer_request(size_t new_socket) { return NULL; } - int become_daemon(const char * name) { +# ifndef DEBUG // debugging is simpler in foreground mode if(fork()) { exit(EXIT_SUCCESS); } else { @@ -90,12 +93,12 @@ int become_daemon(const char * name) { exit(EXIT_SUCCESS); } else { syslog(0, "daemon '%s' is running with pid %d", name, getpid()); - return EXIT_SUCCESS; } } +# endif + return EXIT_SUCCESS; } - static int serve(int server_fd) { struct sockaddr_in address; @@ -129,7 +132,6 @@ int main(const int argc, char const * argv[]) { int port = atoi(argc > 1 ? argv[1] : "8080"); 0 == port ? port = 8080 : port; - struct sockaddr_in address = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, -- cgit v1.2.3