diff -up cups-1.3.7/config.h.in.poppler-pdftops cups-1.3.7/config.h.in --- cups-1.3.7/config.h.in.poppler-pdftops 2010-02-12 17:16:11.357041924 +0000 +++ cups-1.3.7/config.h.in 2010-02-12 17:16:11.527918547 +0000 @@ -434,6 +434,13 @@ #undef HAVE_PYTHON #define CUPS_PYTHON "/usr/bin/python" +/* + * Location of the poppler/Xpdf pdftops program... + */ + +#define HAVE_PDFTOPS +#define CUPS_PDFTOPS "/usr/bin/pdftops" + /* * Do we have Darwin's CoreFoundation and SystemConfiguration frameworks? diff -up cups-1.3.7/conf/mime.convs.in.poppler-pdftops cups-1.3.7/conf/mime.convs.in --- cups-1.3.7/conf/mime.convs.in.poppler-pdftops 2010-02-12 17:16:40.830042352 +0000 +++ cups-1.3.7/conf/mime.convs.in 2010-02-12 17:17:03.522917379 +0000 @@ -38,7 +38,7 @@ # PostScript filters # -application/pdf application/postscript 33 pdftops +application/pdf application/vnd.cups-postscript 66 pdftops application/postscript application/vnd.cups-postscript 66 pstops application/vnd.hp-HPGL application/postscript 66 hpgltops application/x-cshell application/postscript 33 texttops diff -up cups-1.3.7/filter/Makefile.poppler-pdftops cups-1.3.7/filter/Makefile --- cups-1.3.7/filter/Makefile.poppler-pdftops 2007-07-20 00:27:49.000000000 +0100 +++ cups-1.3.7/filter/Makefile 2010-02-12 17:16:11.528918556 +0000 @@ -3,7 +3,7 @@ # # Filter makefile for the Common UNIX Printing System (CUPS). # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2009 by Apple Inc. # Copyright 1997-2006 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -19,7 +19,7 @@ include ../Makedefs FILTERS = gziptoany hpgltops texttops pstops $(IMGFILTERS) \ - rastertolabel rastertoepson rastertohp + $(PDFTOPS) rastertolabel rastertoepson rastertohp TARGETS = $(FILTERS) \ $(LIBCUPSIMAGE) \ libcupsimage.a \ @@ -39,9 +39,9 @@ IMAGE32OBJS = $(IMAGEOBJS:.o=.32.o) IMAGE64OBJS = $(IMAGEOBJS:.o=.64.o) FORMOBJS = form-attr.o form-main.o form-ps.o form-text.o form-tree.o OBJS = $(HPGLOBJS) $(IMAGEOBJS) $(FORMOBJS) \ - gziptoany.o imagetops.o imagetoraster.o common.o pstops.o \ - rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \ - testimage.o testraster.o textcommon.o texttops.o + gziptoany.o imagetops.o imagetoraster.o common.o pdftops.o \ + pstops.o rasterbench.o rastertoepson.o rastertohp.o \ + rastertolabel.o testimage.o testraster.o textcommon.o texttops.o # @@ -324,6 +324,15 @@ pstops: pstops.o common.o ../cups/$(LIBC # +# pdftops +# + +pdftops: pdftops.o common.o ../cups/$(LIBCUPS) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ pdftops.o common.o $(LIBS) + + +# # rastertolabel # diff -up cups-1.3.7/filter/pdftops.c.poppler-pdftops cups-1.3.7/filter/pdftops.c --- cups-1.3.7/filter/pdftops.c.poppler-pdftops 2010-02-12 17:16:11.529917784 +0000 +++ cups-1.3.7/filter/pdftops.c 2010-02-12 17:16:11.529917784 +0000 @@ -0,0 +1,607 @@ +/* + * "$Id: pdftops.c 8676 2009-05-22 19:30:50Z mike $" + * + * PDF to PostScript filter front-end for the Common UNIX Printing + * System (CUPS). + * + * Copyright 2007-2009 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * 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/". + * + * Contents: + * + * main() - Main entry for filter... + * cancel_job() - Flag the job as canceled. + */ + +/* + * Include necessary headers... + */ + +#include <cups/cups.h> +#include <cups/string.h> +#include <cups/i18n.h> +#include <signal.h> +#include <sys/wait.h> +#include <errno.h> + + +/* + * Local functions... + */ + +static void cancel_job(int sig); + + +/* + * Local globals... + */ + +static int job_canceled = 0; + + +/* + * 'main()' - Main entry for filter... + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int fd; /* Copy file descriptor */ + char *filename, /* PDF file to convert */ + tempfile[1024]; /* Temporary file */ + char buffer[8192]; /* Copy buffer */ + int bytes; /* Bytes copied */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + const char *val; /* Option value */ + int orientation, /* Output orientation */ + fit; /* Fit output to default page size? */ + ppd_file_t *ppd; /* PPD file */ + ppd_size_t *size; /* Current page size */ + int pdf_pid, /* Process ID for pdftops */ + pdf_argc, /* Number of args for pdftops */ + pstops_pid, /* Process ID of pstops filter */ + pstops_pipe[2], /* Pipe to pstops filter */ + wait_children, /* Number of child processes left */ + wait_pid, /* Process ID from wait() */ + wait_status, /* Status from child */ + exit_status = 0; /* Exit status */ + char *pdf_argv[100], /* Arguments for pdftops/gs */ + pdf_width[255], /* Paper width */ + pdf_height[255], /* Paper height */ + pstops_path[1024], /* Path to pstops program */ + *pstops_argv[7], /* Arguments for pstops filter */ + *pstops_options, /* Options for pstops filter */ + *pstops_start, /* Start of pstops filter option */ + *pstops_end; /* End of pstops filter option */ + const char *cups_serverbin; /* CUPS_SERVERBIN environment variable */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ + + + /* + * Make sure status messages are not buffered... + */ + + setbuf(stderr, NULL); + + /* + * Make sure we have the right number of arguments for CUPS! + */ + + if (argc < 6 || argc > 7) + { + _cupsLangPrintf(stderr, + _("Usage: %s job user title copies options [filename]\n"), + argv[0]); + return (1); + } + + /* + * Register a signal handler to cleanly cancel a job. + */ + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, cancel_job); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = cancel_job; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, cancel_job); +#endif /* HAVE_SIGSET */ + + /* + * Copy stdin if needed... + */ + + if (argc == 6) + { + /* + * Copy stdin to a temp file... + */ + + if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) + { + _cupsLangPrintf(stderr, _("ERROR: Unable to copy PDF file: %s\n"), + strerror(errno)); + return (1); + } + + fprintf(stderr, "DEBUG: pdftops - copying to temp print file \"%s\"\n", + tempfile); + + while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) + write(fd, buffer, bytes); + + close(fd); + + filename = tempfile; + } + else + { + /* + * Use the filename on the command-line... + */ + + filename = argv[6]; + tempfile[0] = '\0'; + } + + /* + * Load the PPD file and mark options... + */ + + ppd = ppdOpenFile(getenv("PPD")); + num_options = cupsParseOptions(argv[5], 0, &options); + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + + /* + * Build the pstops command-line... + */ + + if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL) + cups_serverbin = CUPS_SERVERBIN; + + snprintf(pstops_path, sizeof(pstops_path), "%s/filter/pstops", + cups_serverbin); + + pstops_options = strdup(argv[5]); + + if ((pstops_start = strstr(pstops_options, "fitplot")) != NULL && + (!pstops_start[7] || isspace(pstops_start[7] & 255))) + { + /* + * Strip [no]fitplot option... + */ + + pstops_end = pstops_start + 7; + + if ((pstops_start - pstops_options) >= 2 && + !strncmp(pstops_start - 2, "no", 2)) + pstops_start -= 2; + + while (*pstops_end && isspace(*pstops_end & 255)) + pstops_end ++; + + _cups_strcpy(pstops_start, pstops_end); + } + + if ((pstops_start = strstr(pstops_options, "fit-to-page")) != NULL && + (!pstops_start[11] || isspace(pstops_start[11] & 255))) + { + /* + * Strip [no]fit-to-page option... + */ + + pstops_end = pstops_start + 11; + + if ((pstops_start - pstops_options) >= 2 && + !strncmp(pstops_start - 2, "no", 2)) + pstops_start -= 2; + + while (*pstops_end && isspace(*pstops_end & 255)) + pstops_end ++; + + _cups_strcpy(pstops_start, pstops_end); + } + + if ((pstops_start = strstr(pstops_options, "landscape")) != NULL && + (!pstops_start[9] || isspace(pstops_start[9] & 255))) + { + /* + * Strip [no]landscape option... + */ + + pstops_end = pstops_start + 9; + + if ((pstops_start - pstops_options) >= 2 && + !strncmp(pstops_start - 2, "no", 2)) + pstops_start -= 2; + + while (*pstops_end && isspace(*pstops_end & 255)) + pstops_end ++; + + _cups_strcpy(pstops_start, pstops_end); + } + + if ((pstops_start = strstr(pstops_options, "orientation-requested=")) != NULL) + { + /* + * Strip [no]fitplot option... + */ + + pstops_end = pstops_start + 22; + while (*pstops_end && !isspace(*pstops_end & 255)) + pstops_end ++; + + _cups_strcpy(pstops_start, pstops_end); + } + + pstops_argv[0] = argv[0]; /* Printer */ + pstops_argv[1] = argv[1]; /* Job */ + pstops_argv[2] = argv[2]; /* User */ + pstops_argv[3] = argv[3]; /* Title */ + pstops_argv[4] = argv[4]; /* Copies */ + pstops_argv[5] = pstops_options; /* Options */ + pstops_argv[6] = NULL; + + /* + * Build the command-line for the pdftops or gs filter... + */ + +#ifdef HAVE_PDFTOPS + pdf_argv[0] = (char *)"pdftops"; + pdf_argc = 1; +#else + pdf_argv[0] = (char *)"gs"; + pdf_argv[1] = (char *)"-q"; + pdf_argv[2] = (char *)"-dNOPAUSE"; + pdf_argv[3] = (char *)"-dBATCH"; + pdf_argv[4] = (char *)"-dSAFER"; + pdf_argv[5] = (char *)"-sDEVICE=pswrite"; + pdf_argv[6] = (char *)"-sOUTPUTFILE=%stdout"; + pdf_argc = 7; +#endif /* HAVE_PDFTOPS */ + + if (ppd) + { + /* + * Set language level and TrueType font handling... + */ + + if (ppd->language_level == 1) + { +#ifdef HAVE_PDFTOPS + pdf_argv[pdf_argc++] = (char *)"-level1"; + pdf_argv[pdf_argc++] = (char *)"-noembtt"; +#else + pdf_argv[pdf_argc++] = (char *)"-dLanguageLevel=1"; +#endif /* HAVE_PDFTOPS */ + } + else if (ppd->language_level == 2) + { +#ifdef HAVE_PDFTOPS + pdf_argv[pdf_argc++] = (char *)"-level2"; + if (!ppd->ttrasterizer) + pdf_argv[pdf_argc++] = (char *)"-noembtt"; +#else + pdf_argv[pdf_argc++] = (char *)"-dLanguageLevel=2"; +#endif /* HAVE_PDFTOPS */ + } + else +#ifdef HAVE_PDFTOPS + pdf_argv[pdf_argc++] = (char *)"-level3"; +#else + pdf_argv[pdf_argc++] = (char *)"-dLanguageLevel=3"; +#endif /* HAVE_PDFTOPS */ + + if ((val = cupsGetOption("fitplot", num_options, options)) == NULL) + val = cupsGetOption("fit-to-page", num_options, options); + + if (val && strcasecmp(val, "no") && strcasecmp(val, "off") && + strcasecmp(val, "false")) + fit = 1; + else + fit = 0; + + /* + * Set output page size... + */ + + size = ppdPageSize(ppd, NULL); + if (size && fit) + { + /* + * Got the size, now get the orientation... + */ + + orientation = 0; + + if ((val = cupsGetOption("landscape", num_options, options)) != NULL) + { + if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 && + strcasecmp(val, "false") != 0) + orientation = 1; + } + else if ((val = cupsGetOption("orientation-requested", num_options, options)) != NULL) + { + /* + * Map IPP orientation values to 0 to 3: + * + * 3 = 0 degrees = 0 + * 4 = 90 degrees = 1 + * 5 = -90 degrees = 3 + * 6 = 180 degrees = 2 + */ + + orientation = atoi(val) - 3; + if (orientation >= 2) + orientation ^= 1; + } + +#ifdef HAVE_PDFTOPS + if (orientation & 1) + { + snprintf(pdf_width, sizeof(pdf_width), "%.0f", size->length); + snprintf(pdf_height, sizeof(pdf_height), "%.0f", size->width); + } + else + { + snprintf(pdf_width, sizeof(pdf_width), "%.0f", size->width); + snprintf(pdf_height, sizeof(pdf_height), "%.0f", size->length); + } + + pdf_argv[pdf_argc++] = (char *)"-paperw"; + pdf_argv[pdf_argc++] = pdf_width; + pdf_argv[pdf_argc++] = (char *)"-paperh"; + pdf_argv[pdf_argc++] = pdf_height; + pdf_argv[pdf_argc++] = (char *)"-expand"; + +#else + if (orientation & 1) + { + snprintf(pdf_width, sizeof(pdf_width), "-dDEVICEWIDTHPOINTS=%.0f", + size->length); + snprintf(pdf_height, sizeof(pdf_height), "-dDEVICEHEIGHTPOINTS=%.0f", + size->width); + } + else + { + snprintf(pdf_width, sizeof(pdf_width), "-dDEVICEWIDTHPOINTS=%.0f", + size->width); + snprintf(pdf_height, sizeof(pdf_height), "-dDEVICEHEIGHTPOINTS=%.0f", + size->length); + } + + pdf_argv[pdf_argc++] = pdf_width; + pdf_argv[pdf_argc++] = pdf_height; +#endif /* HAVE_PDFTOPS */ + } + } + +#ifdef HAVE_PDFTOPS + pdf_argv[pdf_argc++] = filename; + pdf_argv[pdf_argc++] = (char *)"-"; +#else + pdf_argv[pdf_argc++] = (char *)"-c"; + pdf_argv[pdf_argc++] = (char *)"save pop"; + pdf_argv[pdf_argc++] = (char *)"-f"; + pdf_argv[pdf_argc++] = filename; +#endif /* HAVE_PDFTOPS */ + + pdf_argv[pdf_argc] = NULL; + + /* + * Execute "pdftops/gs | pstops"... + */ + + if (pipe(pstops_pipe)) + { + _cupsLangPrintf(stderr, _("ERROR: Unable to create pipe: %s\n"), + strerror(errno)); + + exit_status = 1; + goto error; + } + + if ((pdf_pid = fork()) == 0) + { + /* + * Child comes here... + */ + + dup2(pstops_pipe[1], 1); + close(pstops_pipe[0]); + close(pstops_pipe[1]); + +#ifdef HAVE_PDFTOPS + execv(CUPS_PDFTOPS, pdf_argv); + _cupsLangPrintf(stderr, _("ERROR: Unable to execute pdftops program: %s\n"), + strerror(errno)); +#else + execv(CUPS_GHOSTSCRIPT, pdf_argv); + _cupsLangPrintf(stderr, _("ERROR: Unable to execute gs program: %s\n"), + strerror(errno)); +#endif /* HAVE_PDFTOPS */ + + exit(1); + } + else if (pdf_pid < 0) + { + /* + * Unable to fork! + */ + +#ifdef HAVE_PDFTOPS + _cupsLangPrintf(stderr, _("ERROR: Unable to execute pdftops program: %s\n"), + strerror(errno)); +#else + _cupsLangPrintf(stderr, _("ERROR: Unable to execute gs program: %s\n"), + strerror(errno)); +#endif /* HAVE_PDFTOPS */ + + exit_status = 1; + goto error; + } + + fprintf(stderr, "DEBUG: Started filter %s (PID %d)\n", pdf_argv[0], pdf_pid); + + if ((pstops_pid = fork()) == 0) + { + /* + * Child comes here... + */ + + dup2(pstops_pipe[0], 0); + close(pstops_pipe[0]); + close(pstops_pipe[1]); + + execv(pstops_path, pstops_argv); + _cupsLangPrintf(stderr, _("ERROR: Unable to execute pstops program: %s\n"), + strerror(errno)); + + exit(1); + } + else if (pstops_pid < 0) + { + /* + * Unable to fork! + */ + + _cupsLangPrintf(stderr, _("ERROR: Unable to execute pstops program: %s\n"), + strerror(errno)); + + exit_status = 1; + goto error; + } + + fprintf(stderr, "DEBUG: Started filter pstops (PID %d)\n", pstops_pid); + + close(pstops_pipe[0]); + close(pstops_pipe[1]); + + /* + * Wait for the child processes to exit... + */ + + wait_children = 2; + + while (wait_children > 0) + { + /* + * Wait until we get a valid process ID or the job is canceled... + */ + + while ((wait_pid = wait(&wait_status)) < 0 && errno == EINTR) + { + if (job_canceled) + { + kill(pdf_pid, SIGTERM); + kill(pstops_pid, SIGTERM); + + job_canceled = 0; + } + } + + if (wait_pid < 0) + break; + + wait_children --; + + /* + * Report child status... + */ + + if (wait_status) + { + if (WIFEXITED(wait_status)) + { + exit_status = WEXITSTATUS(wait_status); + + fprintf(stderr, "DEBUG: PID %d (%s) stopped with status %d!\n", + wait_pid, +#ifdef HAVE_PDFTOPS + wait_pid == pdf_pid ? "pdftops" : "pstops", +#else + wait_pid == pdf_pid ? "gs" : "pstops", +#endif /* HAVE_PDFTOPS */ + exit_status); + } + else if (WTERMSIG(wait_status) == SIGTERM) + { + fprintf(stderr, + "DEBUG: PID %d (%s) was terminated normally with signal %d!\n", + wait_pid, +#ifdef HAVE_PDFTOPS + wait_pid == pdf_pid ? "pdftops" : "pstops", +#else + wait_pid == pdf_pid ? "gs" : "pstops", +#endif /* HAVE_PDFTOPS */ + exit_status); + } + else + { + exit_status = WTERMSIG(wait_status); + + fprintf(stderr, "DEBUG: PID %d (%s) crashed on signal %d!\n", wait_pid, +#ifdef HAVE_PDFTOPS + wait_pid == pdf_pid ? "pdftops" : "pstops", +#else + wait_pid == pdf_pid ? "gs" : "pstops", +#endif /* HAVE_PDFTOPS */ + exit_status); + } + } + else + { + fprintf(stderr, "DEBUG: PID %d (%s) exited with no errors.\n", wait_pid, +#ifdef HAVE_PDFTOPS + wait_pid == pdf_pid ? "pdftops" : "pstops"); +#else + wait_pid == pdf_pid ? "gs" : "pstops"); +#endif /* HAVE_PDFTOPS */ + } + } + + /* + * Cleanup and exit... + */ + + error: + + if (tempfile[0]) + unlink(tempfile); + + return (exit_status); +} + + +/* + * 'cancel_job()' - Flag the job as canceled. + */ + +static void +cancel_job(int sig) /* I - Signal number (unused) */ +{ + (void)sig; + + job_canceled = 1; +} + + +/* + * End of "$Id: pdftops.c 8676 2009-05-22 19:30:50Z mike $". + */ diff -up cups-1.3.7/Makefile.poppler-pdftops cups-1.3.7/Makefile --- cups-1.3.7/Makefile.poppler-pdftops 2008-02-15 23:26:51.000000000 +0000 +++ cups-1.3.7/Makefile 2010-02-12 17:16:11.532917010 +0000 @@ -20,7 +20,7 @@ include Makedefs # DIRS = cups backend berkeley cgi-bin filter locale man monitor \ - notifier $(PDFTOPS) scheduler systemv test \ + notifier scheduler systemv test \ $(PHPDIR) \ conf data doc $(FONTS) ppd templates