diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.c b/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.c index 8beaac74..c3cb03c7 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.c @@ -498,54 +498,124 @@ void* guac_rdpdr_print_job_alloc(guac_user* user, void* data) { } +/** + * Attempts to parse the given PostScript "%%Title:" header, storing the + * contents within the filename of the given print job. If the given buffer + * does not immediately begin with the "%%Title:" header, this function has no + * effect. + * + * @param job + * The job whose filename should be set if the "%%Title:" header is + * successfully parsed. + * + * @param buffer + * The buffer to parse as the "%%Title:" header. + * + * @param length + * The number of bytes within the buffer. + * + * @return + * Non-zero if the given buffer began with the "%%Title:" header and this + * header was successfully parsed, zero otherwise. + */ +static int guac_rdpdr_print_job_parse_title_header(guac_rdpdr_print_job* job, + void* buffer, int length) { + + int i; + char* current = buffer; + char* filename = job->filename; + + /* Verify that the buffer begins with "%%Title: " */ + if (strncmp(current, "%%Title: ", 9) != 0) + return 0; + + /* Skip past "%%Title: " */ + current += 9; + length -= 9; + + /* Calculate space remaining in filename */ + int remaining = sizeof(job->filename) - 5 /* ".pdf\0" */; + + /* Do not exceed bounds of provided buffer */ + if (length < remaining) + remaining = length; + + /* Copy as much of title as reasonable */ + for (i = 0; i < remaining; i++) { + + /* Get character, stop at EOL */ + char c = *(current++); + if (c == '\r' || c == '\n') + break; + + /* Copy to filename */ + *(filename++) = c; + + } + + /* Append extension to filename */ + strcpy(filename, ".pdf"); + + /* Title successfully parsed */ + return 1; + +} + +/** + * Searches through the given buffer for PostScript headers denoting the title + * of the document, assigning the filename of the given print job using the + * discovered title. If no title can be found within + * GUAC_RDPDR_PRINT_JOB_TITLE_SEARCH_LENGTH bytes, this function has no effect. + * + * @param job + * The job whose filename should be set if the document title can be found + * within the given buffer. + * + * @param buffer + * The buffer to search for the document title. + * + * @param length + * The number of bytes within the buffer. + */ +static void guac_rdpdr_print_job_read_filename(guac_rdpdr_print_job* job, + void* buffer, int length) { + + char* current = buffer; + int i; + + /* Restrict search area */ + if (length > GUAC_RDPDR_PRINT_JOB_TITLE_SEARCH_LENGTH) + length = GUAC_RDPDR_PRINT_JOB_TITLE_SEARCH_LENGTH; + + /* Search for document title within buffer */ + for (i = 0; i < length; i++) { + + /* If document title has been found, we're done */ + if (guac_rdpdr_print_job_parse_title_header(job, current, length)) + break; + + /* Advance to next character */ + length--; + current++; + + } + +} + int guac_rdpdr_print_job_write(guac_rdpdr_print_job* job, void* buffer, int length) { /* Create print job, if not yet created */ if (job->bytes_received == 0) { - char* filename = job->filename; - unsigned char* search = buffer; - int i; - - /* Search for filename within buffer */ - for (i=0; iclient, job->user, guac_rdpdr_print_job_begin_stream, job); - } /* end if print job beginning */ + } /* Update counter of bytes received */ job->bytes_received += length; diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.h b/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.h index 81b1863c..97e3d623 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_print_job.h @@ -41,6 +41,12 @@ */ #define GUAC_RDPDR_PRINT_JOB_DEFAULT_FILENAME "guacamole-print.pdf" +/** + * The maximum number of bytes to search through at the beginning of a + * PostScript document when locating the document title. + */ +#define GUAC_RDPDR_PRINT_JOB_TITLE_SEARCH_LENGTH 2048 + /** * The current state of an RDPDR print job. */