Index: man/cupsfilter.man =================================================================== --- man/cupsfilter.man (revision 7934) +++ man/cupsfilter.man (working copy) @@ -3,7 +3,7 @@ .\" .\" cupsfilter man page for the Common UNIX Printing System (CUPS). .\" -.\" Copyright 2007 by Apple Inc. +.\" Copyright 2007-2008 by Apple Inc. .\" .\" These coded instructions, statements, and computer programs are the .\" property of Apple Inc. and are protected by Federal copyright @@ -11,7 +11,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH cupsfilter 8 "Common UNIX Printing System" "19 October 2007" "Apple Inc." +.TH cupsfilter 8 "Common UNIX Printing System" "10 September 2008" "Apple Inc." .SH NAME cupsfilter \- convert a file to another format using cups filters .SH SYNOPSIS @@ -50,6 +50,8 @@ -m mime/type .br Specifies the destination file type. The default file type is application/pdf. +Use printer/foo to convert to the printer format defined by the filters in the +PPD file. .TP 5 -n copies .br @@ -74,7 +76,7 @@ .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id$". .\" Index: scheduler/cupsfilter.c =================================================================== --- scheduler/cupsfilter.c (revision 7934) +++ scheduler/cupsfilter.c (working copy) @@ -75,21 +75,28 @@ * Local functions... */ -static int compare_pids(mime_filter_t *a, mime_filter_t *b); -static char *escape_options(int num_options, cups_option_t *options); -static int exec_filter(const char *filter, char **argv, char **envp, - int infd, int outfd); -static int exec_filters(cups_array_t *filters, const char *infile, - const char *outfile, const char *ppdfile, - const char *printer, const char *user, - const char *title, int num_options, - cups_option_t *options); -static void get_job_file(const char *job); -static int open_pipe(int *fds); -static int read_cupsd_conf(const char *filename); -static void set_string(char **s, const char *val); -static void sighandler(int sig); -static void usage(const char *command, const char *opt); +static void add_printer_filter(const char *command, mime_t *mime, + mime_type_t *printer_type, + const char *filter); +static mime_type_t *add_printer_filters(const char *command, + mime_t *mime, const char *printer, + const char *ppdfile, + mime_type_t **prefilter_type); +static int compare_pids(mime_filter_t *a, mime_filter_t *b); +static char *escape_options(int num_options, cups_option_t *options); +static int exec_filter(const char *filter, char **argv, + char **envp, int infd, int outfd); +static int exec_filters(cups_array_t *filters, const char *infile, + const char *outfile, const char *ppdfile, + const char *printer, const char *user, + const char *title, int num_options, + cups_option_t *options); +static void get_job_file(const char *job); +static int open_pipe(int *fds); +static int read_cupsd_conf(const char *filename); +static void set_string(char **s, const char *val); +static void sighandler(int sig); +static void usage(const char *command, const char *opt); /* @@ -102,7 +109,10 @@ { int i; /* Looping vars */ const char *command, /* Command name */ - *opt; /* Current option */ + *opt, /* Current option */ + *printer; /* Printer name */ + mime_type_t *printer_type, /* Printer MIME type */ + *prefilter_type; /* Printer prefilter MIME type */ char *srctype, /* Source type */ *dsttype, /* Destination type */ super[MIME_MAX_SUPER], /* Super-type name */ @@ -137,6 +147,7 @@ else command = argv[0]; + printer = !strcmp(command, "convert") ? "tofile" : "cupsfilter"; mime = NULL; srctype = NULL; compression = 0; @@ -369,6 +380,8 @@ return (1); } + add_printer_filters(command, mime, printer, ppdfile, &prefilter_type); + /* * Get the source and destination types... */ @@ -393,7 +406,9 @@ } sscanf(dsttype, "%15[^/]/%255s", super, type); - if ((dst = mimeType(mime, super, type)) == NULL) + if (!strcasecmp(super, "printer")) + dst = printer_type; + else if ((dst = mimeType(mime, super, type)) == NULL) { _cupsLangPrintf(stderr, _("%s: Unknown destination MIME type %s/%s!\n"), @@ -424,13 +439,38 @@ else if (compression) cupsArrayInsert(filters, &GZIPFilter); + if (prefilter_type) + { + /* + * Add pre-filters... + */ + + mime_filter_t *filter, /* Current filter */ + *prefilter; /* Current pre-filter */ + cups_array_t *prefilters = cupsArrayNew(NULL, NULL); + /* New filters array */ + + + for (filter = (mime_filter_t *)cupsArrayFirst(filters); + filter; + filter = (mime_filter_t *)cupsArrayNext(filters)) + { + if ((prefilter = mimeFilterLookup(mime, filter->src, prefilter_type))) + cupsArrayAdd(prefilters, prefilter); + + cupsArrayAdd(prefilters, filter); + } + + cupsArrayDelete(filters); + filters = prefilters; + } + /* * Do it! */ - status = exec_filters(filters, infile, outfile, ppdfile, - !strcmp(command, "convert") ? "tofile" : "cupsfilter", - user, title, num_options, options); + status = exec_filters(filters, infile, outfile, ppdfile, printer, user, + title, num_options, options); /* * Remove files as needed, then exit... @@ -450,6 +490,131 @@ /* + * 'add_printer_filter()' - Add a single filters from a PPD file. + */ + +static void +add_printer_filter( + const char *command, /* I - Command name */ + mime_t *mime, /* I - MIME database */ + mime_type_t *filtertype, /* I - Printer or prefilter MIME type */ + const char *filter) /* I - Filter to add */ +{ + char super[MIME_MAX_SUPER], /* Super-type for filter */ + type[MIME_MAX_TYPE], /* Type for filter */ + program[1024]; /* Program/filter name */ + int cost; /* Cost of filter */ + mime_type_t *temptype; /* MIME type looping var */ + char filename[1024]; /* Full filter filename */ + + + /* + * Parse the filter string; it should be in the following format: + * + * super/type cost program + */ + + if (sscanf(filter, "%15[^/]/%31s%d%*[ \t]%1023[^\n]", super, type, &cost, + program) != 4) + { + _cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"\n"), command, + filter); + return; + } + + /* + * See if the filter program exists; if not, stop the printer and flag + * the error! + */ + + if (strcmp(program, "-")) + { + if (program[0] == '/') + strlcpy(filename, program, sizeof(filename)); + else + snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program); + + if (access(filename, X_OK)) + { + _cupsLangPrintf(stderr, _("%s: Filter \"%s\" not available: %s\n"), + command, program, strerror(errno)); + return; + } + } + + /* + * Add the filter to the MIME database, supporting wildcards as needed... + */ + + for (temptype = mimeFirstType(mime); + temptype; + temptype = mimeNextType(mime)) + if (((super[0] == '*' && strcasecmp(temptype->super, "printer")) || + !strcasecmp(temptype->super, super)) && + (type[0] == '*' || !strcasecmp(temptype->type, type))) + mimeAddFilter(mime, temptype, filtertype, cost, program); +} + + +/* + * 'add_printer_filters()' - Add filters from a PPD file. + */ + +static mime_type_t * /* O - Printer type or NULL on error */ +add_printer_filters( + const char *command, /* I - Command name */ + mime_t *mime, /* I - MIME database */ + const char *printer, /* I - Printer name */ + const char *ppdfile, /* I - PPD file */ + mime_type_t **prefilter_type) /* O - Prefilter type */ +{ + int i; /* Looping var */ + mime_type_t *printer_type; /* Printer MIME type */ + ppd_file_t *ppd; /* PPD file data */ + ppd_attr_t *ppdattr; /* Current prefilter */ + + + if ((ppd = ppdOpenFile(ppdfile)) == NULL) + { + ppd_status_t status; /* PPD load status */ + + status = ppdLastError(&i); + _cupsLangPrintf(stderr, _("%s: Unable to open PPD file: %s on line %d\n"), + command, ppdErrorString(status), i); + return (NULL); + } + + printer_type = mimeAddType(mime, "printer", printer); + + if (ppd->num_filters > 0) + { + for (i = 0; i < ppd->num_filters; i ++) + add_printer_filter(command, mime, printer_type, ppd->filters[i]); + } + else + { + add_printer_filter(command, mime, printer_type, + "application/vnd.cups-command 0 commandtops"); + add_printer_filter(command, mime, printer_type, + "application/vnd.cups-postscript 0 -"); + } + + if ((ppdattr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) + { + *prefilter_type = mimeAddType(mime, "prefilter", printer); + + for (; ppdattr; ppdattr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) + if (ppdattr->value) + add_printer_filter(command, mime, *prefilter_type, ppdattr->value); + } + else + *prefilter_type = NULL; + + return (printer_type); +} + + +/* * 'compare_pids()' - Compare two filter PIDs... */