From 3b80c89c7e72401bcf0d1bc64ada1322e9ed6bad Mon Sep 17 00:00:00 2001 From: Till Kamppeter Date: Mon, 21 Mar 2022 21:00:24 +0100 Subject: [PATCH] cupsfilters: Make bannertopdf() work without environment variables bannertopdf() uses CUPS' environment variables to determine the template file directory, and the printer description (info) and location entries. To make it easier to use this filter function also without CUPS, the directory is now supplied as a string pointed at by the parameters pointer and the printer description and location fields via the "printer-info" and "printer-location" options or IPP attributes. In addition fixed several bugs: - Free options list correctly - Free templates file field in banner data structure correctly - Handle a missing template PDF file correctly, without crash --- cupsfilters/bannertopdf.c | 58 +++++++++++++++++++++------------------ cupsfilters/filter.h | 8 ++++++ cupsfilters/pdf.cxx | 8 +++++- filter/bannertopdf.c | 9 +++++- 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/cupsfilters/bannertopdf.c b/cupsfilters/bannertopdf.c index 820a5c0af..1d7be65bf 100644 --- a/cupsfilters/bannertopdf.c +++ b/cupsfilters/bannertopdf.c @@ -67,7 +67,7 @@ enum banner_info typedef struct { - const char *template_file; + char *template_file; char *header, *footer; unsigned infos; } banner_t; @@ -76,6 +76,7 @@ void banner_free(banner_t *banner) { if (banner) { + free(banner->template_file); free(banner->header); free(banner->footer); free(banner); @@ -166,30 +167,22 @@ static unsigned parse_show(char *s, filter_logfunc_t log, void *ld) return info; } -static char *template_path(const char *name) +static char *template_path(const char *name, const char *datadir) { - char *datadir, *result; + char *result; if (name[0] == '/') return strdup(name); - if ((datadir = getenv("CUPS_DATADIR")) == NULL) - { - result = malloc(strlen(BANNERTOPDF_DATADIR) + strlen(name) + 2); - sprintf(result, "%s/%s", BANNERTOPDF_DATADIR, name); - } - else - { - result = malloc(strlen(datadir) + strlen(name) + 7); - sprintf(result, "%s/data/%s", datadir, name); - } + result = malloc(strlen(datadir) + strlen(name) + 2); + sprintf(result, "%s/%s", datadir, name); return result; } banner_t *banner_new_from_file(const char *filename, int *num_options, - cups_option_t **options, filter_logfunc_t log, - void *ld) + cups_option_t **options, const char *datadir, + filter_logfunc_t log, void *ld) { FILE *f; char *line = NULL; @@ -257,7 +250,7 @@ banner_t *banner_new_from_file(const char *filename, int *num_options, key ++; if (!strcasecmp(key, "template")) - banner->template_file = template_path(value); + banner->template_file = template_path(value, datadir); else if (!strcasecmp(key, "header")) banner->header = strdup(value); else if (!strcasecmp(key, "footer")) @@ -300,9 +293,9 @@ banner_t *banner_new_from_file(const char *filename, int *num_options, if (!banner->template_file) { if (ispdf) - banner->template_file = filename; + banner->template_file = strdup(filename); else - banner->template_file = template_path("default.pdf"); + banner->template_file = template_path("default.pdf", datadir); } if (!gotinfos) { @@ -584,20 +577,25 @@ opt_t *get_known_opts( ipp_t *printer_attrs = data->printer_attrs; ipp_attribute_t *ipp_attr; char buf[1024]; + const char *value = NULL; + /* Job ID */ opt = add_opt(opt, "job-id", jobid); /* Job title */ opt = add_opt(opt, "job-title", jobtitle); - /* Printer by */ + /* Printed by */ opt = add_opt(opt, "user", user); /* Printer name */ opt = add_opt(opt, "printer-name", data->printer); /* Printer info */ - opt = add_opt(opt, "printer-info", getenv("PRINTER_INFO")); + if ((value = cupsGetOption("printer-info", + noptions, options)) == NULL || !value[0]) + value = getenv("PRINTER_INFO"); + opt = add_opt(opt, "printer-info", value); /* Time at creation */ opt = add_opt(opt, "time-at-creation", @@ -750,7 +748,7 @@ static int generate_banner_pdf(banner_t *banner, if (!(doc = pdf_load_template(banner->template_file))) { if (log) log(ld, FILTER_LOGLEVEL_ERROR, - "PDF template must contain exactly 1 page: %s", + "PDF template must exist and contain exactly 1 page: %s", banner->template_file); return (1); } @@ -810,11 +808,15 @@ static int generate_banner_pdf(banner_t *banner, info_line(s, "Printer", data->printer); if ((banner->infos & INFO_PRINTER_INFO) && - (value = getenv("PRINTER_INFO")) != NULL && value[0]) + (((value = cupsGetOption("printer-info", + noptions, options)) != NULL && value[0]) || + ((value = getenv("PRINTER_INFO")) != NULL && value[0]))) info_line(s, "Description", value); if ((banner->infos & INFO_PRINTER_LOCATION) && - (value = getenv("PRINTER_LOCATION")) != NULL && value[0]) + (((value = cupsGetOption("printer-location", + noptions, options)) != NULL && value[0]) || + ((value = getenv("PRINTER_LOCATION")) != NULL && value[0]))) info_line(s, "Location", value); if ((banner->infos & INFO_JOB_ID) && @@ -1002,9 +1004,10 @@ static int generate_banner_pdf(banner_t *banner, int bannertopdf(int inputfd, /* I - File descriptor input stream */ int outputfd, /* I - File descriptor output stream */ - int inputseekable, /* I - Is input stream seekable? (unused) */ + int inputseekable, /* I - Is input stream seekable? (unused)*/ filter_data_t *data, /* I - Job and printer data */ - void *parameters) /* I - Filter-specific parameters (unused) */ + void *parameters) /* I - Filter-specific parameters - + Template/Banner data directory */ { banner_t *banner; int num_options = 0; @@ -1016,6 +1019,7 @@ int bannertopdf(int inputfd, /* I - File descriptor input stream */ cups_option_t *options = NULL; char tempfile[1024], buffer[1024]; size_t bytes; + const char *datadir = (const char *)parameters; filter_logfunc_t log = data->logfunc; void *ld = data->logdata; @@ -1098,7 +1102,7 @@ int bannertopdf(int inputfd, /* I - File descriptor input stream */ /* * Parse the instructions... */ - banner = banner_new_from_file(tempfile, &num_options, &options, + banner = banner_new_from_file(tempfile, &num_options, &options, datadir, log, ld); if (!banner) @@ -1128,7 +1132,7 @@ int bannertopdf(int inputfd, /* I - File descriptor input stream */ * Clean up... */ banner_free(banner); - if(options) free(options); + if (options) cupsFreeOptions(num_options, options); unlink(tempfile); return ret; diff --git a/cupsfilters/filter.h b/cupsfilters/filter.h index aa959b2f3..e8597b0ca 100644 --- a/cupsfilters/filter.h +++ b/cupsfilters/filter.h @@ -223,6 +223,14 @@ extern int bannertopdf(int inputfd, filter_data_t *data, void *parameters); +/* Parameters: const char* + Template directory: In this directory there are the PDF template files + for the banners and test pages. CUPS uses /usr/share/cups/data/ for that. + If you submit a PDF file with added banner instructions as input file + the template directory is not needed as the PDF input file itself is used + as template. */ + + extern int imagetopdf(int inputfd, int outputfd, int inputseekable, diff --git a/cupsfilters/pdf.cxx b/cupsfilters/pdf.cxx index e8333035c..97a9b8fe3 100644 --- a/cupsfilters/pdf.cxx +++ b/cupsfilters/pdf.cxx @@ -61,7 +61,13 @@ static QPDFObjectHandle makeRealBox(float values[4]) extern "C" pdf_t * pdf_load_template(const char *filename) { QPDF *pdf = new QPDF(); - pdf->processFile(filename); + try { + pdf->processFile(filename); + } catch(...) { + delete pdf; + return NULL; + } + unsigned pages = (pdf->getAllPages()).size(); if (pages != 1) { diff --git a/filter/bannertopdf.c b/filter/bannertopdf.c index bf0d82492..087646fa3 100644 --- a/filter/bannertopdf.c +++ b/filter/bannertopdf.c @@ -3,6 +3,7 @@ */ #include +#include #include /* @@ -52,7 +53,13 @@ main(int argc, /* I - Number of command-line arguments */ * Fire up the pdftoraster() filter function */ - ret = filterCUPSWrapper(argc, argv, bannertopdf, NULL, &JobCanceled); + char buf[1024]; + const char *datadir = getenv("CUPS_DATADIR"); + if (!datadir) + datadir = CUPS_DATADIR; + snprintf(buf, sizeof(buf), "%s/data", datadir); + + ret = filterCUPSWrapper(argc, argv, bannertopdf, buf, &JobCanceled); if (ret) fprintf(stderr, "ERROR: bannertopdf filter function failed.\n"); -- 2.47.3