GUACAMOLE-200: Clean up PostScript document title search logic.

This commit is contained in:
Michael Jumper 2017-02-13 18:42:03 -08:00
parent 3fc43fba37
commit d23a22b7c6
2 changed files with 113 additions and 37 deletions

View File

@ -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, int guac_rdpdr_print_job_write(guac_rdpdr_print_job* job,
void* buffer, int length) { void* buffer, int length) {
/* Create print job, if not yet created */ /* Create print job, if not yet created */
if (job->bytes_received == 0) { if (job->bytes_received == 0) {
char* filename = job->filename; /* Attempt to read document title from first buffer of data */
unsigned char* search = buffer; guac_rdpdr_print_job_read_filename(job, buffer, length);
int i;
/* Search for filename within buffer */
for (i=0; i<length-9 && i < 2048; i++) {
/* If title. use as filename */
if (memcmp(search, "%%Title: ", 9) == 0) {
/* Skip past "%%Title: " */
search += 9;
/* Copy as much of title as reasonable */
int j;
for (j=0; j < GUAC_RDPDR_PRINT_JOB_FILENAME_MAX_LENGTH - 5 /* extension + 1 */ && i<length; i++, j++) {
/* Get character, stop at EOL */
char c = *(search++);
if (c == '\r' || c == '\n')
break;
/* Copy to filename */
filename[j] = c;
}
/* Append filename with extension */
strcpy(&(filename[j]), ".pdf");
break;
}
/* Next character */
search++;
}
/* Begin print stream */ /* Begin print stream */
guac_client_for_user(job->client, job->user, guac_client_for_user(job->client, job->user,
guac_rdpdr_print_job_begin_stream, job); guac_rdpdr_print_job_begin_stream, job);
} /* end if print job beginning */ }
/* Update counter of bytes received */ /* Update counter of bytes received */
job->bytes_received += length; job->bytes_received += length;

View File

@ -41,6 +41,12 @@
*/ */
#define GUAC_RDPDR_PRINT_JOB_DEFAULT_FILENAME "guacamole-print.pdf" #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. * The current state of an RDPDR print job.
*/ */