diff --git a/PrintAnalyzer b/PrintAnalyzer new file mode 100644 index 0000000..84a1a73 --- /dev/null +++ b/PrintAnalyzer @@ -0,0 +1,499 @@ +#!/usr/bin/perl -w +#*************************************************************************** +# PrintAnalyzer +# Generate some stats from cups page_log file +# copyright : (C) 1999 - 2002 by Thies Moeller +# email : moeller@tu-harburg.de +#*************************************************************************** + +#*************************************************************************** +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU General Public License as published by * +#* the Free Software Foundation; either version 2 of the License, or * +#* (at your option) any later version. * +#* * +#*************************************************************************** +use strict; +use warnings; +use POSIX qw(strftime); +use Time::Local; + +############## +# edit place of your page_log file +############## + +my $PAGE_LOG_FILE = "/var/log/cups/page_log"; + +############## +# edit start and end of normal work time +# activity outside this interval will be marked with an "!" +# to disable set WorkStart to 0 and WorkEnd to 23 +############## +my $WorkStart = 8; +my $WorkEnd = 21; + + +############################ nothing to modify below this line ############## + +my %userRequests = (); +my %userPages = (); +my %hourRequests = (); +my %dateRequests = (); +my %datePages = (); +my %pageRequests = (); +my %queueRequests = (); +my %queuePages = (); +my %pageHeu = (); +my %copyRequests = (); +my %logline = (); +my %lastlogline = (); +my %billingStats = (); +my $totalReq = 0; +my $totalPages = 0; + +sub DateCompare +{ + my $date1 = substr($a, 6, 2) * 1024; # Years + my $date2 = substr($b, 6, 2) * 1024; + + $date1 += substr($a,3,2) * 64; # Months + $date2 += substr($b,3,2) * 64; + + $date1 += substr($a, 0, 2); # Days + $date2 += substr($b, 0, 2); + return ($date1 <=> $date2); +} + + +sub tzdiff2sec +{ +## this method is copied from LogReport Time.pm +## Copyright (C) 2000-2002 Stichting LogReport Foundation LogReport@LogReport.org + + die "tzdiff2sec needs 1 arg\n" + unless @_ == 1; + + # e.g. +0100 or -0900 ; +hh:mm, +hhmm, or +hh + my ( $sign, $hour, $min ) = $_[0] =~ /^([+-])?(\d\d):?(\d\d)?$/ + or die "invalid tzdiff format: $_[0]. It must looks like +0100 or -01:00\n"; + $sign ||= "+"; + $hour ||= 0; + $min ||= 0; + my $sec = $hour * 60 * 60 + $min * 60; + $sec *= -1 if $sign eq '-'; + return $sec; +} + +sub getMonth +{ + my $AllMonths= 'JanFebMarAprMayJunJulAugSepOctNovDec'; + my $month = shift(@_); + return index($AllMonths, $month)/3; +} + + + +sub DateTime2Epoch +{ + my ($day,$month,$year,$hour,$min,$sec,$tz)= + unpack'@1 A2 @4 A3 @8 A4 @13 A2 @16 A2 @19 A2 @22 A5', shift(); + + my $epoch=timegm $sec , + $min , + $hour, + $day, + getMonth($month), + $year; + return $epoch - tzdiff2sec($tz); +} + +sub PrintDayLog +{ + my $dateReq; + +############# Output Form ################ +format DAYLOG_TOP = + +Daily Usage +Date %Requests Pages +----------------------------------------- +. + +format DAYLOG = +@<<<<<<<<<<<<< @>>>>>>> @>>>>>>> +$dateReq,$dateRequests{$dateReq},$datePages{$dateReq} +. +############# Output Form ################ + + + $-=0; + $~="DAYLOG"; + $^="DAYLOG_TOP"; + foreach $dateReq (sort DateCompare keys %dateRequests) + { + #printf("Monat %d\n",getMonth($dateReq)); + write; + } +} + +sub PrintUserLog +{ + my $userReq; + my $pageperjob; + +############# Output Form ################ +format USERLOG_TOP = +PrinterAccounting +Username Requests Pages Pages/Request +-------------------------------------------------------- +. + +format USERLOG = +@<<<<<<<<<<<<<<<<<< @>>>>>>> @>>>>>>> @>>>>>>>> +$userReq, $userRequests{$userReq}, $userPages{$userReq}, $pageperjob +. +############# Output Form ################ + + $-=0; + $~="USERLOG"; + $^="USERLOG_TOP"; + foreach $userReq (sort { $userPages{$b} <=> $userPages{$a}} keys %userRequests) + { + $pageperjob = sprintf("%5d", POSIX::ceil($userPages{$userReq} / $userRequests{$userReq})); + write ; + } +} + +sub PrintHourLog +{ + my $hourReq; + my $outOfWorkingTime; + +############# Output Form ################ +format HOURLOG_TOP = +Hour Usage +Hour Requests +--------------------- +. + +format HOURLOG = +@<@<<<<< @>>>>>>> +$outOfWorkingTime,$hourReq,$hourRequests{$hourReq} +. +############# Output Form ################ + + + $-=0; + $~="HOURLOG"; + $^="HOURLOG_TOP"; + + foreach $hourReq (sort {$a <=> $b} keys %hourRequests) + { + if($hourReq <$WorkStart || $hourReq > $WorkEnd) + { + if($hourRequests{$hourReq} == 0) + { + next; + } + else + { + $outOfWorkingTime = "!"; + } + } + else + { + $outOfWorkingTime = " "; + } + write; + } + +} + +sub PrintRequestSize +{ + my $pageReq; + my %pageHeu; + my $pageHeuK; + my $pageperHeu; +############# Output Form ################ + +format REQUESTLOG_TOP = +Heuristic +JobSize %Requests +--------------------------- +. + +format REQUESTLOG = +@||||||||||| @>>>>>>>> +$pageHeuK,$pageperHeu +. +############# Output Form ################ + + # sammeln der Daten + foreach $pageReq (sort {$a <=> $b} keys %pageRequests) + { + if($pageReq >0 && $pageReq <=10) + {$pageHeu{"1. 0-10"}+=$pageRequests{$pageReq}}; + if ($pageReq >10 && $pageReq <=20) + {$pageHeu{ "2. 20-30"}+=$pageRequests{$pageReq}}; + if ($pageReq >20 && $pageReq <=30) + {$pageHeu{ "3. 30-40"}+=$pageRequests{$pageReq}}; + if ($pageReq >40 && $pageReq <=50) + {$pageHeu{ "4. 40-50"}+=$pageRequests{$pageReq}}; + if ($pageReq >50 && $pageReq <=100) + {$pageHeu{ "5. 50-100"}+=$pageRequests{$pageReq}}; + if ($pageReq >100 && $pageReq <=200) + {$pageHeu{ "6. 100-200"}+=$pageRequests{$pageReq}}; + if ($pageReq >200 ) + {$pageHeu{ "7. 200- "}+=$pageRequests{$pageReq}}; + } + $-=0; + $~="REQUESTLOG"; + $^="REQUESTLOG_TOP"; + + foreach $pageHeuK (sort keys %pageHeu) + { + $pageperHeu = sprintf("%5.2f", 100*$pageHeu{$pageHeuK}/$totalReq); + write; + } +} + +sub PrintCopySize +{ + my $copyReq; + my %copyHeu; + my $copyHeuK; + my $copyperheu; +############# Output Form ################ +format COPY_TOP = +Heuristic +Copies %Requests +--------------------------- +. +format COPYLOG = +@||||||||||||| @>>>>>>>> +$copyHeuK,$copyperheu +. +############# Output Form ################ + + + foreach $copyReq (sort {$a <=> $b} keys %copyRequests) + { + if($copyReq == 1 ) + {$copyHeu{" 1. single"}+=$copyRequests{$copyReq}}; + if($copyReq == 2) + {$copyHeu{" 2. 2 "}+=$copyRequests{$copyReq}}; + if($copyReq == 3) + {$copyHeu{" 3. 3 "}+=$copyRequests{$copyReq}}; + if($copyReq == 4) + {$copyHeu{" 4. 4 "}+=$copyRequests{$copyReq}}; + if($copyReq >=5 && $copyReq <=10) + {$copyHeu{" 5. 5-10 "}+=$copyRequests{$copyReq}}; + if ($copyReq >10 && $copyReq <=20) + {$copyHeu{ " 6. 20-30 "}+=$copyRequests{$copyReq}}; + if ($copyReq >20 && $copyReq <=30) + {$copyHeu{ " 7. 30-40 "}+=$copyRequests{$copyReq}}; + if ($copyReq >40 && $copyReq <=50) + {$copyHeu{ " 8. 40-50 "}+=$copyRequests{$copyReq}}; + if ($copyReq >50 && $copyReq <=100) + {$copyHeu{ " 9. 50-100 "}+=$copyRequests{$copyReq}}; + if ($copyReq >100 && $copyReq <=200) + {$copyHeu{ "10. 100-200 "}+=$copyRequests{$copyReq}}; + if ($copyReq >200 ) + {$copyHeu{ "11. 200- "}+=$copyRequests{$copyReq}}; + } + $-=0; + $~="COPYLOG"; + $^="COPY_TOP"; + foreach $copyHeuK (sort keys %copyHeu) + { + $copyperheu = sprintf("%5.2f", 100*$copyHeu{$copyHeuK}/$totalReq); + write; + } +} + +sub PrintQueueLog +{ + my $queueReq; + my $reqperqueue; + my $pagepermin; + my $pageperqueue ; +############# Output Form ################ +format QUEUELOG_TOP = +Queue Heuristic +Queue %Requests %Pages Pages +-------------------------------------------------------------- +. + +format QUEUELOG = +@>>>>>>>>>>>>>>>>>>>>> @>>>>>>> @>>>>>>> @>>>>>>>> +$queueReq,$reqperqueue,$pageperqueue,$queuePages{$queueReq} +. +############# Output Form ################ + + + $-=0; + $~="QUEUELOG"; + $^="QUEUELOG_TOP"; + foreach $queueReq (sort { $queuePages{$b} <=> $queuePages{$a} } keys %queuePages) + { + $reqperqueue = sprintf("%5.2f", 100*$queueRequests{$queueReq}/$totalReq); + $pageperqueue = sprintf("%5.2f", 100*$queuePages{$queueReq}/$totalPages); + write; + } + +} + +sub PrintBillingLog +{ + my $billing; + my $pageperbilling ; + my $billinguser; + +############# Output Form ################ +format BILLINGLOG_TOP = +Billing Heuristic +Billing Pages +-------------------------------------------------------------- +. + +format BILLINGLOG = +@<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>> +$billing,$pageperbilling +. + +format BILLINGUSERLOG = +|- @>>>>>>>>>>>>>>>>>>>>> @>>>>>>>> +$billinguser,$pageperbilling +. +############# Output Form ################ + + + $-=0; + $~="BILLINGLOG"; + $^="BILLINGLOG_TOP"; + foreach $billing (sort keys %billingStats) + { + $pageperbilling = $billingStats{$billing}{"total_pages"}; + $~="BILLINGLOG"; + write; + $~="BILLINGUSERLOG"; + foreach $billinguser ( sort {$billingStats{$billing}{"user"}{$b} <=> $billingStats{$billing}{"user"}{$a}} keys %{$billingStats{$billing}{"user"}}) + { + $pageperbilling = $billingStats{$billing}{"user"}{$billinguser}; + write; + } + } + +} + +sub HandleNewJob +{ + my $realpages = $lastlogline{num_pages}*$lastlogline{copies}; + my $hourstring = POSIX::strftime "%H", localtime($lastlogline{time}) ; + my $daystring = POSIX::strftime "%d/%m/%y", localtime($lastlogline{time}) ; + + $userRequests{$lastlogline{user}}++; + $userPages{$lastlogline{user}}+=$realpages; + $dateRequests{$daystring}++; + $datePages{$daystring}+=$realpages; + $pageRequests{$realpages}++; + $queueRequests{$lastlogline{printer}}++; + $queuePages{$lastlogline{printer}}+=$realpages; + $hourRequests{$hourstring}++; + $copyRequests{$lastlogline{copies}}++; + $billingStats{$lastlogline{billing}}{"user"}{$lastlogline{user}} += $realpages; + $billingStats{$lastlogline{billing}}{"printer"}{$lastlogline{printer}} += $realpages; + $billingStats{$lastlogline{billing}}{"total_pages"} += $realpages; + + $totalReq++; + $totalPages+=$realpages; + +} + +sub InitHourHistogram +{ + my $i; + for ($i = 0 ; $i <=24 ; $i++) + { + my $hourstring = sprintf("%02d", $i); + $hourRequests{$hourstring}=0; + } +} + +# main +open(PAGELOG,"$PAGE_LOG_FILE") || die "Can't open pagelog file $PAGE_LOG_FILE"; + + +#initialize the hourhistogram +InitHourHistogram; + +while() +{ + my $time; + my $pagenum; + %logline = (); + chomp(); + ($logline{printer}, + $logline{user}, + $logline{jobid}, + $time, + $pagenum, + $logline{copies}, + $logline{billing}) = + ($_ =~ /^(.*)\s(.*)\s(\d+)\s(\[.*\])\s(\d+)\s(\d+)\s(.*)$/) + or do { + print STDERR "Cannot convert $_ \n"; + next; + }; + # downcase username because of samba + $logline{user}=~ tr/A-Z/a-z/; + # handle empty user + if ($logline{user} eq "") { + $logline{user}="TestPages"; + } + # handle empty billing code + if ($logline{billing} eq "") { + $logline{billing}="-none-"; + } + my $endtime = DateTime2Epoch( $time ); + + if ( ! defined $lastlogline{jobid} || $lastlogline{jobid} ne $logline{jobid} ) + { + # new job; + $logline{num_pages} = 1; + $logline{time} = $endtime; + if ( defined $lastlogline{jobid} ) { + HandleNewJob; + }; + } else { + # same job; update info + $logline{num_pages} = $lastlogline{num_pages} + 1; + $logline{time} = $lastlogline{time}; + } + %lastlogline= %logline; + +} +close(PAGELOG); + +# handle last job +if ( defined $lastlogline{jobid} ) { + HandleNewJob; + } + + + +PrintQueueLog; +PrintRequestSize; +PrintCopySize; +PrintBillingLog; +PrintUserLog; +PrintHourLog; +PrintDayLog; + + + + + + diff --git a/cups-1.1.21-testppd_duplex.patch b/cups-1.1.21-testppd_duplex.patch new file mode 100644 index 0000000..ef7c814 --- /dev/null +++ b/cups-1.1.21-testppd_duplex.patch @@ -0,0 +1,23 @@ +Index: cups-1.3.11/systemv/cupstestppd.c +=================================================================== +--- cups-1.3.11.orig/systemv/cupstestppd.c ++++ cups-1.3.11/systemv/cupstestppd.c +@@ -931,6 +931,7 @@ main(int argc, /* I - Number of comm + if (size->left == 0.0 && size->bottom == 0.0 && + size->right == 0.0 && size->top == 0.0) + { ++#if 0 + if (verbose >= 0) + { + if (!errors && !verbose) +@@ -945,6 +946,10 @@ main(int argc, /* I - Number of comm + } + + errors ++; ++#else ++ printf(" WARN Bad %s choice %s!\n", ++ option->keyword, choice->choice); ++#endif + } + + /* diff --git a/cups-1.2.0-ppdsdat_generation.patch b/cups-1.2.0-ppdsdat_generation.patch new file mode 100644 index 0000000..3d8beb2 --- /dev/null +++ b/cups-1.2.0-ppdsdat_generation.patch @@ -0,0 +1,99 @@ +Index: cups-1.3.11/scheduler/main.c +=================================================================== +--- cups-1.3.11.orig/scheduler/main.c ++++ cups-1.3.11/scheduler/main.c +@@ -172,6 +172,7 @@ main(int argc, /* I - Number of comm + */ + + fg = 0; ++ ppds_generation = 0; + + #ifdef HAVE_LAUNCHD + if (getenv("CUPSD_LAUNCHD")) +@@ -272,6 +273,10 @@ main(int argc, /* I - Number of comm + fg = 1; + break; + ++ case 'P' : /* generate ppds only */ ++ ppds_generation = 1; ++ break; ++ + default : /* Unknown option */ + _cupsLangPrintf(stderr, _("cupsd: Unknown option \"%c\" - " + "aborting!\n"), *opt); +@@ -340,17 +345,18 @@ main(int argc, /* I - Number of comm + perror("cupsd"); + return (1); + } +- else if (WIFEXITED(i)) ++ else if (!ppds_generation && WIFEXITED(i)) + { + fprintf(stderr, "cupsd: Child exited with status %d!\n", + WEXITSTATUS(i)); + return (2); + } +- else ++ else if (!ppds_generation || WTERMSIG(i)!=0) + { + fprintf(stderr, "cupsd: Child exited on signal %d!\n", WTERMSIG(i)); + return (3); +- } ++ } else ++ return (0); + } + + #ifdef __OpenBSD__ +@@ -625,6 +631,9 @@ main(int argc, /* I - Number of comm + } + #endif /* __sgi */ + ++ if (ppds_generation > 0) ++ return (stop_scheduler); ++ + /* + * Initialize authentication certificates... + */ +@@ -2031,13 +2040,14 @@ static void + usage(int status) /* O - Exit status */ + { + _cupsLangPuts(status ? stderr : stdout, +- _("Usage: cupsd [-c config-file] [-f] [-F] [-h] [-l]\n" ++ _("Usage: cupsd [-c config-file] [-f] [-F] [-h] [-l] [-P]\n" + "\n" + "-c config-file Load alternate configuration file\n" + "-f Run in the foreground\n" + "-F Run in the foreground but detach\n" + "-h Show this usage message\n" +- "-l Run cupsd from launchd(8)\n")); ++ "-l Run cupsd from launchd(8)\n" ++ "-P Generate ppds.dat and exit\n")); + exit(status); + } + +Index: cups-1.3.11/scheduler/cupsd.h +=================================================================== +--- cups-1.3.11.orig/scheduler/cupsd.h ++++ cups-1.3.11/scheduler/cupsd.h +@@ -180,6 +180,8 @@ VAR PSQUpdateQuotaProcPtr PSQUpdateQuota + + + ++VAR int ppds_generation;/* Generate ppds.dat and exit() */ ++ + + /* + * Prototypes... +Index: cups-1.3.11/scheduler/conf.c +=================================================================== +--- cups-1.3.11.orig/scheduler/conf.c ++++ cups-1.3.11/scheduler/conf.c +@@ -941,6 +941,9 @@ cupsdReadConfiguration(void) + return (0); + } + ++ if (ppds_generation > 0) ++ return(1); ++ + /* + * Setup environment variables... + */ diff --git a/cups-1.2.11-testppd_filename.patch b/cups-1.2.11-testppd_filename.patch new file mode 100644 index 0000000..0914244 --- /dev/null +++ b/cups-1.2.11-testppd_filename.patch @@ -0,0 +1,29 @@ +Index: cups-1.3.11/systemv/cupstestppd.c +=================================================================== +--- cups-1.3.11.orig/systemv/cupstestppd.c ++++ cups-1.3.11/systemv/cupstestppd.c +@@ -129,6 +129,7 @@ main(int argc, /* I - Number of comm + int i, j, k, m, n; /* Looping vars */ + int len; /* Length of option name */ + char *opt; /* Option character */ ++ char *ppdfilename; /* Pointer to actual PPD file */ + const char *ptr; /* Pointer into string */ + int files; /* Number of files */ + int verbose; /* Want verbose output? */ +@@ -375,6 +376,7 @@ main(int argc, /* I - Number of comm + + errors = 0; + ppdversion = 43; ++ ppdfilename = argv[i]; + + if (verbose > 0) + _cupsLangPuts(stdout, +@@ -1171,7 +1173,7 @@ main(int argc, /* I - Number of comm + + if (verbose >= 0) + { +- check_basics(argv[i]); ++ check_basics(ppdfilename); + + if (warn & WARN_CONSTRAINTS) + errors = check_constraints(ppd, errors, verbose, 1); diff --git a/cups-1.2.7-libwrap.patch b/cups-1.2.7-libwrap.patch new file mode 100644 index 0000000..18e4313 --- /dev/null +++ b/cups-1.2.7-libwrap.patch @@ -0,0 +1,54 @@ +*** cups-1.2.7/scheduler/Makefile.orig Mon Sep 11 20:30:09 2006 +--- cups-1.2.7/scheduler/Makefile Tue Feb 13 17:56:10 2007 +*************** TARGETS = \ +*** 77,82 **** +--- 77,83 ---- + testspeed \ + testsub + ++ CUPSDLIBS += -lwrap + + # + # Make everything... +--- cups-1.2.7/scheduler/client.c.orig 2006-11-15 21:28:39.000000000 +0100 ++++ cups-1.2.7/scheduler/client.c 2007-02-13 19:10:38.000000000 +0100 +@@ -65,6 +65,11 @@ + # include + #endif /* HAVE_GNUTLS */ + ++#include ++#include ++int allow_severity = LOG_INFO; ++int deny_severity = LOG_WARNING; ++ + + /* + * Local functions... +@@ -180,6 +185,27 @@ cupsdAcceptClient(cupsd_listener_t *lis) + con->http.hostaddr->ipv4.sin_port = lis->address.ipv4.sin_port; + + /* ++ * libwrap/tcp_wrappers: ++ * draht@suse.de, Tue Jan 29 2002 ++ * kssingvo@suse.de, Thu Feb 01 2007 ++ */ ++ ++ if (lis->address.addr.sa_family == AF_INET || lis->address.addr.sa_family == AF_INET6) { ++ struct request_info wrap_req; ++ ++ request_init(&wrap_req, RQ_DAEMON, "cupsd" , RQ_FILE, con->http.fd, NULL); ++ fromhost(&wrap_req); ++ if (!hosts_access(&wrap_req)) { /* we do not accept the connection: */ ++ cupsdLogMessage(CUPSD_LOG_WARN, ++ "tcp_wrappers refused connection from %s, ip=%s. See /etc/hosts.allow and /etc/hosts.deny.", ++ eval_client(&wrap_req), eval_hostaddr(wrap_req.client)); ++ close(con->http.fd); ++ free(con); ++ return; ++ } ++ } ++ ++ /* + * Check the number of clients on the same address... + */ + diff --git a/cups-1.3.11-CVE-2009-2820-regression-fix.patch b/cups-1.3.11-CVE-2009-2820-regression-fix.patch new file mode 100644 index 0000000..2b48048 --- /dev/null +++ b/cups-1.3.11-CVE-2009-2820-regression-fix.patch @@ -0,0 +1,27 @@ +--- cgi-bin/admin.c.after-cups-1.3.11-CVE-2009-2820-patch 2009-11-03 12:33:53.000000000 +0100 ++++ cgi-bin/admin.c 2009-11-03 12:37:37.000000000 +0100 +@@ -486,6 +486,7 @@ do_am_class(http_t *http, /* I - HTTP c + ipp_attribute_t *attr; /* member-uris attribute */ + char uri[HTTP_MAX_URI]; /* Device or printer URI */ + const char *name, /* Pointer to class name */ ++ *op, /* Operation name */ + *ptr; /* Pointer to CGI variable */ + const char *title; /* Title of page */ + static const char * const pattrs[] = /* Requested printer attributes */ +@@ -497,6 +498,7 @@ do_am_class(http_t *http, /* I - HTTP c + + + title = cgiText(modify ? _("Modify Class") : _("Add Class")); ++ op = cgiGetVariable("OP"); + name = cgiGetVariable("PRINTER_NAME"); + + if (cgiGetVariable("PRINTER_LOCATION") == NULL) +@@ -516,6 +518,8 @@ do_am_class(http_t *http, /* I - HTTP c + */ + + cgiClearVariables(); ++ if (op) ++ cgiSetVariable("OP", op); + if (name) + cgiSetVariable("PRINTER_NAME", name); + diff --git a/cups-1.3.11-CVE-2009-2820.patch b/cups-1.3.11-CVE-2009-2820.patch new file mode 100644 index 0000000..ca92046 --- /dev/null +++ b/cups-1.3.11-CVE-2009-2820.patch @@ -0,0 +1,424 @@ +diff -upr cups-1.3.11.orig/cgi-bin/admin.c cups-1.3.11/cgi-bin/admin.c +--- cups-1.3.11.orig/cgi-bin/admin.c 2009-06-18 23:42:45.000000000 +0200 ++++ cups-1.3.11/cgi-bin/admin.c 2009-10-21 11:43:02.000000000 +0200 +@@ -104,6 +104,7 @@ main(int argc, /* I - Number of comm + */ + + cgiSetVariable("SECTION", "admin"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we have form data... +@@ -134,16 +135,61 @@ main(int argc, /* I - Number of comm + + + if (getenv("HTTPS")) +- snprintf(prefix, sizeof(prefix), "https://%s:%s", +- getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ snprintf(prefix, sizeof(prefix), "https://%s:%s", ++ getenv("SERVER_NAME"), getenv("SERVER_PORT")); + else +- snprintf(prefix, sizeof(prefix), "http://%s:%s", +- getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ snprintf(prefix, sizeof(prefix), "http://%s:%s", ++ getenv("SERVER_NAME"), getenv("SERVER_PORT")); ++ ++ fprintf(stderr, "DEBUG: redirecting with prefix %s!\n", prefix); + + if ((url = cgiGetVariable("URL")) != NULL) +- printf("Location: %s%s\n\n", prefix, url); ++ { ++ char encoded[1024], /* Encoded URL string */ ++ *ptr; /* Pointer into encoded string */ ++ ++ ++ ptr = encoded; ++ if (*url != '/') ++ *ptr++ = '/'; ++ ++ for (; *url && ptr < (encoded + sizeof(encoded) - 4); url ++) ++ { ++ if (strchr("%@&+ <>#=", *url) || *url < ' ' || *url & 128) ++ { ++ /* ++ * Percent-encode this character; safe because we have at least 4 ++ * bytes left in the array... ++ */ ++ ++ sprintf(ptr, "%%%02X", *url & 255); ++ ptr += 3; ++ } ++ else ++ *ptr++ = *url; ++ } ++ ++ *ptr = '\0'; ++ ++ if (*url) ++ { ++ /* ++ * URL was too long, just redirect to the admin page... ++ */ ++ ++ printf("Location: %s/admin\n\n", prefix); ++ } ++ else ++ { ++ /* ++ * URL is OK, redirect there... ++ */ ++ ++ printf("Location: %s%s\n\n", prefix, encoded); ++ } ++ } + else +- printf("Location: %s/admin\n\n", prefix); ++ printf("Location: %s/admin\n\n", prefix); + } + else if (!strcmp(op, "start-printer")) + do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer"))); +@@ -293,6 +339,31 @@ do_add_rss_subscription(http_t *http) /* + * and classes and (re)show the add page... + */ + ++ if (cgiGetVariable("EVENT_JOB_CREATED")) ++ cgiSetVariable("EVENT_JOB_CREATED", "CHECKED"); ++ if (cgiGetVariable("EVENT_JOB_COMPLETED")) ++ cgiSetVariable("EVENT_JOB_COMPLETED", "CHECKED"); ++ if (cgiGetVariable("EVENT_JOB_STOPPED")) ++ cgiSetVariable("EVENT_JOB_STOPPED", "CHECKED"); ++ if (cgiGetVariable("EVENT_JOB_CONFIG_CHANGED")) ++ cgiSetVariable("EVENT_JOB_CONFIG_CHANGED", "CHECKED"); ++ if (cgiGetVariable("EVENT_PRINTER_STOPPED")) ++ cgiSetVariable("EVENT_PRINTER_STOPPED", "CHECKED"); ++ if (cgiGetVariable("EVENT_PRINTER_ADDED")) ++ cgiSetVariable("EVENT_PRINTER_ADDED", "CHECKED"); ++ if (cgiGetVariable("EVENT_PRINTER_MODIFIED")) ++ cgiSetVariable("EVENT_PRINTER_MODIFIED", "CHECKED"); ++ if (cgiGetVariable("EVENT_PRINTER_DELETED")) ++ cgiSetVariable("EVENT_PRINTER_DELETED", "CHECKED"); ++ if (cgiGetVariable("EVENT_SERVER_STARTED")) ++ cgiSetVariable("EVENT_SERVER_STARTED", "CHECKED"); ++ if (cgiGetVariable("EVENT_SERVER_STOPPED")) ++ cgiSetVariable("EVENT_SERVER_STOPPED", "CHECKED"); ++ if (cgiGetVariable("EVENT_SERVER_RESTARTED")) ++ cgiSetVariable("EVENT_SERVER_RESTARTED", "CHECKED"); ++ if (cgiGetVariable("EVENT_SERVER_AUDIT")) ++ cgiSetVariable("EVENT_SERVER_AUDIT", "CHECKED"); ++ + request = ippNewRequest(CUPS_GET_PRINTERS); + response = cupsDoRequest(http, request, "/"); + +@@ -450,6 +521,10 @@ do_am_class(http_t *http, /* I - HTTP c + * Do the request and get back a response... + */ + ++ cgiClearVariables(); ++ if (name) ++ cgiSetVariable("PRINTER_NAME", name); ++ + if ((response = cupsDoRequest(http, request, "/")) != NULL) + { + /* +@@ -2336,7 +2411,9 @@ do_menu(http_t *http) /* I - HTTP conn + if ((val = cupsGetOption("DefaultAuthType", num_settings, + settings)) != NULL && !strcasecmp(val, "Negotiate")) + cgiSetVariable("KERBEROS", "CHECKED"); ++ else + #endif /* HAVE_GSSAPI */ ++ cgiSetVariable("KERBEROS", ""); + + cupsFreeOptions(num_settings, settings); + +diff -upr cups-1.3.11.orig/cgi-bin/cgi.h cups-1.3.11/cgi-bin/cgi.h +--- cups-1.3.11.orig/cgi-bin/cgi.h 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/cgi.h 2009-10-21 11:42:42.000000000 +0200 +@@ -54,6 +54,7 @@ typedef struct cgi_file_s /**** Uploade + extern void cgiAbort(const char *title, const char *stylesheet, + const char *format, ...); + extern int cgiCheckVariables(const char *names); ++extern void cgiClearVariables(void); + extern void *cgiCompileSearch(const char *query); + extern void cgiCopyTemplateFile(FILE *out, const char *tmpl); + extern void cgiCopyTemplateLang(const char *tmpl); +diff -upr cups-1.3.11.orig/cgi-bin/classes.c cups-1.3.11/cgi-bin/classes.c +--- cups-1.3.11.orig/cgi-bin/classes.c 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/classes.c 2009-10-21 11:43:16.000000000 +0200 +@@ -69,6 +69,7 @@ main(int argc, /* I - Number of comm + */ + + cgiSetVariable("SECTION", "classes"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we are displaying a printer or all classes... +diff -upr cups-1.3.11.orig/cgi-bin/help.c cups-1.3.11/cgi-bin/help.c +--- cups-1.3.11.orig/cgi-bin/help.c 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/help.c 2009-10-21 11:43:06.000000000 +0200 +@@ -63,6 +63,7 @@ main(int argc, /* I - Number of comm + */ + + cgiSetVariable("SECTION", "help"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * Load the help index... +@@ -102,7 +103,7 @@ main(int argc, /* I - Number of comm + */ + + for (i = 0; i < argc; i ++) +- fprintf(stderr, "argv[%d]=\"%s\"\n", i, argv[i]); ++ fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); + + if ((helpfile = getenv("PATH_INFO")) != NULL) + { +@@ -179,6 +180,12 @@ main(int argc, /* I - Number of comm + topic = cgiGetVariable("TOPIC"); + si = helpSearchIndex(hi, query, topic, helpfile); + ++ cgiClearVariables(); ++ if (query) ++ cgiSetVariable("QUERY", query); ++ if (topic) ++ cgiSetVariable("TOPIC", topic); ++ + fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n", + query ? query : "(null)", topic ? topic : "(null)"); + +diff -upr cups-1.3.11.orig/cgi-bin/ipp-var.c cups-1.3.11/cgi-bin/ipp-var.c +--- cups-1.3.11.orig/cgi-bin/ipp-var.c 2009-03-05 19:44:14.000000000 +0100 ++++ cups-1.3.11/cgi-bin/ipp-var.c 2009-10-21 11:42:57.000000000 +0200 +@@ -1220,7 +1220,9 @@ cgiShowJobs(http_t *http, /* I - Co + int ascending, /* Order of jobs (0 = descending) */ + first, /* First job to show */ + count; /* Number of jobs */ +- const char *var; /* Form variable */ ++ const char *var, /* Form variable */ ++ *query, /* Query string */ ++ *section; /* Section in web interface */ + void *search; /* Search data */ + char url[1024], /* URL for prev/next/this */ + *urlptr, /* Position in URL */ +@@ -1265,10 +1267,13 @@ cgiShowJobs(http_t *http, /* I - Co + * Get a list of matching job objects. + */ + +- if ((var = cgiGetVariable("QUERY")) != NULL) +- search = cgiCompileSearch(var); ++ if ((query = cgiGetVariable("QUERY")) != NULL) ++ search = cgiCompileSearch(query); + else ++ { ++ query = NULL; + search = NULL; ++ } + + jobs = cgiGetIPPObjects(response, search); + count = cupsArrayCount(jobs); +@@ -1293,16 +1298,27 @@ cgiShowJobs(http_t *http, /* I - Co + if (first < 0) + first = 0; + +- sprintf(url, "%d", count); +- cgiSetVariable("TOTAL", url); +- + if ((var = cgiGetVariable("ORDER")) != NULL) + ascending = !strcasecmp(var, "asc"); + else +- { + ascending = !which_jobs || !strcasecmp(which_jobs, "not-completed"); +- cgiSetVariable("ORDER", ascending ? "asc" : "dec"); +- } ++ ++ section = cgiGetVariable("SECTION"); ++ ++ cgiClearVariables(); ++ ++ if (query) ++ cgiSetVariable("QUERY", query); ++ ++ cgiSetVariable("ORDER", ascending ? "asc" : "dec"); ++ ++ cgiSetVariable("SECTION", section); ++ ++ sprintf(url, "%d", count); ++ cgiSetVariable("TOTAL", url); ++ ++ if (which_jobs) ++ cgiSetVariable("WHICH_JOBS", which_jobs); + + if (ascending) + { +@@ -1325,11 +1341,10 @@ cgiShowJobs(http_t *http, /* I - Co + + urlend = url + sizeof(url); + +- if ((var = cgiGetVariable("QUERY")) != NULL) ++ if (query != NULL) + { + if (dest) +- snprintf(url, sizeof(url), "/%s/%s?QUERY=", cgiGetVariable("SECTION"), +- dest); ++ snprintf(url, sizeof(url), "/%s/%s?QUERY=", section, dest); + else + strlcpy(url, "/jobs/?QUERY=", sizeof(url)); + +@@ -1344,7 +1359,7 @@ cgiShowJobs(http_t *http, /* I - Co + else + { + if (dest) +- snprintf(url, sizeof(url), "/%s/%s?", cgiGetVariable("SECTION"), dest); ++ snprintf(url, sizeof(url), "/%s/%s?", section, dest); + else + strlcpy(url, "/jobs/?", sizeof(url)); + +diff -upr cups-1.3.11.orig/cgi-bin/jobs.c cups-1.3.11/cgi-bin/jobs.c +--- cups-1.3.11.orig/cgi-bin/jobs.c 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/jobs.c 2009-10-21 11:43:13.000000000 +0200 +@@ -57,6 +57,7 @@ main(int argc, /* I - Number of comm + */ + + cgiSetVariable("SECTION", "jobs"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * Connect to the HTTP server... +diff -upr cups-1.3.11.orig/cgi-bin/printers.c cups-1.3.11/cgi-bin/printers.c +--- cups-1.3.11.orig/cgi-bin/printers.c 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/printers.c 2009-10-21 11:42:30.000000000 +0200 +@@ -72,6 +72,7 @@ main(int argc, /* I - Number of comm + */ + + cgiSetVariable("SECTION", "printers"); ++ cgiSetVariable("REFRESH_PAGE", ""); + + /* + * See if we are displaying a printer or all printers... +diff -upr cups-1.3.11.orig/cgi-bin/template.c cups-1.3.11/cgi-bin/template.c +--- cups-1.3.11.orig/cgi-bin/template.c 2008-07-12 00:48:49.000000000 +0200 ++++ cups-1.3.11/cgi-bin/template.c 2009-10-21 11:42:50.000000000 +0200 +@@ -639,6 +639,8 @@ cgi_puts(const char *s, /* I - String + fputs(">", out); + else if (*s == '\"') + fputs(""", out); ++ else if (*s == '\'') ++ fputs("'", out); + else if (*s == '&') + fputs("&", out); + else +@@ -659,7 +661,7 @@ cgi_puturi(const char *s, /* I - String + { + while (*s) + { +- if (strchr("%&+ <>#=", *s) || *s & 128) ++ if (strchr("%@&+ <>#=", *s) || *s < ' ' || *s & 128) + fprintf(out, "%%%02X", *s & 255); + else + putc(*s, out); +diff -upr cups-1.3.11.orig/cgi-bin/var.c cups-1.3.11/cgi-bin/var.c +--- cups-1.3.11.orig/cgi-bin/var.c 2009-05-08 06:56:54.000000000 +0200 ++++ cups-1.3.11/cgi-bin/var.c 2009-10-21 11:43:09.000000000 +0200 +@@ -15,6 +15,7 @@ + * Contents: + * + * cgiCheckVariables() - Check for the presence of "required" variables. ++ * cgiClearVariables() - Clear all form variables. + * cgiGetArray() - Get an element from a form array... + * cgiGetFile() - Get the file (if any) that was submitted in the form. + * cgiGetSize() - Get the size of a form array value. +@@ -135,6 +136,31 @@ cgiCheckVariables(const char *names) /* + + + /* ++ * 'cgiClearVariables()' - Clear all form variables. ++ */ ++ ++void ++cgiClearVariables(void) ++{ ++ int i, j; /* Looping vars */ ++ _cgi_var_t *v; /* Current variable */ ++ ++ ++ for (v = form_vars, i = form_count; i > 0; v ++, i --) ++ { ++ _cupsStrFree(v->name); ++ for (j = 0; j < v->nvalues; j ++) ++ if (v->values[j]) ++ _cupsStrFree(v->values[j]); ++ } ++ ++ form_count = 0; ++ ++ cgi_unlink_file(); ++} ++ ++ ++/* + * 'cgiGetArray()' - Get an element from a form array... + */ + +@@ -154,7 +180,7 @@ cgiGetArray(const char *name, /* I - Na + if (element < 0 || element >= var->nvalues) + return (NULL); + +- return (var->values[element]); ++ return (_cupsStrAlloc(var->values[element])); + } + + +@@ -209,7 +235,7 @@ cgiGetVariable(const char *name) /* I - + var->values[var->nvalues - 1]); + #endif /* DEBUG */ + +- return ((var == NULL) ? NULL : var->values[var->nvalues - 1]); ++ return ((var == NULL) ? NULL : _cupsStrAlloc(var->values[var->nvalues - 1])); + } + + +@@ -341,9 +367,9 @@ cgiSetArray(const char *name, /* I - Na + var->nvalues = element + 1; + } + else if (var->values[element]) +- free((char *)var->values[element]); ++ _cupsStrFree((char *)var->values[element]); + +- var->values[element] = strdup(value); ++ var->values[element] = _cupsStrAlloc(value); + } + } + +@@ -388,7 +414,7 @@ cgiSetSize(const char *name, /* I - Nam + { + for (i = size; i < var->nvalues; i ++) + if (var->values[i]) +- free((void *)(var->values[i])); ++ _cupsStrFree((void *)(var->values[i])); + } + + var->nvalues = size; +@@ -421,9 +447,9 @@ cgiSetVariable(const char *name, /* I - + { + for (i = 0; i < var->nvalues; i ++) + if (var->values[i]) +- free((char *)var->values[i]); ++ _cupsStrFree((char *)var->values[i]); + +- var->values[0] = strdup(value); ++ var->values[0] = _cupsStrAlloc(value); + var->nvalues = 1; + } + } +@@ -470,10 +496,10 @@ cgi_add_variable(const char *name, /* I + if ((var->values = calloc(element + 1, sizeof(char *))) == NULL) + return; + +- var->name = strdup(name); ++ var->name = _cupsStrAlloc(name); + var->nvalues = element + 1; + var->avalues = element + 1; +- var->values[element] = strdup(value); ++ var->values[element] = _cupsStrAlloc(value); + + form_count ++; + } diff --git a/cups-1.3.11-source.tar.bz2 b/cups-1.3.11-source.tar.bz2 new file mode 100644 index 0000000..0fd6664 --- /dev/null +++ b/cups-1.3.11-source.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:824b7fe5cefa981f2ce20f356983be182a551f716ccab8f5194fe645b1178303 +size 3799424 diff --git a/cups-1.3.3-mime.patch b/cups-1.3.3-mime.patch new file mode 100644 index 0000000..10d5869 --- /dev/null +++ b/cups-1.3.3-mime.patch @@ -0,0 +1,26 @@ +Index: cups-1.3.11/conf/mime.types +=================================================================== +--- cups-1.3.11.orig/conf/mime.types ++++ cups-1.3.11/conf/mime.types +@@ -75,6 +75,8 @@ application/postscript ai eps ps string + contains(0,4096,"LANGUAGE = POSTSCRIPT") \ + (contains(0,4096,<0a>%!) + \ + !contains(0,4096,"ENTER LANGUAGE"))) ++#application/x-dvi dvi string(0,) ++application/netscape-ps ps (string(0,%!) + contains(30,200,"Mozilla")) + application/vnd.hp-HPGL hpgl \ + string(0,<1B>E<1B>%0B) \ + string(0,<1B>%-1B) string(0,<201B>)\ +Index: cups-1.3.11/conf/mime.convs.in +=================================================================== +--- cups-1.3.11.orig/conf/mime.convs.in ++++ cups-1.3.11/conf/mime.convs.in +@@ -40,6 +40,8 @@ + + application/pdf application/vnd.cups-postscript 66 pdftops + application/postscript application/vnd.cups-postscript 66 pstops ++#application/x-dvi application/postscript 50 dvitops ++application/netscape-ps application/vnd.cups-postscript 33 ogonki + application/vnd.hp-HPGL application/postscript 66 hpgltops + application/x-cshell application/postscript 33 texttops + application/x-csource application/postscript 33 texttops diff --git a/cups-1.3.3-pswrite.patch b/cups-1.3.3-pswrite.patch new file mode 100644 index 0000000..53f8c0b --- /dev/null +++ b/cups-1.3.3-pswrite.patch @@ -0,0 +1,31 @@ +Index: cups-1.3.11/conf/mime.types +=================================================================== +--- cups-1.3.11.orig/conf/mime.types ++++ cups-1.3.11/conf/mime.types +@@ -76,7 +76,10 @@ application/postscript ai eps ps string + (contains(0,4096,<0a>%!) + \ + !contains(0,4096,"ENTER LANGUAGE"))) + #application/x-dvi dvi string(0,) +-application/netscape-ps ps (string(0,%!) + contains(30,200,"Mozilla")) ++application/mozilla-ps ps (string(0,%!) + \ ++ contains(30,200,"Creator: Mozilla PostScript")) ++application/netscape-ps ps (string(0,%!) + \ ++ contains(30,200,"Creator: Mozilla (NetScape)")) + application/vnd.hp-HPGL hpgl \ + string(0,<1B>E<1B>%0B) \ + string(0,<1B>%-1B) string(0,<201B>)\ +Index: cups-1.3.11/conf/mime.convs.in +=================================================================== +--- cups-1.3.11.orig/conf/mime.convs.in ++++ cups-1.3.11/conf/mime.convs.in +@@ -41,7 +41,9 @@ + application/pdf application/vnd.cups-postscript 66 pdftops + application/postscript application/vnd.cups-postscript 66 pstops + #application/x-dvi application/postscript 50 dvitops +-application/netscape-ps application/vnd.cups-postscript 33 ogonki ++application/netscape-ps application/postscript 33 ogonki ++#application/mozilla-ps application/postscript 33 pswrite ++application/mozilla-ps application/vnd.cups-postscript 66 pstops + application/vnd.hp-HPGL application/postscript 66 hpgltops + application/x-cshell application/postscript 33 texttops + application/x-csource application/postscript 33 texttops diff --git a/cups-1.3.3-testppd_none.patch b/cups-1.3.3-testppd_none.patch new file mode 100644 index 0000000..3c17223 --- /dev/null +++ b/cups-1.3.3-testppd_none.patch @@ -0,0 +1,13 @@ +--- cups-1.3.3/systemv/cupstestppd.c.orig 2007-10-15 18:50:01.000000000 +0200 ++++ cups-1.3.3/systemv/cupstestppd.c 2007-10-15 18:52:26.000000000 +0200 +@@ -983,8 +983,8 @@ + else + ydpi = xdpi; + +- if (xdpi <= 0 || xdpi > 99999 || ydpi <= 0 || ydpi > 99999 || +- strcmp(ptr, "dpi")) ++ if ((xdpi <= 0 || xdpi > 99999 || ydpi <= 0 || ydpi > 99999 || ++ strcmp(ptr, "dpi")) && (strcmp(ptr, "None"))) + { + if (verbose >= 0) + { diff --git a/cups-1.3.7-additional_policies.patch b/cups-1.3.7-additional_policies.patch new file mode 100644 index 0000000..c44d8e5 --- /dev/null +++ b/cups-1.3.7-additional_policies.patch @@ -0,0 +1,58 @@ +--- cups-1.3.7/conf/cupsd.conf.in.orig 2008-07-08 12:11:01.000000000 +0200 ++++ cups-1.3.7/conf/cupsd.conf.in 2008-07-08 13:11:57.000000000 +0200 +@@ -78,6 +78,55 @@ + + + ++DefaultPolicy default ++ ++# easy is a very relaxed policy ++ ++ # Job-related operations must be done by the owner or an administrator... ++ ++ Satisfy any ++ Order allow,deny ++ ++ ++ ++# paranoid is a very restricted policy ++ ++ # Job-related operations must be done by the owner ++ ++ Require user @OWNER ++ Allow from 127.0.0.0/8 ++ Order deny,allow ++ ++ # All administration operations require an administrator to authenticate... ++ ++ AuthType Default ++ Require user @SYSTEM ++ Allow from 127.0.0.0/8 ++ Order deny,allow ++ ++ ++ # All printer operations require a printer operator to authenticate... ++ ++ AuthType Default ++ Require user @CUPS_DEFAULT_PRINTADMIN_AUTH@ ++ Allow from 127.0.0.0/8 ++ Order deny,allow ++ ++ ++ # Only the owner or an administrator can cancel or authenticate a job... ++ ++ Require user @OWNER ++ Allow from 127.0.0.0/8 ++ Order deny,allow ++ ++ ++ ++ Require user @OWNER @CUPS_DEFAULT_PRINTADMIN_AUTH@ ++ Allow from 127.0.0.0/8 ++ Order deny,allow ++ ++ ++ + # + # End of "$Id: cupsd.conf.in 7199 2008-01-08 00:16:30Z mike $". + # diff --git a/cups-1.3.7-keeping_recommended.patch b/cups-1.3.7-keeping_recommended.patch new file mode 100644 index 0000000..e6bccb4 --- /dev/null +++ b/cups-1.3.7-keeping_recommended.patch @@ -0,0 +1,27 @@ +--- cups-1.3.7/scheduler/cups-driverd.c.orig 2008-04-01 00:33:33.000000000 +0200 ++++ cups-1.3.7/scheduler/cups-driverd.c 2008-05-07 12:19:40.000000000 +0200 +@@ -180,8 +180,6 @@ + int type) /* I - Driver type */ + { + ppd_info_t *ppd; /* PPD */ +- char *recommended; /* Foomatic driver string */ +- + + /* + * Add a new PPD file... +@@ -238,15 +236,6 @@ + strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id)); + + /* +- * Strip confusing (and often wrong) "recommended" suffix added by +- * Foomatic drivers... +- */ +- +- if ((recommended = strstr(ppd->record.make_and_model, +- " (recommended)")) != NULL) +- *recommended = '\0'; +- +- /* + * Return the new PPD pointer... + */ + diff --git a/cups-1.3.7-lppasswd_fixperm.patch b/cups-1.3.7-lppasswd_fixperm.patch new file mode 100644 index 0000000..3a739be --- /dev/null +++ b/cups-1.3.7-lppasswd_fixperm.patch @@ -0,0 +1,11 @@ +--- cups-1.3.7/scheduler/conf.c.orig 2008-07-01 15:32:53.000000000 +0200 ++++ cups-1.3.7/scheduler/conf.c 2008-07-01 15:51:22.000000000 +0200 +@@ -785,7 +785,7 @@ + Group, 1, 1) < 0 || + cupsdCheckPermissions(StateDir, "certs", RunUser ? 0711 : 0511, User, + SystemGroupIDs[0], 1, 1) < 0 || +- cupsdCheckPermissions(ServerRoot, NULL, 0755, RunUser, ++ cupsdCheckPermissions(ServerRoot, NULL, 0775, RunUser, + Group, 1, 0) < 0 || + cupsdCheckPermissions(ServerRoot, "ppd", 0755, RunUser, + Group, 1, 1) < 0 || diff --git a/cups-1.3.9-CVE-2009-3553.patch b/cups-1.3.9-CVE-2009-3553.patch new file mode 100644 index 0000000..9d6d552 --- /dev/null +++ b/cups-1.3.9-CVE-2009-3553.patch @@ -0,0 +1,38 @@ +--- scheduler/select.c.orig 2008-07-12 00:48:49.000000000 +0200 ++++ scheduler/select.c 2009-11-12 16:32:50.000000000 +0100 +@@ -483,7 +483,7 @@ cupsdDoSelect(long timeout) /* I - Time + (*(fdptr->read_cb))(fdptr->data); + } + +- if (fdptr->write_cb && event->filter == EVFILT_WRITE) ++ if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", + fdptr->fd); +@@ -543,7 +543,7 @@ cupsdDoSelect(long timeout) /* I - Time + (*(fdptr->read_cb))(fdptr->data); + } + +- if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) ++ if (fdptr->use > 1 && fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", + fdptr->fd); +@@ -655,7 +655,7 @@ cupsdDoSelect(long timeout) /* I - Time + (*(fdptr->read_cb))(fdptr->data); + } + +- if (fdptr->write_cb && (pfd->revents & (POLLOUT | POLLERR | POLLHUP))) ++ if (fdptr->use > 1 && fdptr->write_cb && (pfd->revents & (POLLOUT | POLLERR | POLLHUP))) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", + fdptr->fd); +@@ -725,7 +725,7 @@ cupsdDoSelect(long timeout) /* I - Time + (*(fdptr->read_cb))(fdptr->data); + } + +- if (fdptr->write_cb && FD_ISSET(fdptr->fd, &cupsd_current_output)) ++ if (fdptr->use > 1 && fdptr->write_cb && FD_ISSET(fdptr->fd, &cupsd_current_output)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDoSelect: Write on fd %d...", + fdptr->fd); diff --git a/cups-1.3.9-desktop_file.patch b/cups-1.3.9-desktop_file.patch index 6a85a77..a421936 100644 --- a/cups-1.3.9-desktop_file.patch +++ b/cups-1.3.9-desktop_file.patch @@ -1,9 +1,9 @@ ---- desktop/cups.desktop.in.orig 2009-10-02 19:15:07.000000000 +0200 -+++ desktop/cups.desktop.in 2010-01-27 15:14:58.000000000 +0100 +--- cups-1.3.9/desktop/cups.desktop.orig 2008-09-06 02:30:39.000000000 +0200 ++++ cups-1.3.9/desktop/cups.desktop 2008-10-13 10:50:03.000000000 +0200 @@ -1,6 +1,6 @@ [Desktop Entry] -Categories=System;Printing;HardwareSettings;X-Red-Hat-Base; --Exec=@CUPS_HTMLVIEW@ http://localhost:631/ +-Exec=htmlview http://localhost:631/ +Categories=System;Printing;HardwareSettings; +Exec=desktop-launch http://localhost:631/ Icon=cups diff --git a/cups-1.4-additional_policies.patch b/cups-1.4-additional_policies.patch deleted file mode 100644 index f82243c..0000000 --- a/cups-1.4-additional_policies.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- conf/cupsd.conf.in.orig 2010-01-27 11:49:09.000000000 +0100 -+++ conf/cupsd.conf.in 2010-01-27 11:55:34.000000000 +0100 -@@ -120,3 +120,23 @@ DefaultAuthType Basic - # - # End of "$Id: cupsd.conf.in 8805 2009-08-31 16:34:06Z mike $". - # -+ -+# The policy below is added by openSUSE/Novell during build of our cups package. -+# The policy 'allowallforanybody' is totally open and insecure and therefore -+# it can only be used within an internal network where only trused users exist -+# and where the cupsd is not accessible at all from any external host. -+# Have in mind that any user who is allowed to do printer admin tasks -+# can change the print queues as he likes (e.g. send copies of confidental -+# print jobs from an internal network to any external destination). -+# For documentation regarding 'Managing Operation Policies' see -+# http://www.cups.org/documentation.php/doc-1.4/policies.html -+ -+ -+ Order deny,allow -+ Allow from all -+ -+ -+# Explicitely set the CUPS 'default' policy to be used by default: -+DefaultPolicy default -+# End of additions by openSUSE/Novell. -+ diff --git a/cups-1.4-do_not_strip_recommended_from_PPDs.patch b/cups-1.4-do_not_strip_recommended_from_PPDs.patch deleted file mode 100644 index f368a93..0000000 --- a/cups-1.4-do_not_strip_recommended_from_PPDs.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- scheduler/cups-driverd.cxx.orig 2009-06-09 00:00:14.000000000 +0200 -+++ scheduler/cups-driverd.cxx 2009-07-01 14:38:44.000000000 +0200 -@@ -211,7 +211,6 @@ add_ppd(const char *filename, /* I - PP - const char *scheme) /* I - PPD scheme */ - { - ppd_info_t *ppd; /* PPD */ -- char *recommended; /* Foomatic driver string */ - - - /* -@@ -250,15 +249,6 @@ add_ppd(const char *filename, /* I - PP - strlcpy(ppd->record.scheme, scheme, sizeof(ppd->record.scheme)); - - /* -- * Strip confusing (and often wrong) "recommended" suffix added by -- * Foomatic drivers... -- */ -- -- if ((recommended = strstr(ppd->record.make_and_model, -- " (recommended)")) != NULL) -- *recommended = '\0'; -- -- /* - * Add the PPD to the PPD arrays... - */ - diff --git a/cups-1.4.2-source.tar.bz2 b/cups-1.4.2-source.tar.bz2 deleted file mode 100644 index 80ccfd1..0000000 --- a/cups-1.4.2-source.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:646bc0dbac064d05c0a93735fb556299eda0ae32ce4568506654cb952c719314 -size 4450466 diff --git a/cups-1.4svn-pdftops.c b/cups-1.4svn-pdftops.c new file mode 100644 index 0000000..a980e3e --- /dev/null +++ b/cups-1.4svn-pdftops.c @@ -0,0 +1,392 @@ +/* + * "$Id: pdftops.c 7449 2008-04-14 18:27:53Z mike $" + * + * PDF to PostScript filter front-end for the Common UNIX Printing + * System (CUPS). + * + * Copyright 2007-2008 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 +#include +#include +#include +#include +#include + + +/* + * 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 */ + ppd_file_t *ppd; /* PPD file */ + ppd_size_t *size; /* Current page size */ + int pdfpid, /* Process ID for pdftops */ + pdfwaitpid, /* Process ID from wait() */ + pdfstatus, /* Status from pdftops */ + pdfargc; /* Number of args for pdftops */ + char *pdfargv[100], /* Arguments for pdftops/gs */ +#ifdef HAVE_PDFTOPS + pdfwidth[255], /* Paper width */ + pdfheight[255]; /* Paper height */ +#else + pdfgeometry[255]; /* Paper width and height */ +#endif /* HAVE_PDFTOPS */ +#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) + { + _cupsLangPrintError(_("ERROR: Unable to copy PDF file")); + 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 command-line for the pdftops or gs filter... + */ + +#ifdef HAVE_PDFTOPS + pdfargv[0] = (char *)"pdftops"; + pdfargc = 1; +#else + pdfargv[0] = (char *)"gs"; + pdfargv[1] = (char *)"-q"; + pdfargv[2] = (char *)"-dNOPAUSE"; + pdfargv[3] = (char *)"-dBATCH"; + pdfargv[4] = (char *)"-dSAFER"; + pdfargv[5] = (char *)"-sDEVICE=pswrite"; + pdfargv[6] = (char *)"-sOUTPUTFILE=%stdout"; + pdfargc = 7; +#endif /* HAVE_PDFTOPS */ + + if (ppd) + { + /* + * Set language level and TrueType font handling... + */ + + if (ppd->language_level == 1) + { +#ifdef HAVE_PDFTOPS + pdfargv[pdfargc++] = (char *)"-level1"; + pdfargv[pdfargc++] = (char *)"-noembtt"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=1"; +#endif /* HAVE_PDFTOPS */ + } + else if (ppd->language_level == 2) + { +#ifdef HAVE_PDFTOPS + pdfargv[pdfargc++] = (char *)"-level2"; + if (!ppd->ttrasterizer) + pdfargv[pdfargc++] = (char *)"-noembtt"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=2"; +#endif /* HAVE_PDFTOPS */ + } + else +#ifdef HAVE_PDFTOPS + pdfargv[pdfargc++] = (char *)"-level3"; +#else + pdfargv[pdfargc++] = (char *)"-dLanguageLevel=3"; +#endif /* HAVE_PDFTOPS */ + + /* + * Set output page size... + */ + + size = ppdPageSize(ppd, NULL); + if (size) + { + /* + * 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(pdfwidth, sizeof(pdfwidth), "%.0f", size->length); + snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->width); + } + else + { + snprintf(pdfwidth, sizeof(pdfwidth), "%.0f", size->width); + snprintf(pdfheight, sizeof(pdfheight), "%.0f", size->length); + } + + pdfargv[pdfargc++] = (char *)"-paperw"; + pdfargv[pdfargc++] = pdfwidth; + pdfargv[pdfargc++] = (char *)"-paperh"; + pdfargv[pdfargc++] = pdfheight; +#else + if (orientation & 1) + snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->length, + size->width); + else + snprintf(pdfgeometry, sizeof(pdfgeometry), "-g%.0fx%.0f", size->width, + size->length); + + pdfargv[pdfargc++] = pdfgeometry; +#endif /* HAVE_PDFTOPS */ + } + } + +#ifdef HAVE_PDFTOPS + if ((val = cupsGetOption("fitplot", num_options, options)) != NULL && + strcasecmp(val, "no") && strcasecmp(val, "off") && + strcasecmp(val, "false")) + pdfargv[pdfargc++] = (char *)"-expand"; + + pdfargv[pdfargc++] = filename; + pdfargv[pdfargc++] = (char *)"-"; +#else + pdfargv[pdfargc++] = (char *)"-c"; + pdfargv[pdfargc++] = (char *)"save pop"; + pdfargv[pdfargc++] = (char *)"-f"; + pdfargv[pdfargc++] = filename; +#endif /* HAVE_PDFTOPS */ + + pdfargv[pdfargc] = NULL; + + if ((pdfpid = fork()) == 0) + { + /* + * Child comes here... + */ + +#ifdef HAVE_PDFTOPS + execv(HAVE_PDFTOPS, pdfargv); + _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); +#else + execv(CUPS_GHOSTSCRIPT, pdfargv); + _cupsLangPrintError(_("ERROR: Unable to execute gs program")); +#endif /* HAVE_PDFTOPS */ + + exit(1); + } + else if (pdfpid < 0) + { + /* + * Unable to fork! + */ + +#ifdef HAVE_PDFTOPS + _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); +#else + _cupsLangPrintError(_("ERROR: Unable to execute gs program")); +#endif /* HAVE_PDFTOPS */ + + pdfstatus = 1; + } + else + { + /* + * Parent comes here... + */ + + while ((pdfwaitpid = wait(&pdfstatus)) < 0 && errno == EINTR) + { + /* + * Wait until we get a valid process ID or the job is canceled... + */ + + if (job_canceled) + break; + } + + if (pdfwaitpid != pdfpid) + { + kill(pdfpid, SIGTERM); + pdfstatus = 1; + } + else if (pdfstatus) + { + if (WIFEXITED(pdfstatus)) + { + pdfstatus = WEXITSTATUS(pdfstatus); + + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter exited with status %d!\n"), + pdfstatus); + } + else + { + pdfstatus = WTERMSIG(pdfstatus); + + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter crashed on signal %d!\n"), + pdfstatus); + } + } + } + + /* + * Cleanup and exit... + */ + + if (tempfile[0]) + unlink(tempfile); + + return (pdfstatus); +} + + +/* + * '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 7449 2008-04-14 18:27:53Z mike $". + */ diff --git a/cups-pdf.ppd b/cups-pdf.ppd new file mode 100644 index 0000000..85bd73d --- /dev/null +++ b/cups-pdf.ppd @@ -0,0 +1,136 @@ +*PPD-Adobe: "4.3" +*% +*% "$Id: pdf.ppd,v 1.2 2003/01/02 15:47:37 gurubert Exp $" +*% +*% Printer description for a printer that uses the pstopdf filter +*% +*% This file is based on the laserjet.ppd that comes with CUPS. +*% +*FormatVersion: "4.3" +*FileVersion: "1.1" +*LanguageVersion: English +*LanguageEncoding: ISOLatin1 +*PCFileName: "PDF.PPD" +*Manufacturer: "SUSE" +*Product: "(openSUSE 11.0)" +*cupsVersion: 1.1 +*cupsManualCopies: False +*cupsFilter: "application/vnd.cups-postscript 33 pstopdf" +*ModelName: "PDF Converter" +*ShortNickName: "PDF Converter" +*NickName: "PDF Converter CUPS v1.1" +*PSVersion: "(3010.000) 550" +*LanguageLevel: "3" +*ColorDevice: True +*DefaultColorSpace: RGB +*FileSystem: False +*Throughput: "8" +*LandscapeOrientation: Plus90 +*VariablePaperSize: False +*TTRasterizer: Type42 + +*OpenUI *PageSize/Media Size: PickOne +*OrderDependency: 10 AnySetup *PageSize +*DefaultPageSize: A4 +*PageSize Letter/US Letter: "<>setpagedevice" +*PageSize Legal/US Legal: "<>setpagedevice" +*PageSize Executive/US Executive: "<>setpagedevice" +*PageSize Tabloid/US Tabloid: "<>setpagedevice" +*PageSize A3/A3: "<>setpagedevice" +*PageSize A4/A4: "<>setpagedevice" +*PageSize A5/A5: "<>setpagedevice" +*PageSize B5/B5 (JIS): "<>setpagedevice" +*PageSize EnvISOB5/Envelope B5: "<>setpagedevice" +*PageSize Env10/Envelope #10: "<>setpagedevice" +*PageSize EnvC5/Envelope C5: "<>setpagedevice" +*PageSize EnvDL/Envelope DL: "<>setpagedevice" +*PageSize EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageSize + +*OpenUI *PageRegion: PickOne +*OrderDependency: 10 AnySetup *PageRegion +*DefaultPageRegion: A4 +*PageRegion Letter/US Letter: "<>setpagedevice" +*PageRegion Legal/US Legal: "<>setpagedevice" +*PageRegion Executive/US Executive: "<>setpagedevice" +*PageRegion Tabloid/US Tabloid: "<>setpagedevice" +*PageRegion A3/A3: "<>setpagedevice" +*PageRegion A4/A4: "<>setpagedevice" +*PageRegion A5/A5: "<>setpagedevice" +*PageRegion B5/B5 (JIS): "<>setpagedevice" +*PageRegion EnvISOB5/Envelope B5: "<>setpagedevice" +*PageRegion Env10/Envelope #10: "<>setpagedevice" +*PageRegion EnvC5/Envelope C5: "<>setpagedevice" +*PageRegion EnvDL/Envelope DL: "<>setpagedevice" +*PageRegion EnvMonarch/Envelope Monarch: "<>setpagedevice" +*CloseUI: *PageRegion + +*DefaultImageableArea: A4 +*ImageableArea Letter/US Letter: "18 36 594 756" +*ImageableArea Legal/US Legal: "18 36 594 972" +*ImageableArea Executive/US Executive: "18 36 504 684" +*ImageableArea Tabloid/US Tabloid: "18 36 774 1188" +*ImageableArea A3/A3: "18 36 824 1155" +*ImageableArea A4/A4: "18 36 577 806" +*ImageableArea A5/A5: "18 36 403 559" +*ImageableArea B5/JIS B5: "18 36 498 693" +*ImageableArea EnvISOB5/B5 (ISO): "18 36 463 673" +*ImageableArea Env10/Com-10: "18 36 279 648" +*ImageableArea EnvC5/EnvC5: "18 36 441 613" +*ImageableArea EnvDL/EnvDL: "18 36 294 588" +*ImageableArea EnvMonarch/Envelope Monarch: "18 36 261 504" + +*DefaultPaperDimension: A4 +*PaperDimension Letter/US Letter: "612 792" +*PaperDimension Legal/US Legal: "612 1008" +*PaperDimension Executive/US Executive: "522 756" +*PaperDimension Tabloid/US Tabloid: "792 1224" +*PaperDimension A3/A3: "842 1191" +*PaperDimension A4/A4: "595 842" +*PaperDimension A5/A5: "421 595" +*PaperDimension B5/B5 (JIS): "516 729" +*PaperDimension EnvISOB5/Envelope B5: "499 709" +*PaperDimension Env10/Envelope #10: "297 684" +*PaperDimension EnvC5/Envelope C5: "459 649" +*PaperDimension EnvDL/Envelope DL: "312 624" +*PaperDimension EnvMonarch/Envelope Monarch: "279 540" + +*DefaultFont: Courier +*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM +*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM +*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM +*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM +*Font Bookman-Demi: Standard "(001.004S)" Standard ROM +*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM +*Font Bookman-Light: Standard "(001.004S)" Standard ROM +*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM +*Font Courier: Standard "(002.004S)" Standard ROM +*Font Courier-Bold: Standard "(002.004S)" Standard ROM +*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM +*Font Courier-Oblique: Standard "(002.004S)" Standard ROM +*Font Helvetica: Standard "(001.006S)" Standard ROM +*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM +*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM +*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM +*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM +*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM +*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM +*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM +*Font Palatino-Bold: Standard "(001.005S)" Standard ROM +*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM +*Font Palatino-Italic: Standard "(001.005S)" Standard ROM +*Font Palatino-Roman: Standard "(001.005S)" Standard ROM +*Font Symbol: Special "(001.007S)" Special ROM +*Font Times-Bold: Standard "(001.007S)" Standard ROM +*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM +*Font Times-Italic: Standard "(001.007S)" Standard ROM +*Font Times-Roman: Standard "(001.007S)" Standard ROM +*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM +*Font ZapfDingbats: Special "(001.004S)" Standard ROM +*% +*% End of "$Id: pdf.ppd,v 1.2 2003/01/02 15:47:37 gurubert Exp $". +*% diff --git a/cups-pstopdf b/cups-pstopdf new file mode 100644 index 0000000..11f6b24 --- /dev/null +++ b/cups-pstopdf @@ -0,0 +1,65 @@ +#!/bin/sh + +# $Id: pstopdf,v 1.2 2003/01/02 15:39:26 gurubert Exp $ +# +# This is a Postscript to PDF filter for CUPS +# +# (C) 2003 Robert Sander +# +# Released under GPL +# +# NO WARRANTY AT ALL +# + +echo "INFO: pstopdf argv[$#] = $@" >&2 + +if [ $# -lt 5 -o $# -gt 6 ]; then + + echo "ERROR: $0 job-id user title copies options [file]" >&2 + exit 1 + +fi + +jobid=$1 + +#infile=`mktemp /tmp/$jobid.pstopdf.in.XXXXXX` +#if [ $? -ne 0 ]; then +# echo "ERROR: Error creating tmpfile $infile" >&2 +# exit 1 +#fi +#outfile=`mktemp /tmp/$jobid.pstopdf.out.XXXXXX` +#if [ $? -ne 0 ]; then +# echo "ERROR: Error creating tmpfile $outfile" >&2 +# exit 1 +#fi + +if [ $# -eq 6 ]; then + + echo "INFO: file is $6" >&2 + #cp $6 $infile + #rm -f $6 + + infile="$6" + outfile="$infile".pdf + + /usr/bin/ps2pdf "$infile" "$outfile" 2>&1 >> /tmp/pstopdf.log + +else + + outfile=`mktemp /tmp/$jobid.pstopdf.out.XXXXXX` + if [ $? -ne 0 ]; then + echo "ERROR: Error creating tmpfile $outfile" >&2 + exit 1 + fi + + /usr/bin/ps2pdf - "$outfile" 2>&1 >> /tmp/pstopdf.log + +fi + +cat $outfile + +# cp "$infile" "$outfile" /tmp/cups/ + +rm -f "$outfile" + +exit 0 diff --git a/cups.SuSEfirewall2 b/cups.SuSEfirewall2 new file mode 100644 index 0000000..baa2d6d --- /dev/null +++ b/cups.SuSEfirewall2 @@ -0,0 +1,17 @@ +## Name: cups +## Description: Firewall Configuration file for printing service CUPS + +# space separated list of allowed TCP ports +TCP="ipp" + +# space separated list of allowed UDP ports +UDP="ipp" + +# space separated list of allowed RPC services +RPC="" + +# space separated list of allowed IP protocols +IP="" + +# space separated list of allowed UDP ports for UDP broadcasts +BROADCAST="ipp" diff --git a/cups.changes b/cups.changes index 1a1c58c..f983898 100644 --- a/cups.changes +++ b/cups.changes @@ -1,36 +1,3 @@ -------------------------------------------------------------------- -Wed Jan 27 14:43:37 CET 2010 - jsmeix@suse.de - -- CUPS 1.3 -> 1.4 version upgrade and major cleanup: - For the CUPS upstream changes see the CHANGES.txt file. - Such a major version upgrade is the perfect chance - to drop almost all our own patches to enforce a - reset to almost 100% compliance with upstream. - Here our openSUSE CUPS versions and their number of patches - (i.e. the "Patch" entries in the cups.spec files): - CUPS version 1.2.12 in openSUSE 10.3: 37 - CUPS version 1.3.7 in openSUSE 11.0: 29 - CUPS version 1.3.9 in openSUSE 11.1: 26 - CUPS version 1.3.11 in openSUSE 11.2: 17 - Of course this includes patches with backported bug fixes - via our maintenance but nevertheless there were really - too much openSUSE specific patches. - Therefore I would like to provide CUPS 1.4 "as is" to the - furthest possible extent (there are still 6 patches left). - Then let's see if we get bug reports because of this. - I did such a reset to 100% compliance with upstream - already in the past for sane-backends and guess what: - I got no single bug report at all because of this. - I guess what they do at upstream is actually not so bad ;-) -- Added the explicite path to '--with-cachedir=/var/cache/cups' - in cups.spec to avoid that the fallback value 'yes' results - the cache directory '/etc/cups/yes/'. -- cups-1.3.11-CVE-2009-2820-regression-fix.patch and - cups-1.3.11-CVE-2009-2820.patch have become - obsolete because it is fixed in the source. -- cups-1.4-full_path_to_configure_with-pdftops.patch has become - obsolete because it is fixed in the source. - ------------------------------------------------------------------- Tue Dec 15 22:22:18 CET 2009 - jengelh@medozas.de diff --git a/cups.spec b/cups.spec index 413bf14..fde6d0a 100644 --- a/cups.spec +++ b/cups.spec @@ -1,7 +1,7 @@ # -# spec file for package cups (Version 1.3.9) +# spec file for package cups (Version 1.3.11) # -# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -26,22 +26,12 @@ BuildRequires: fdupes update-desktop-files PreReq: textutils, fileutils, sh-utils, %insserv_prereq, PreReq: %fillup_prereq /usr/sbin/groupadd Url: http://www.cups.org/ -License: GPL v2 or later +License: GPLv2+ Group: Hardware/Printing Summary: The Common UNIX Printing System -Version: 1.4.2 -Release: 13 -# Require the exact matching version-release of the cups-libs sub-package because -# non-matching CUPS libraries may let CUPS software crash (e.g. segfault) -# because all CUPS software is built from the one same CUPS source tar ball -# so that there are CUPS-internal dependencies via CUPS private API calls -# (which do not happen for third-party software which uses only the CUPS public API). -# The exact matching version-release of the cups-libs sub-package is available -# on the same package repository where the cups package is because -# all are built simulaneously from the same cups source package -# and all required packages are provided on the same repository: -Requires: cups-libs = %{version}-%{release} -Requires: cups-client = %{version} +Version: 1.3.11 +Release: 7 +Requires: cups-libs = %{version}, cups-client = %{version} Requires: ghostscript_any, ghostscript-fonts-std, foomatic-filters Requires: util-linux /usr/bin/pdftops %if 0%{?suse_version} >= 1100 @@ -50,167 +40,240 @@ Requires: pdftools_any Suggests: poppler-tools Conflicts: plp lprold lprng Obsoletes: cups-SUSE-ppds-dat -# Source0...Source9 is for sources from upstream: -# URL for Source0: http://ftp.easysw.com/pub/cups/1.4.2/cups-1.4.2-source.tar.bz2 -# MD5 sum for Source0 on http://www.cups.org/software.php is d95e2d588e3d36e563027a963b117b1b +# URL for Source0: http://ftp.easysw.com/pub/cups/1.3.11/cups-1.3.11-source.tar.bz2 +# MD5 sum for Source0 on http://www.cups.org/software.php is 17f3e2bcb3cae3dd9dceb65a2bfd295f Source0: cups-%{version}-source.tar.bz2 -# Patch0...Patch9 is for patches from upstream: -# Source10...Source99 is for sources from Novell/openSUSE which are intended for upstream: -# Patch10...Patch99 is for patches from Novell/openSUSE which are intended for upstream: -# Patch10 adds 'smb://...' URIs to templates/choose-uri.tmpl: -Patch10: cups-1.2rc1-template.patch -# Source100...Source999 is for private sources from Novell/openSUSE which are not intended for upstream: -Source100: cups-krb5-config -Source101: cups.init -Source102: postscript.ppd.bz2 -Source103: cups.sysconfig -Source104: cups.xinetd -Source105: PSLEVEL1.PPD.bz2 -Source106: PSLEVEL2.PPD.bz2 -Source108: cups-client.conf -Source109: baselibs.conf -# Patch100...Patch999 is for private patches from Novell/openSUSE which are not intended for upstream: -# Patch100 adds conf/pam.suse regarding support for PAM for Novell/openSUSE: -Patch100: cups-pam.diff -# Patch101 adds 'Allow 127.0.0.2' to cupsd.conf -# to allow access for the loopback IP address 127.0.0.2 -# which is set for the hostname by Novell/openSUSE in /etc/hosts -Patch101: cups-1.3.6-access_conf.patch -# Patch102 changes desktop/cups.desktop according to what Novell/openSUSE needs: -Patch102: cups-1.3.9-desktop_file.patch -# Patch103 reverts the change which was added by Michael Sweet in Jan 2007 -# which strips the word "recommended" from NickName in PPDs because -# at least yast2-printer in Novell/openSUSE needs it, compare the -# 'Why not "recommend" PPDs in the NickName?' and the subsequent -# 'RFC: New Driver Rating/Information Attributes' mail thread on cups@easysw.com: -Patch103: cups-1.4-do_not_strip_recommended_from_PPDs.patch -# Patch104 adds the 'allowallforanybody' policy to cupsd.conf -# see https://fate.novell.com/303515 -Patch104: cups-1.4-additional_policies.patch -# Install into this non-root directory (required when norootforbuild is used): +Source1: poll_ppd_base.c +Source2: lphelp.c +Source3: dvitops +Source4: pswrite +Source5: baselibs.conf +Source7: ogonki +Source8: cups.init +Source9: http://amaru.ti6.tu-harburg.de/portal/Members/ti6ntm/Projekte/Printanalyzer/PrintAnalyzer +Source10: http://homepages.nyu.edu/~ml1100/files/quosnmp +Source11: setcupsbroadcasting +Source12: postscript.ppd.bz2 +Source13: cups.sysconfig +Source14: cups.xinetd +Source15: PSLEVEL1.PPD.bz2 +Source16: PSLEVEL2.PPD.bz2 +Source17: cups.SuSEfirewall2 +Source18: http://download.sourceforge.net/cups-mailto/cups-pdf.ppd +Source19: http://download.sourceforge.net/cups-mailto/cups-pstopdf +Source20: cups-krb5-config +Source21: cups-client.conf +Source22: cups-1.4svn-pdftops.c +Patch1: cups-1.3.3-mime.patch +Patch2: cups-1.2.0-ppdsdat_generation.patch +Patch3: cups-1.2rc1-template.patch +Patch4: cups-1.2.7-libwrap.patch +Patch5: cups-pam.diff +Patch6: cups-1.3.6-access_conf.patch +# Patch9 cups-1.1.21rc2-preauth_security.patch is finally removed +# since CUPS 1.3.10 because it was made for CUPS 1.1 and +# it was no longer applied since CUPS 1.2 in Suse Linux 10.3 and +# we did not get any user or SLE11 customer request for it. +# Patch10 cups-1.1.21rc2-usermode.patch is finally removed +# since CUPS 1.3.10 because it was made for CUPS 1.1 and +# can no longer apply since CUPS 1.2 in Suse Linux 10.3 because +# RunAsUser in cupsd.conf is no longer supported since CUPS 1.2. +Patch12: cups-1.3.3-pswrite.patch +# Patch13 cups-1.1.21-umlaut_printer.patch is finally removed +# since CUPS 1.3.10 because it was made for CUPS 1.1 and +# it was no longer applied since CUPS 1.2 in Suse Linux 10.3 and +# we did not get any user or SLE11 customer request for it. +Patch14: cups-1.1.21-testppd_duplex.patch +Patch15: cups-1.2.11-testppd_filename.patch +Patch16: cups-1.3.9-desktop_file.patch +Patch17: cups-1.3.3-testppd_none.patch +# Patch18 cups-1.4svn-pdftops_as_filter.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch19 cups-1.4svn-pdftops_dont_fail_on_cancel.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +Patch20: cups-1.3.7-keeping_recommended.patch +Patch21: cups-1.3.7-lppasswd_fixperm.patch +Patch22: cups-1.3.7-additional_policies.patch +# Patch23 cups-1.3.9-cupstestppd.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch24 cups-1.3.9-max_subscription.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch25 cups-1.3.9-filter_png_overflow2.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch26 cups-1.3.9-hpgltops2.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch27 cups-1.3.9-cupsImageReadTiff.patch is obsolete +# since CUPS 1.3.10 because it is fixed in the source. +# Patch28 cups-1.3.10-fix-DNS-rebinding-protection.patch is obsolete +# since CUPS 1.3.11 because it is fixed in the source. +# Patch29 full_path_to_configure_with-pdftops.patch adds support +# to specify a full path in 'configure --with-pdftops=/usr/bin/pdftops' +# to avoid 'BuildRequires: xpdf-tools' which would bloat the build system +# but would be only needed to satisfy 'AC_PATH_PROG(CUPS_PDFTOPS, pdftops)' +# in cups-pdf.m4 if only 'configure --with-pdftops=pdftops' was possible: +Patch29: full_path_to_configure_with-pdftops.patch +# Patch30 fixes CUPS Web Interface Cross-Site Scripting (XSS) and CRLF injection in HTTP headers, +# (CVE-2009-2820 and Novell/Suse Bugzilla bnc#548317): +Patch30: cups-1.3.11-CVE-2009-2820.patch +# Patch31 fixes a regression which was introduced by Patch30 +# now adding a class via web interface fails with 'Unknown operation "{op}"' +# (Novell/Suse Bugzilla bnc#548317 starting at comment #24): +Patch31: cups-1.3.11-CVE-2009-2820-regression-fix.patch +# Patch32 fixes a use-after-free bug in the scheduler which leads to remote denial of service, +# (CVE-2009-3553, CUPS STR #3200, and Novell/Suse Bugzilla bnc#554861): +Patch32: cups-1.3.9-CVE-2009-3553.patch +# Patch100 cups-1.1.23-testpage.patch is finally removed +# since CUPS 1.3.10 because it was made for CUPS 1.1 and +# it was no longer applied since CUPS 1.2 in Suse Linux 10.3 and +# we did not get any user or SLE11 customer request for it. BuildRoot: %{_tmppath}/%{name}-%{version}-build - %description The Common UNIX Printing System provides a portable printing layer for -UNIX operating systems like BSD lp or lprng. CUPS provides some +UNIX® operating systems like BSD lp or lprng. CUPS provides some additional features. http://www.cups.org + + +Authors: +-------- + Easy Software Products + +%define INSTALL install -m755 +%define INSTALL_SCRIPT install -m755 +%define INSTALL_DIR install -d -m755 +%define INSTALL_DATA install -m644 +%define CPUs %(grep -c ^processor\ /proc/cpuinfo || echo 1) + %package libs -License: GPL v2 or later; LGPL v2.1 or later +License: GPLv2+ ; LGPLv2.1+ Summary: Libraries for CUPS Group: Hardware/Printing -# https://bugzilla.novell.com/show_bug.cgi?id=437293 +# bug437293 %ifarch ppc64 Obsoletes: cups-libs-64bit %endif +# %description libs The Common UNIX Printing System provides a portable printing layer for -UNIX operating systems like BSD lp or lprng. CUPS provides some +UNIX® operating systems like BSD lp or lprng. CUPS provides some additional features. This package contains libraries needed by CUPS and some other packages. + + +Authors: +-------- + Easy Software Products + %package client -License: GPL v2 or later +License: GPLv2+ Summary: CUPS Client Programs Group: Hardware/Printing Conflicts: plp lprold lprng -# Require the exact matching version-release of the cups-libs sub-package because -# non-matching CUPS libraries may let CUPS software crash (e.g. segfault) -# because all CUPS software is built from the one same CUPS source tar ball -# so that there are CUPS-internal dependencies via CUPS private API calls -# (which do not happen for third-party software which uses only the CUPS public API). -# The exact matching version-release of the cups-libs sub-package is available -# on the same package repository where the cups package is because -# all are built simulaneously from the same cups source package -# and all required packages are provided on the same repository: -Requires: cups-libs = %{version}-%{release} +Requires: cups-libs = %{version} %description client The Common UNIX Printing System provides a portable printing layer for -UNIX operating systems like BSD lp or lprng. CUPS provides some +UNIX® operating systems like BSD lp or lprng. CUPS provides some additional features. This package contains all programs needed for running a CUPS client, not a server. + + +Authors: +-------- + Easy Software Products + %package devel -License: GPL v2 or later +License: GPLv2+ Summary: Development Environment for CUPS Group: Development/Libraries/C and C++ -# Do not require the exact matching version-release of cups-libs -# but only a cups-libs package with matching version because -# for building third-party software which uses only the CUPS public API -# there are no CUPS-internal dependencies via CUPS private API calls -# (the latter would require the exact matching cups-libs version-release): -Requires: cups-libs = %{version} -Requires: openssl-devel glibc-devel krb5-devel -# https://bugzilla.novell.com/show_bug.cgi?id=437293 +Requires: %{name}-libs = %{version} openssl-devel glibc-devel krb5-devel +# bug437293 %ifarch ppc64 Obsoletes: cups-devel-64bit %endif +# %description devel The Common UNIX Printing System provides a portable printing layer for -UNIX operating systems like BSD lp or lprng. CUPS provides some +UNIX® operating systems like BSD lp or lprng. CUPS provides some additional features. This is the development package. http://www.cups.org -%package ddk -License: GPL v2 or later -Summary: CUPS Driver Development Kit -Group: Hardware/Printing -Requires: cups = %{version} -Requires: cups-devel = %{version} -# Since CUPS 1.4 the CUPS Driver Development Kit (DDK) is bundled with CUPS. -# For CUPS 1.2.x and 1.3.x, the DDK was separated software -# which we provided (up to openSUSE 11.1 / SLE11) in our cupsddk package: -Provides: cupsddk = %{version} -Obsoletes: cupsddk < %{version} -%description ddk -The CUPS Driver Development Kit (DDK) provides a suite of standard -drivers, a PPD file compiler, and other utilities that can be used to -develop printer drivers for CUPS and other printing environments. CUPS -provides a portable printing layer for UNIX(r)-based operating systems. -The CUPS DDK provides the means for mass-producing PPD files and -drivers or filters for CUPS-based printer drivers. -The Common UNIX Printing System provides a portable printing layer for -UNIX operating systems like BSD lp or lprng. CUPS provides some -additional features. This is the Driver Development Kit package. -http://www.cups.org +Authors: +-------- + Easy Software Products %prep # Be quiet when unpacking: %setup -q -n %{name}-%{version} -# Patch0...Patch9 is for patches from upstream: -# Patch10...Patch99 is for patches from Novell/openSUSE which are intended for upstream: -# Patch10 adds 'smb://...' URIs to templates/choose-uri.tmpl: -%patch10 -p1 -# Patch100...Patch999 is for private patches from Novell/openSUSE which are not intended for upstream: -# Patch100 adds conf/pam.suse regarding support for PAM for Novell/openSUSE: -%patch100 -# Patch101 adds 'Allow 127.0.0.2' to cupsd.conf: -%patch101 -p1 -# Patch102 changes desktop/cups.desktop according to what Novell/openSUSE needs: -%patch102 -# Patch103 reverts the change which strips the word "recommended" from NickName in PPDs: -%patch103 -# Patch104 adds the 'allowallforanybody' policy to cupsd.conf: -%patch104 -# Install our special krb5-config (Source100: cups-krb5-config): -install -m755 %{SOURCE100} krb5-config +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 +%patch6 -p1 +%patch12 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +# Patch29 full_path_to_configure_with-pdftops.patch adds support +# for 'configure --with-pdftops=/usr/bin/pdftops': +%patch29 +# Patch30 fixes CUPS Web Interface Cross-Site Scripting (XSS) and CRLF injection in HTTP headers, +# (CVE-2009-2820 and Novell/Suse Bugzilla bnc#548317): +%patch30 -p1 +# Patch31 fixes a regression which was introduced by Patch30 +# now adding a class via web interface fails with 'Unknown operation "{op}"' +# (Novell/Suse Bugzilla bnc#548317 starting at comment #24): +%patch31 +# Patch32 fixes a use-after-free bug in the scheduler which leads to remote denial of service, +# (CVE-2009-3553, CUPS STR #3200, and Novell/Suse Bugzilla bnc#554861): +%patch32 +if [ -f /.buildenv ]; then + . /.buildenv + test -z "$BUILD_DISTRIBUTION_NAME" && BUILD_DISTRIBUTION_NAME="%{?distribution}" +fi +test -z "$BUILD_DISTRIBUTION_NAME" && BUILD_DISTRIBUTION_NAME="personal build CUPS version" +perl -pi -e "s|SUSEVERSION|$BUILD_DISTRIBUTION_NAME|; \ + s/CUPSVERSION/%{version}/" %{PATCH100} +# fix hardcoded $_libdir path to real architecture dependend $_libdir +perl -pi -e 's|(CUPS_SERVERBIN=\")\$exec_prefix/lib|$1'%{_libdir}'|' \ + config-scripts/cups-directories.m4 +cp -a %{SOURCE9} . +cp -a %{SOURCE10} . +%{INSTALL_SCRIPT} %{SOURCE20} krb5-config %build +# To build the /usr/lib/cups/filter/pdftops filter +# (via the configure options --enable-pdftops, --with-pdftops=pdftops) +# the config-scripts/cups-pdf.m4 tests if there is a pdftops executable in its path +# which could be satisfied with 'BuildRequires: xpdf-tools' which would bloat the build system +# so that we fake a pdftops executable with the following link: +ln -s /bin/true pdftops %{?suse_update_config:%{suse_update_config -f . }} libtoolize --force aclocal autoconf +%if %suse_version >= 1010 export CXXFLAGS="$CXXFLAGS $RPM_OPT_FLAGS -O2 -fno-strict-aliasing -fstack-protector" export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing -fstack-protector -DLDAP_DEPRECATED" +%else +export CXXFLAGS="$CXXFLAGS $RPM_OPT_FLAGS -O2 -fno-strict-aliasing" +export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" +%endif export CXX=g++ KRB5CONFIG=${PWD}/krb5-config ./configure \ --mandir=%{_mandir} \ @@ -230,73 +293,98 @@ KRB5CONFIG=${PWD}/krb5-config ./configure \ --with-java \ --with-php \ --with-python \ - --with-cachedir=/var/cache/cups \ + --with-python \ + --with-cachedir \ --with-pdftops=/usr/bin/pdftops \ --prefix=/ -make %{?_smp_mflags} CXX=g++ +# perl -pi -e 's:^(OPTIONS\s+\=):$1 -I/usr/X11R6/include -O2 -fstack-protector -fno-strict-aliasing:' Makedefs +# perl -pi -e 's:^(INSTALL_BIN\s+\=.*)-s:$1:' Makedefs +# for debugging enable: +#perl -pi -e 's:^(OPTIONS\s+\=):$1 -I/usr/X11R6/include -O2 -fno-strict-aliasing -g -DDEBUG:' Makedefs +#perl -pi -e 's:^(OPTIM\s+\=):$1 -g -DDEBUG:' Makedefs +make %{?jobs:-j%jobs} CXX=g++ +# Compile additional tools +gcc -opoll_ppd_base $CFLAGS -fPIC -fPIE -pie -I. -L./cups %{SOURCE1} -lcups +gcc -olphelp $CFLAGS -fPIC -fPIE -pie -I. -L./cups %{SOURCE2} -lcups %install -make BUILDROOT=$RPM_BUILD_ROOT install -install -d -m755 $RPM_BUILD_ROOT/etc/init.d -# Source101: cups.init -install -m755 %{SOURCE101} $RPM_BUILD_ROOT/etc/init.d/cups -install -d -m755 $RPM_BUILD_ROOT/var/adm/fillup-templates -# Source103: cups.sysconfig -install -m 644 %{SOURCE103} $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cups +make BUILDROOT=$RPM_BUILD_ROOT \ + install +if [ x%{version} = x"1.1.18" ]; then + mv $RPM_BUILD_ROOT/usr/sbin/cupstestppd \ + $RPM_BUILD_ROOT/usr/bin/cupstestppd +fi +# place CUPS-O-MATIC script in CUPS filter directory +%{INSTALL_SCRIPT} %{SOURCE7} $RPM_BUILD_ROOT%{_libdir}/cups/filter +%{INSTALL_SCRIPT} %{SOURCE3} $RPM_BUILD_ROOT%{_libdir}/cups/filter +%{INSTALL_SCRIPT} %{SOURCE4} $RPM_BUILD_ROOT%{_libdir}/cups/filter +# might no longer be needed: ln -s /etc/cups/printcap $RPM_BUILD_ROOT/etc +# install the two little tools +install -m 755 poll_ppd_base $RPM_BUILD_ROOT/usr/bin/ +install -m 755 lphelp $RPM_BUILD_ROOT/usr/bin/ +%{INSTALL_DIR} $RPM_BUILD_ROOT/etc/init.d +%{INSTALL_SCRIPT} %{SOURCE8} $RPM_BUILD_ROOT/etc/init.d/cups +%{INSTALL_DIR} $RPM_BUILD_ROOT/var/adm/fillup-templates +install -m 644 %{SOURCE13} $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cups perl -pi -e "s:\@LIB\@:%{_libdir}:g" $RPM_BUILD_ROOT/etc/init.d/cups ln -sf ../../etc/init.d/cups $RPM_BUILD_ROOT/usr/sbin/rccups -# use Ghostscript fonts instead of CUPS fonts: +# rm -r $RPM_BUILD_ROOT/usr/share/cups/fonts +#mkdir -p /usr/share/ghostscript/fonts mkdir -p $RPM_BUILD_ROOT/usr/share/ghostscript/fonts ln -sf /usr/share/ghostscript/fonts $RPM_BUILD_ROOT/usr/share/cups/ # make directory for ssl files: mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/cups/ssl -# add old client.conf as reference (Source108: cups-client.conf): -install -m644 %{SOURCE108} $RPM_BUILD_ROOT%{_sysconfdir}/cups/client.conf +# add old client.conf as reference: +%{INSTALL_DATA} %{SOURCE21} $RPM_BUILD_ROOT%{_sysconfdir}/cups/client.conf mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d install -m 644 -D packaging/cups-dbus.conf $RPM_BUILD_ROOT%{_sysconfdir}/dbus-1/system.d/cups.conf -# Source104: cups.xinetd -install -m 644 -D %{SOURCE104} $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/cups-lpd +install -m 644 -D %{SOURCE14} $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/cups-lpd perl -pi -e "s:\@LIB\@:%{_libdir}:g" $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/cups-lpd ln -sf libcupsimage.so.2 $RPM_BUILD_ROOT%{_libdir}/libcupsimage.so ln -sf libcups.so.2 $RPM_BUILD_ROOT%{_libdir}/libcups.so -install -d -m755 $RPM_BUILD_ROOT/usr/share/cups/drivers -install -d -m755 $RPM_BUILD_ROOT/var/cache/cups -install -d -m755 $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name} -install -d -m755 $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name}/images +ln -sf ../sbin/lpc $RPM_BUILD_ROOT/usr/bin/lpc # bugzilla#16652 +%{INSTALL_DIR} $RPM_BUILD_ROOT/usr/share/cups/drivers +%{INSTALL_DIR} $RPM_BUILD_ROOT/var/cache/cups +%{INSTALL_DIR} $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name} +%{INSTALL_DIR} $RPM_BUILD_ROOT/%{_defaultdocdir}/%{name}/images install -m 644 -D conf/pam.suse $RPM_BUILD_ROOT/etc/pam.d/cups +install -m 755 PrintAnalyzer $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}/ +install -m 755 quosnmp $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}/ for f in CHANGES*.txt CREDITS.txt INSTALL.txt LICENSE.txt README.txt; do install -m 644 "$f" $RPM_BUILD_ROOT%{_defaultdocdir}/%{name}/ done -# Source102: postscript.ppd.bz2 -bzip2 -cd < %{SOURCE102} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript.ppd -# Source105: PSLEVEL1.PPD.bz2 -bzip2 -cd < %{SOURCE105} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript-level1.ppd -# Source106: PSLEVEL2.PPD.bz2 -bzip2 -cd < %{SOURCE106} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript-level2.ppd +bzip2 -cd < %{SOURCE12} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript.ppd +bzip2 -cd < %{SOURCE15} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript-level1.ppd +bzip2 -cd < %{SOURCE16} > $RPM_BUILD_ROOT%{_datadir}/cups/model/Postscript-level2.ppd +%{INSTALL_DATA} %{SOURCE18} $RPM_BUILD_ROOT%{_datadir}/cups/model/PDF.ppd find %{buildroot}/usr/share/cups/model -name "*.ppd" | while read FILE -do # change default paper size from Letter to A4 if possible - # https://bugzilla.novell.com/show_bug.cgi?id=suse30662 - # and delete trailing whitespace: - perl -pi -e 's:^(\*Default.*)Letter\s*$:$1A4\n:; \ - s:^(\*ImageableArea A4.*\:\s+)"0 0 595 842":$1"24 48 571 818":; \ - s:^(\*ImageableArea Letter.*\:\s+)"0 0 612 792":$1"24 48 588 768":; \ - s:\s\n:\n:' "$FILE" - gzip -9 "$FILE" +do + # change default paper size from letter to A4 if possible (bugzilla#30662) + # and delete trailing whitespace + perl -pi -e 's:^(\*Default.*)Letter\s*$:$1A4\n:; \ + s:^(\*ImageableArea A4.*\:\s+)"0 0 595 842":$1"24 48 571 818":; \ + s:^(\*ImageableArea Letter.*\:\s+)"0 0 612 792":$1"24 48 588 768":; \ + s:\s\n:\n:' \ + "$FILE" + gzip -9 "$FILE" done -# add files for menu: -rm -f $RPM_BUILD_ROOT/usr/share/applications/cups.desktop +# add files for menu +rm -f $RPM_BUILD_ROOT//usr/share/applications/cups.desktop %suse_update_desktop_file -i -r %name PrintingUtility 2>/dev/null mkdir $RPM_BUILD_ROOT/usr/share/pixmaps install -m 644 $RPM_BUILD_ROOT/usr/share/icons/hicolor/64x64/apps/cups.png $RPM_BUILD_ROOT/usr/share/pixmaps rm -rf $RPM_BUILD_ROOT/usr/share/icons -# remove unpackaged files: +# remove unpackaged files rm -rf $RPM_BUILD_ROOT/%{_mandir}/es/cat? rm -rf $RPM_BUILD_ROOT/%{_mandir}/fr/cat? rm -rf $RPM_BUILD_ROOT/%{_mandir}/cat? -# remove unknown locale directory: +# +# SuSEfirewall2: +install -d $RPM_BUILD_ROOT/etc/sysconfig/SuSEfirewall2.d/services/ +install -m 644 %{SOURCE17} $RPM_BUILD_ROOT/etc/sysconfig/SuSEfirewall2.d/services/cups +# remove unknown locale directory rm -rf $RPM_BUILD_ROOT/usr/share/locale/no -# run fdupes: %fdupes $RPM_BUILD_ROOT %clean @@ -321,181 +409,93 @@ rm -rf $RPM_BUILD_ROOT/usr/share/locale/no %files %defattr(-,root,root) -%config(noreplace) %attr(640,root,lp) %{_sysconfdir}/cups/cupsd.conf -%config(noreplace) %attr(640,root,lp) %{_sysconfdir}/cups/snmp.conf -%config(noreplace) %attr(755,lp,lp) %{_sysconfdir}/cups/interfaces -%config(noreplace) %{_sysconfdir}/xinetd.d/cups-lpd -%config %attr(0755,root,root) %{_sysconfdir}/init.d/cups -%config %{_sysconfdir}/pam.d/cups %dir %attr(700,root,lp) %{_sysconfdir}/cups/ssl %dir %attr(755,root,lp) %{_sysconfdir}/cups/ppd +%config(noreplace) %attr(640,root,lp) %{_sysconfdir}/cups/cupsd.conf +%config(noreplace) %attr(640,root,lp) %{_sysconfdir}/cups/snmp.conf %{_sysconfdir}/cups/cupsd.conf.default %{_sysconfdir}/dbus-1/system.d/cups.conf -/var/adm/fillup-templates/sysconfig.cups +%config(noreplace) %attr(755,lp,lp) %{_sysconfdir}/cups/interfaces +%config(noreplace) %{_sysconfdir}/cups/mime.* +%config(noreplace) %{_sysconfdir}/xinetd.d/cups-lpd +%{_bindir}/poll_ppd_base %{_bindir}/cupstestppd +%{_bindir}/cupstestdsc +%dir %{_libdir}/cups +%dir %{_libdir}/cups/backend +%{_libdir}/cups/backend/http +%{_libdir}/cups/backend/ipp +%{_libdir}/cups/backend/lpd +%{_libdir}/cups/backend/parallel +%{_libdir}/cups/backend/scsi +%{_libdir}/cups/backend/snmp +%{_libdir}/cups/backend/serial +%{_libdir}/cups/backend/socket +%{_libdir}/cups/backend/usb +%{_libdir}/cups/cgi-bin +%{_libdir}/cups/daemon +%dir %{_libdir}/cups/driver +%dir %{_libdir}/cups/filter +%{_libdir}/cups/filter/[abd-z]* +%dir %{_libdir}/cups/monitor +%{_libdir}/cups/monitor/* +%dir %{_libdir}/cups/notifier +%{_libdir}/cups/notifier/* %{_sbindir}/cupsaddsmb %{_sbindir}/cupsctl %{_sbindir}/cupsd %{_sbindir}/cupsfilter -%{_sbindir}/rccups -%dir /usr/lib/cups -%dir /usr/lib/cups/backend -/usr/lib/cups/backend/http -/usr/lib/cups/backend/ipp -/usr/lib/cups/backend/lpd -/usr/lib/cups/backend/parallel -/usr/lib/cups/backend/scsi -/usr/lib/cups/backend/serial -/usr/lib/cups/backend/snmp -/usr/lib/cups/backend/socket -/usr/lib/cups/backend/usb -%dir /usr/lib/cups/cgi-bin -/usr/lib/cups/cgi-bin/admin.cgi -/usr/lib/cups/cgi-bin/classes.cgi -/usr/lib/cups/cgi-bin/help.cgi -/usr/lib/cups/cgi-bin/jobs.cgi -/usr/lib/cups/cgi-bin/printers.cgi -%dir /usr/lib/cups/daemon -/usr/lib/cups/daemon/cups-deviced -/usr/lib/cups/daemon/cups-driverd -/usr/lib/cups/daemon/cups-lpd -/usr/lib/cups/daemon/cups-polld -%dir /usr/lib/cups/driver -%dir /usr/lib/cups/filter -/usr/lib/cups/filter/bannertops -/usr/lib/cups/filter/commandtoescpx -/usr/lib/cups/filter/commandtopclx -/usr/lib/cups/filter/commandtops -/usr/lib/cups/filter/gziptoany -/usr/lib/cups/filter/hpgltops -/usr/lib/cups/filter/imagetops -/usr/lib/cups/filter/imagetoraster -/usr/lib/cups/filter/pdftops -/usr/lib/cups/filter/pstops -/usr/lib/cups/filter/rastertodymo -/usr/lib/cups/filter/rastertoepson -/usr/lib/cups/filter/rastertoescpx -/usr/lib/cups/filter/rastertohp -/usr/lib/cups/filter/rastertolabel -/usr/lib/cups/filter/rastertopclx -/usr/lib/cups/filter/texttops -%dir /usr/lib/cups/monitor -/usr/lib/cups/monitor/bcp -/usr/lib/cups/monitor/tbcp -%dir /usr/lib/cups/notifier -/usr/lib/cups/notifier/mailto -/usr/lib/cups/notifier/rss -%dir %attr(0775,root,ntadmin) %{_datadir}/cups/drivers -%{_datadir}/applications/cups.desktop -%{_datadir}/pixmaps/cups.png -%doc %{_defaultdocdir}/cups -%doc %{_mandir}/man1/cupstestppd.1.gz -%doc %{_mandir}/man5/classes.conf.5.gz -%doc %{_mandir}/man5/client.conf.5.gz -%doc %{_mandir}/man5/cups-snmp.conf.5.gz -%doc %{_mandir}/man5/cupsd.conf.5.gz -%doc %{_mandir}/man5/mailto.conf.5.gz -%doc %{_mandir}/man5/mime.convs.5.gz -%doc %{_mandir}/man5/mime.types.5.gz -%doc %{_mandir}/man5/printers.conf.5.gz -%doc %{_mandir}/man5/subscriptions.conf.5.gz -%doc %{_mandir}/man7/backend.7.gz -%doc %{_mandir}/man7/drv.7.gz -%doc %{_mandir}/man7/filter.7.gz -%doc %{_mandir}/man7/notifier.7.gz -%doc %{_mandir}/man8/cups-deviced.8.gz -%doc %{_mandir}/man8/cups-driverd.8.gz -%doc %{_mandir}/man8/cups-lpd.8.gz -%doc %{_mandir}/man8/cups-polld.8.gz -%doc %{_mandir}/man8/cupsaddsmb.8.gz -%doc %{_mandir}/man8/cupsctl.8.gz -%doc %{_mandir}/man8/cupsd.8.gz -%doc %{_mandir}/man8/cupsfilter.8.gz -%{_datadir}/cups/ -%exclude %{_datadir}/cups/ppdc/ +%{_sbindir}/rc* +%dir %attr(0775,root,ntadmin) /usr/share/cups/drivers +%dir /usr/share/cups +/usr/share/applications/cups.desktop +/usr/share/pixmaps/cups.png +/usr/share/cups/[bcf-t]* +/usr/share/cups/d[ao]* +%dir %attr(0775,lp,lp) /var/cache/cups +%config %attr(0755,root,root) /etc/init.d/cups +%config /etc/pam.d/cups +/var/adm/fillup-templates/sysconfig.cups +%doc %{_defaultdocdir}/%{name} +%doc %{_mandir}/man5/* +%doc %{_mandir}/man7/* +%doc %{_mandir}/man8/* %files client %defattr(-,root,root) -%{_bindir}/cancel -%{_bindir}/cupstestdsc %{_bindir}/lp +%{_bindir}/lpc +%{_bindir}/lphelp %{_bindir}/lpoptions %attr(2755,lp,lp) %{_bindir}/lppasswd %{_bindir}/lpq %{_bindir}/lpr %{_bindir}/lprm %{_bindir}/lpstat +%{_bindir}/cancel +%{_sbindir}/*able %{_sbindir}/accept -%{_sbindir}/cupsaccept -%{_sbindir}/cupsdisable -%{_sbindir}/cupsenable -%{_sbindir}/cupsreject -%{_sbindir}/lpadmin -%{_sbindir}/lpc -%{_sbindir}/lpinfo -%{_sbindir}/lpmove +%{_sbindir}/lp* %{_sbindir}/reject -%doc %{_mandir}/man1/cancel.1.gz -%doc %{_mandir}/man1/cupstestdsc.1.gz -%doc %{_mandir}/man1/lp.1.gz -%doc %{_mandir}/man1/lpoptions.1.gz -%doc %{_mandir}/man1/lppasswd.1.gz -%doc %{_mandir}/man1/lpq.1.gz -%doc %{_mandir}/man1/lpr.1.gz -%doc %{_mandir}/man1/lprm.1.gz -%doc %{_mandir}/man1/lpstat.1.gz -%doc %{_mandir}/man8/accept.8.gz -%doc %{_mandir}/man8/cupsaccept.8.gz -%doc %{_mandir}/man8/cupsdisable.8.gz -%doc %{_mandir}/man8/cupsenable.8.gz -%doc %{_mandir}/man8/cupsreject.8.gz -%doc %{_mandir}/man8/lpadmin.8.gz -%doc %{_mandir}/man8/lpc.8.gz -%doc %{_mandir}/man8/lpinfo.8.gz -%doc %{_mandir}/man8/lpmove.8.gz -%doc %{_mandir}/man8/reject.8.gz +%doc %{_mandir}/man1/[a-eg-z]* %files devel %defattr(-,root,root) -%{_includedir}/cups/ +%{_includedir}/cups %{_libdir}/libcups.so %{_libdir}/libcupsimage.so -%{_libdir}/libcupscgi.so -%{_libdir}/libcupsdriver.so -%{_libdir}/libcupsmime.so -%{_libdir}/libcupsppdc.so -%{_datadir}/cups/ppdc/ - -%files ddk -%defattr(-,root,root) -%{_bindir}/ppdc -%{_bindir}/ppdhtml -%{_bindir}/ppdi -%{_bindir}/ppdmerge -%{_bindir}/ppdpo -%doc %{_mandir}/man1/ppdc.1.gz -%doc %{_mandir}/man1/ppdhtml.1.gz -%doc %{_mandir}/man1/ppdi.1.gz -%doc %{_mandir}/man1/ppdmerge.1.gz -%doc %{_mandir}/man1/ppdpo.1.gz -%doc %{_mandir}/man5/ppdcfile.5.gz %files libs %defattr(-,root,root) -%config(noreplace) %{_sysconfdir}/cups/client.conf +%{_bindir}/cups-config +# %dir %attr(0775,root,lp) %{_sysconfdir}/cups/ %dir %attr(0710,root,lp) %{_var}/spool/cups %dir %attr(1770,root,lp) %{_var}/spool/cups/tmp %dir %attr(0755,lp,lp) %{_var}/log/cups/ -%dir %attr(0775,lp,lp) %{_var}/cache/cups -%{_bindir}/cups-config +%config(noreplace) %{_sysconfdir}/cups/client.conf +%config(noreplace) /etc/sysconfig/SuSEfirewall2.d/services/cups %{_libdir}/libcups.so.* -%{_libdir}/libcupscgi.so.* -%{_libdir}/libcupsdriver.so.* %{_libdir}/libcupsimage.so.* -%{_libdir}/libcupsmime.so.* -%{_libdir}/libcupsppdc.so.* %{_datadir}/locale/*/cups_* -%doc %{_mandir}/man1/cups-config.1.gz %changelog - diff --git a/dvitops b/dvitops new file mode 100644 index 0000000..5313ee0 --- /dev/null +++ b/dvitops @@ -0,0 +1,41 @@ +#!/bin/sh + +if test "$#" -lt "5"; then + echo "ERROR: Number of arguments ($#) is wrong" 1>&2 + exit 1 +fi + +if test "$#" -gt "6"; then + echo "ERROR: Number of arguments ($#) is wrong" 1>&2 + exit 1 +fi + +# Log the command line +echo dvitops: $@ 1>&2 + +# Get the last parameter (which is the filename if present) +eval filename="\${$#}" + +if [ -e $filename ]; then + FILE_TO_PRINT=$filename; +else + FILE_TO_PRINT=""; +fi + +if [ -z $FILE_TO_PRINT ]; then + FILE_TO_PRINT=`mktemp -q /tmp/dvitops.XXXXXX` + if [ $? -ne 0 ]; then + echo "ERROR: Can't create temp file, exiting..." 1>&2 + exit 1 + fi + trap "rm -f $FILE_TO_PRINT" EXIT SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM + cat >$FILE_TO_PRINT +fi + +if [ -z $FILE_TO_PRINT ]; then + /usr/bin/dvips -q -f +else + /usr/bin/dvips -q -f <$FILE_TO_PRINT +fi + + diff --git a/full_path_to_configure_with-pdftops.patch b/full_path_to_configure_with-pdftops.patch new file mode 100644 index 0000000..d42a609 --- /dev/null +++ b/full_path_to_configure_with-pdftops.patch @@ -0,0 +1,15 @@ +--- config-scripts/cups-pdf.m4.orig 2009-07-31 14:39:16.000000000 +0200 ++++ config-scripts/cups-pdf.m4 2009-07-31 15:04:18.000000000 +0200 +@@ -62,6 +62,12 @@ case "x$with_pdftops" in + exit 1 + fi + ;; ++ ++ *) # Use exactly the /path/to/program which is specified ++ CUPS_PDFTOPS="$with_pdftops" ++ AC_DEFINE(HAVE_PDFTOPS) ++ PDFTOPS="pdftops" ++ ;; + esac + + AC_DEFINE_UNQUOTED(CUPS_PDFTOPS, "$CUPS_PDFTOPS") diff --git a/lphelp.c b/lphelp.c new file mode 100644 index 0000000..41cdbba --- /dev/null +++ b/lphelp.c @@ -0,0 +1,362 @@ +/* + * + * lphelp + * ------ + # + # A simple tool for getting information about an installed printer or a + # PPD file. Especially the printer-specific options defined in the PPD + # file are listed, so that one can make use of them with the "lp", "lpr", + # and "lpoptions" commands. The programm can also be used by installation/ + # configuration scripts to give a "preview" to a PPD file. + # + # ONLY WORKS WITH CUPS DAEMON RUNNING! + # The CUPS library (libcups.so.*) must be installed! + # + # Compile with: gcc -olphelp -lcups lphelp.c + # + * Copyright 2000 by Till Kamppeter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include + +/* + * 'main()' - Main entry for test program. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i, j, k, m; /* Looping vars */ + const char *filename; /* File to load */ + FILE *ppdfile; + + // Temporary file name (for reading from stdin) + char tmpfile[19] = "/tmp/lphelp.XXXXXX"; + const int blocksize = 1024; + char buffer[blocksize]; + int bytesread; + + // variables for parsing PPD file for usual options (boolean, enumerated) + ppd_file_t *ppd; /* PPD file record */ + ppd_size_t *size; /* Size record */ + ppd_group_t *group; /* UI group */ + ppd_option_t *option; /* Standard UI option */ + ppd_choice_t *choice; /* Standard UI option choice */ + static char *uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" }; + static char *sections[] = { "ANY", "DOCUMENT", "EXIT", + "JCL", "PAGE", "PROLOG" }; + + // variables for parsing CUPS-O-MATIC info for numerical options (float, int) + char line[1024], /* buffer for reading PPD file line by + line to search numerical options */ + item[1024], /* item to be defined (left of "=>") */ + value[1024], /* value for item (right of "=>") */ + argname[1024], /* name of the current argument */ + comment[1024]; /* human-readable argument name */ + const char *line_contents; /* contents of line */ + const char *scan; /* pointer scanning the line */ + char *writepointer; + double min, max, defvalue; /* Range of numerical + CUPS-O-MATIC option */ + int opttype; /* 0 = other, 1 = int, 2 = float */ + int openbrackets; /* How many curled brackets are open? */ + int inquotes; /* are we in quotes now? */ + int inargspart; /* are we in the arguments part now? */ + + /* + * Display PPD files for each file listed on the command-line... + */ + + if (argc == 1) { + fputs("Usage: lphelp .ppd [.ppd ...]\n lphelp [ ...]\n lphelp -\n", stderr); + return (1); + } + + for (i = 1; i < argc; i ++) { + if ((strstr(argv[i], ".ppd")) || (strstr(argv[i], "-"))) + filename = argv[i]; + else + filename = cupsGetPPD(argv[i]); + if (strcmp(filename,"-") == 0) { + if ((ppdfile = fdopen(mkstemp(tmpfile), "w")) == NULL) { + fprintf(stderr, "Unable to generate temporary file!\n"); + } + while ((bytesread = fread(buffer, 1, blocksize, stdin)) > 0) { + fwrite(buffer, 1, bytesread, ppdfile); + } + fclose(ppdfile); + filename = tmpfile; + } + if ((ppd = ppdOpenFile(filename)) == NULL) { + fprintf(stderr, "Unable to open \'%s\' as a PPD file!\n", filename); + continue; + } + + printf("==============================================================================\n\n"); + printf("%s\n\n", ppd->modelname); + printf("==============================================================================\n\n"); + printf(" %s printer\n\n", ppd->color_device ? "Colour" : "Black & white"); + printf(" Printer-specific options\n"); + printf(" ------------------------\n\n"); + printf(" Besides the options described in the CUPS software users manual\n"); + printf(" (http://localhost:631/sum.html) you can use also the following options\n"); + printf(" when you print on this printer with the \"lp\" or \"lpr\" command (a choice\n"); + printf(" with the \"default\" mark represents the behaviour of the printer when the\n"); + printf(" appropriate option is not given on the command line):\n\n"); + + for (j = 0, group = ppd->groups; j < ppd->num_groups; j ++, group ++) { + for (k = 0, option = group->options; k < group->num_options; + k ++, option ++) { + if (strcmp(option->keyword, "PageRegion") != 0) { + if ((strcmp(uis[option->ui],"BOOLEAN") == 0) || + (strcmp(uis[option->ui],"PICKONE") == 0)) { + printf(" %s: -o %s=\n\n", + option->text, option->keyword); + printf(" can be one of the following:\n\n"); + } else { + printf(" %s: -o %s=,,...\n\n", + option->text, option->keyword); + printf(" , , and so on can be out of the following:\n\n"); + } + if (strcmp(option->keyword, "PageSize") == 0) { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) { + size = ppdPageSize(ppd, choice->choice); + + if (size == NULL) + printf(" %s (%s, size unknown", choice->choice, choice->text); + else + printf(" %s (%s, size: %.2fx%.2fin", choice->choice, + choice->text, size->width / 72.0, size->length / 72.0); + if (strcmp(option->defchoice, choice->choice) == 0) + puts(", default)"); + else + puts(")"); + } + } else { + for (m = option->num_choices, choice = option->choices; + m > 0; + m --, choice ++) { + printf(" %s (%s", choice->choice, choice->text); + if (strcmp(option->defchoice, choice->choice) == 0) + puts(", default)"); + else + puts(")"); + } + } + printf("\n"); + } + } + } + ppdClose(ppd); + + // Search for numerical options of CUPS-O-MATIC + if ((ppdfile = fopen(filename,"r")) == NULL) { + fprintf(stderr, "Unable to open \'%s\' as a PPD file!\n", filename); + continue; + } + // Reset all variables + opttype = 0; + min = 0.0; max = 0.0; defvalue = 0.0; + openbrackets = 0; + inquotes = 0; + writepointer = item; + inargspart = 0; + // Read the PPD file again, line by line. + while (fgets(line,sizeof(line),ppdfile)) { + // evaluate only lines with CUPS-O-MATIC info + if (line_contents = strstr(line,"*% COMDATA #")) { + line_contents += 12; // Go to the text after + // "*% COMDATA #" + for (scan = line_contents; + (*scan != '\n') && (*scan != '\0'); + scan ++) { + switch(*scan) { + case '[': // open square bracket + case '{': // open curled bracket + if (!inquotes) { + openbrackets ++; + // we are on the left hand side now + *writepointer = '\0'; + writepointer = item; + // in which type of block are we now? + if ((openbrackets == 2) && + (strncasecmp(item,"args",4) == 0)) { + // we are entering the arguments section now + inargspart = 1; + } + if ((openbrackets == 3) && + (inargspart == 1)) { + // new argument, get its name + strcpy(argname,item); + } + // item already evaluated now + item[0] = '\0'; + } else {*writepointer = *scan; writepointer ++;} + break; + case ',': // end of logical line + case ']': // close square bracket + case '}': // close curled bracket + if (!inquotes) { + // right hand side completed, go to left hand side + *writepointer = '\0'; + writepointer = item; + // evaluate logical line + if (item[0]) { + // Machine-readable argument name + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"name") == 0)) { + strcpy(argname,value); + } + // Human-readable argument name + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"comment") == 0)) { + strcpy(comment,value); + } + // argument type + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"type") == 0)) { + if (strcasecmp(value,"int") == 0) opttype = 1; + if (strcasecmp(value,"float") == 0) opttype = 2; + } + // minimum value + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"min") == 0)) { + min = atof(value); + } + // maximum value + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"max") == 0)) { + max = atof(value); + } + // default value + if ((openbrackets == 3) && + (inargspart == 1) && + (strcasecmp(item,"default") == 0)) { + defvalue = atof(value); + } + // item already evaluated now + item[0] = '\0'; + } + // close bracket + if ((*scan == '}') || (*scan == ']')) { + // which block did we complete now? + if ((openbrackets == 2) && + (inargspart == 1)) { + // We are leaving the arguments part now + inargspart = 0; + } + if ((openbrackets == 3) && + (inargspart == 1)) { + // The current option is completely parsed + // Is the option a valid numerical option? + if ((opttype > 0) && + (min != max) && + (argname[0])) { + // Correct the default value, if necessary + if (min < max) { + if (defvalue < min) defvalue = min; + if (defvalue > max) defvalue = max; + } else { + if (defvalue < max) defvalue = max; + if (defvalue > min) defvalue = min; + } + // Show the found argument + printf(" %s: -o %s=\n\n", + comment, argname); + if (opttype == 1) { + printf( + " must be an integer number in the range %d..%d\n", + (int)(min),(int)(max)); + printf( + " The default value is %d\n\n", + (int)(defvalue)); + } else { + printf( + " must be a decimal number in the range %.2f..%.2f\n", + min,max); + printf( + " The default value is %.2f\n\n", + defvalue); + } + } + // reset the values + argname[0] = '\0'; + opttype = 0; + min = 0.0; max = 0.0; defvalue = 0.0; + } + openbrackets --; + } + } else {*writepointer = *scan; writepointer ++;} + break; + case '\'': // quote + if (!inquotes) { // open quote pair + inquotes = 1; + } else { // close quote pair + inquotes = 0; + } + break; + case '=': // "=>" + if ((!inquotes) && (*(scan + 1) == '>')) { + scan ++; + // left hand side completed, go to right hand side + *writepointer = '\0'; + writepointer = value; + } else {*writepointer = *scan; writepointer ++;} + break; + case ' ': // white space + case '\t': + if (!inquotes) { + // ignore white space outside quotes + } else {*writepointer = *scan; writepointer ++;} + break; + default: + // write all other characters + *writepointer = *scan; writepointer ++; + break; + } + } + inquotes = 0; // quote pairs cannot enclose more + // than one line + } + } + fclose(ppdfile); + printf("\n\n\n"); + } + + if (!(strstr(tmpfile, "XXXXXX"))) { + unlink(tmpfile); + } + + return (0); +} diff --git a/ogonki b/ogonki new file mode 100644 index 0000000..9e8bb14 --- /dev/null +++ b/ogonki @@ -0,0 +1,50 @@ +#!/bin/sh + +if test "$#" -lt "5"; then + echo "ERROR: Number of arguments ($#) is wrong" 1>&2 + exit 1 +fi + +if test "$#" -gt "6"; then + echo "ERROR: Number of arguments ($#) is wrong" 1>&2 + exit 1 +fi + +# Log the command line +echo ogonkify: $@ 1>&2 + +# Get the last parameter (which is the filename if present) +eval filename="\${$#}" + +case "$CHARSET" in + iso-8859-1) CMD="cat " ;; + iso-8859-2) CMD="/usr/bin/ogonkify -AT -N " ;; + iso-8859-3) CMD="/usr/bin/ogonkify -e L3 -AT -N " ;; + iso-8859-4) CMD="/usr/bin/ogonkify -e L4 -AT -N " ;; + iso-8859-9) CMD="/usr/bin/ogonkify -e L5 -AT -N " ;; + iso-8859-10) CMD="/usr/bin/ogonkify -e L6 -AT -N " ;; + iso-8859-15) CMD="/usr/bin/ogonkify -e L9 -AT -N " ;; + *) CMD="cat " ;; +esac + +if [ -e $filename ]; then + FILE_TO_PRINT=$filename; +else + FILE_TO_PRINT=""; +fi + +if [ -z $FILE_TO_PRINT ]; then + FILE_TO_PRINT=`mktemp -q /tmp/ogonki.XXXXXX` + if [ $? -ne 0 ]; then + echo "ERROR: Can't create temp file, exiting..." 1>&2 + exit 1 + fi + trap "rm -f $FILE_TO_PRINT" EXIT SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM + cat >$FILE_TO_PRINT +fi + +if [ -z $FILE_TO_PRINT ]; then + eval $CMD +else + eval $CMD <$FILE_TO_PRINT +fi diff --git a/poll_ppd_base.c b/poll_ppd_base.c new file mode 100644 index 0000000..78f4381 --- /dev/null +++ b/poll_ppd_base.c @@ -0,0 +1,302 @@ +/* + * + * poll_ppd_base + * ------------- + # + # A simple tool for getting a list of all installed PPD files + # with printer manufacturer and printer model, polling the database + # of the CUPS daemon. This program is mainly intended to be called + # from installation/configuration scripts for CUPS. + # + # ONLY WORKS WITH CUPS DAEMON RUNNING! + # The CUPS library (libcups.so.*) must be installed! + # + # Compile with: gcc -opoll_ppd_base -lcups poll_ppd_base.c + # + * Copyright 2000 by Till Kamppeter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA + * + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include +#include + +// IPP Request routines for getting the printer type, stolen from QTCUPS from +// Michael Goffioul (file qtcups/cupshelper.cpp) + +ipp_t* newIppRequest() +{ + ipp_t *request; + cups_lang_t *lang; + request = ippNew(); + request->request.op.request_id = 1; + lang = cupsLangDefault(); + ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_CHARSET,"attributes-charset",NULL,cupsLangEncoding(lang)); + ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_LANGUAGE,"attributes-natural-language",NULL,lang->language); + return request; +} + +ipp_t* processRequest(ipp_t *req, const char *res) +{ + http_t *HTTP; + ipp_t *answer; + HTTP = httpConnect(cupsServer(),ippPort()); + if (!HTTP) { + ippDelete(req); + return 0; + } + answer = cupsDoRequest(HTTP,req,res); + httpClose(HTTP); + if (!answer) return 0; + if (answer->state == IPP_ERROR || answer->state == IPP_IDLE) { + ippDelete(answer); + return 0; + } + return answer; +} + +ipp_t *getPPDList() +{ + ipp_t *request = newIppRequest(); + char str[1024]; + const char* server = cupsServer(); + int port = ippPort(); + + request->request.op.operation_id = CUPS_GET_PPDS; + if ((!server) || (port < 0)) return NULL; + sprintf(str,"ipp://%s:%d/printers/",cupsServer(),ippPort()); + ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_URI,"printer-uri",NULL,str); + //str.sprintf("/printers/%s",name); + request = processRequest(request,"/"); + return request; +} + +/* + * Main program + */ + +int /* O - exit state */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i,j; /* Looping vars */ + int makelen = 0; /* Length of current manufacturer name */ + int makelist = 0; /* List of manufacturers */ + int makegiven = 0; /* List of models for given manufacturer */ + int all = 0; /* LIst of all models */ + char *make; /* Chosen manufacturer */ + ipp_t *ppdlist; /* List of PPD files resulting from IPP */ + /* request */ + ipp_attribute_t *attr, /* Current attribute */ + *last; /* Last attribute */ + char *currmake, /* current data red from PPD list */ + *currmod, + *currlang, + *currfile, + *c; + char buffer[80], + buffer2[256]; + int lineprinted = 1; /* Is the current line already printed to + stdout */ + + // read command line arguments + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'm' : /* Manufacturer options */ + if (argv[i][2] != '\0') { + if (strcmp(argv[i],"-ml") == 0) { + makelist = 1; + } else { + make = argv[i] + 2; + makegiven = 1; + } + } else { + i ++; + if (!(make = argv[i])) return 1; + makegiven = 1; + } + break; + case 'a' : /* List all PPD files */ + all = 1; + break; + default : + fprintf(stderr,"Unknown option \'%c\'!\n", argv[i][1]); + fprintf(stderr,"Start program without options for help!\n"); + return(1); + } + } else { + fprintf(stderr,"Unknown option \'%s\'!", argv[i]); + fprintf(stderr,"Start program without options for help!\n"); + return(1); + } + if ((all) || (makegiven)) { // list all PPDs or PPDs of given manufacturer + ppdlist = getPPDList(); + if (!ppdlist) return 1; + for (attr = ppdlist->attrs; // go through all entries + attr != NULL; + attr = attr->next) + if (attr->name) { + // read data items + if (strcmp(attr->name, "ppd-name") == 0) { + currfile = attr->values[0].string.text; + lineprinted = 0; + } else if (strcmp(attr->name, "ppd-make") == 0) { + currmake = attr->values[0].string.text; + } else if (strcmp(attr->name, "ppd-make-and-model") == 0) { + currmod = attr->values[0].string.text; + } else if (strcmp(attr->name, "ppd-natural-language") == 0) { + currlang = attr->values[0].string.text; + } + } else { // attr->name = NULL ==> data set completed + lineprinted = 1; + // Fill empty entries with some default stuff + if (!currmod) currmod = "UNKNOWN"; + if (!currmake) currmake = "UNKNOWN"; + if (!currlang) currlang = "en"; + // Remove the manufacturer's name from the model entries + makelen = strlen(currmake); + if (strcasecmp(currmake,"UNKNOWN") != 0) { + if (strncasecmp(currmake,currmod,makelen) == 0) { + currmod += makelen; + while ((*currmod == ' ') || + (*currmod == '-') || + (*currmod == '\t')) currmod ++; + } + } + // Make the manufacturer's name all-uppercase + currmake = strcpy(buffer,currmake); + for (i = 0; i < makelen; i ++) buffer[i] = toupper(buffer[i]); + // Clean up the driver info + currmod = strcpy(buffer2,currmod); + if (c = strstr(currmod, "Foomatic + Postscript")) { + memmove(c, "PostScript", 10); + memmove(c + 10, c + 21, strlen(c) - 20); + } else if (c = strstr(currmod, "Foomatic")) { + memmove(c + 11, c + 8, strlen(c) - 7); + memmove(c, "GhostScript", 11); + } else if (c = strstr(currmod, "CUPS+GIMP-print")) { + memmove(c + 17, c + 15, strlen(c) - 14); + memmove(c, "CUPS + GIMP-Print", 17); + } else if (c = strstr(currmod, "Series CUPS")) { + memmove(c + 12, c + 11, strlen(c) - 10); + memmove(c, "Series, CUPS", 12); + } else if (!((strstr(currmod, "PostScript")) || + (strstr(currmod, "Postscript")) || + (strstr(currmod, "POSTSCRIPT")))) { + memmove(currmod + strlen(currmod), ", PostScript", 13); + } + // Put data to stdout when "all" is chosen or when the manufacturer + // matches the given one. + if ((currfile) && ((all) || !strcasecmp(currmake,make))) + printf("%s|%s|%s|%s\n",currfile,currmake,currmod,currlang); + } + if (!lineprinted) { + // Fill empty entries with some default stuff + if (!currmod) currmod = "UNKNOWN"; + if (!currmake) currmake = "UNKNOWN"; + if (!currlang) currlang = "en"; + // Remove the manufacturer's name from the model entries + makelen = strlen(currmake); + if (strcasecmp(currmake,"UNKNOWN") != 0) { + if (strncasecmp(currmake,currmod,makelen) == 0) { + currmod += makelen; + while ((*currmod == ' ') || + (*currmod == '-') || + (*currmod == '\t')) currmod ++; + } + } + // Make the manufacturer's name all-uppercase + currmake = strcpy(buffer,currmake); + for (i = 0; i < makelen; i ++) buffer[i] = toupper(buffer[i]); + // Clean up the driver info + currmod = strcpy(buffer2,currmod); + if (c = strstr(currmod, "Foomatic + Postscript")) { + memmove(c, "PostScript", 10); + memmove(c + 10, c + 21, strlen(c) - 20); + } else if (c = strstr(currmod, "Foomatic")) { + memmove(c + 11, c + 8, strlen(c) - 7); + memmove(c, "GhostScript", 11); + } else if (c = strstr(currmod, "CUPS+GIMP-print")) { + memmove(c + 17, c + 15, strlen(c) - 14); + memmove(c, "CUPS + GIMP-Print", 17); + } else if (c = strstr(currmod, "Series CUPS")) { + memmove(c + 12, c + 11, strlen(c) - 10); + memmove(c, "Series, CUPS", 12); + } else if (!((strstr(currmod, "PostScript")) || + (strstr(currmod, "Postscript")) || + (strstr(currmod, "POSTSCRIPT")))) { + memmove(currmod + strlen(currmod), ", PostScript", 13); + } + // Put data to stdout when "all" is chosen or when the manufacturer + // matches the given one. + if ((currfile) && ((all) || !strcasecmp(currmake,make))) + printf("%s|%s|%s|%s\n",currfile,currmake,currmod,currlang); + } + } else if (makelist) { // list all manufacturers + ppdlist = getPPDList(); + if (!ppdlist) return 1; + for (attr = ppdlist->attrs, last = NULL; // go through all entries + attr != NULL; + attr = attr->next) + if (attr->name && strcmp(attr->name, "ppd-make") == 0) + // only search for manufacturerer entriees + if (last == NULL || + strcasecmp(last->values[0].string.text, + attr->values[0].string.text) != 0) + // Do not take the same manufacturer twice + { + // Put found manufacturer to stdout + printf("%s\n",attr->values[0].string.text); + last = attr; + } + } else { // Help! + fprintf(stderr,"Usage:\n"); + fprintf(stderr,"------\n"); + fprintf(stderr,"\n"); + fprintf(stderr," poll_ppd_base\n"); + fprintf(stderr,"\n"); + fprintf(stderr," This help page\n"); + fprintf(stderr,"\n"); + fprintf(stderr," poll_ppd_base -a\n"); + fprintf(stderr,"\n"); + fprintf(stderr," List all PPD files\n"); + fprintf(stderr,"\n"); + fprintf(stderr," poll_ppd_base -ml\n"); + fprintf(stderr,"\n"); + fprintf(stderr," List of all printer manufacturers supported by the PPD files installed\n"); + fprintf(stderr,"\n"); + fprintf(stderr," poll_ppd_base -m \n"); + fprintf(stderr,"\n"); + fprintf(stderr," List of all supported printer models of this manufacturer\n"); + fprintf(stderr,"\n"); + fprintf(stderr,"ONLY WORKS WITH CUPS DAEMON RUNNING!\n"); + fprintf(stderr,"\n"); + return(1); + } + return(0); +} diff --git a/pswrite b/pswrite new file mode 100644 index 0000000..c5492d4 --- /dev/null +++ b/pswrite @@ -0,0 +1,12 @@ +#! /bin/bash + +# enable "set -x" for debug info in /var/log/cups/error_log +#set -x + +# set inputfile to where the input comes from +inputfile="-" +[ -n "$6" ] && inputfile="$6" + +# output PostScript level 1 (for PostScript level 2 use -dLanguageLevel=2) +gs -q -dBATCH -dPARANOIDSAFER -dNOPAUSE -sDEVICE=pswrite -dLanguageLevel=1 -sOutputFile=- $inputfile + diff --git a/quosnmp b/quosnmp new file mode 100644 index 0000000..6d9c7f8 --- /dev/null +++ b/quosnmp @@ -0,0 +1,574 @@ +#!/usr/bin/perl +# quosnmp +# Version 1.0.0, Last modified on 2007-06-22 +# A CUPS backend for SNMP-based print accounting and quota enforcement. +# +# Released by Marcus Lauer (marcus.lauer at nyu dot edu) +# +# Copyright (C) 2007 by Marcus Lauer (marcus.lauer at nyu dot edu) except where +# previous copyright is in effect. +# +# Based on accsnmp v1.02.20070124 by jeff hardy (hardyjm at potsdam dot edu) +# ############ +# accsnmp +# v1.02.20070124 +# jeff hardy (hardyjm at potsdam dot edu) +# backend wrapper hardware accounting for cups +# +# ############ +# Copyright 2007, Jeff Hardy (hardyjm at potsdam dot edu) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# +# ########### +# example URI - quosnmp://socket://192.168.xxx.xxx +# +# arguments according to the docs, as C sees them: +# 0 1 2 3 4 5 6 +# lpd jobid username jobtitle copies printoptions file ///or read from STDIN if no filename +# +# arguments as Perl sees them: +# 0 1 2 3 4 5 +# jobid username jobtitle copies printoptions file ///or read from STDIN if no filename + + +use strict; +use Net::SNMP; + +# --- Modify these settings to suit your needs. +my $ENFORCE_QUOTA = 1; # Turn on/off [1/0] print quota enforcement +my $SAVE_JOBS = 0; #turn on/off [1/0] saving printjobs +my $JOB_BLACKLIST = 0; #turn on/off [1/0] jobs blacklist +my @JobBlacklist = (""); # Names of jobs to be blacklisted. + +my $LOGGING = 1; # Turn on/off [1/0] print logging function call +my $LOGGING_FILE = "/var/log/cups/acc_page_log"; # File for printer logging +my $ERROR_LOGGING = 1; # Turn on/off [1/0] error logging function call +my $ERROR_LOGGING_FILE = "/var/log/cups/acc_error_log"; # File for error logging + +my $headerDiscount = 0; # Credit accounts this many pages per print job for mandatory header (or footer) pages + +my $DEBUG = 0; #turn on/off [1/0] debugging function call +my $DEBUG_FILE = "/tmp/quosnmp.debug"; #tmp file for debugging + +my $SNMP_COMMUNITY = "public"; #best to use read community obviously + +# --- These settings can be modified, but it is less likely that you will need to do so. +my $accDir = "/var/log/cups/accounting"; #directory to keep accounting files +my $quoDir = "/var/log/cups/quotas"; #directory to keep quota files +my $accPrinterList = "/etc/cups/accounted-printers.txt";#list of special (usually color) printers -- pages printed to these count triple + +my $backendDir = "/usr/lib/cups/backend"; #directory which contains all cups backends + +my $SNMP_TIMEOUT = 15; # SNMP timeout in seconds, 0 to try forever, max 60 +my $SNMP_RETRIES = 5; # Number of times to retry an SNMP request, max 20 +my $BACKEND_ATTEMPTS = 10; #backend retry attempts, 0 to try forever +my $STALL_TIMEOUT = 600; # Assume printer is stalled after this many seconds, 0 to disable + +# --- You almost certainly do not want to modify these variables. +my $PAGECOUNT_OID = "1.3.6.1.2.1.43.10.2.1.4.1.1"; #printer lifetime pagecount +my $PRINTERSTATUS_OID = "1.3.6.1.2.1.25.3.5.1.1.1"; #printer status + + +# --- Only experts should modify the code below this line. + +# This is used by some of the logging features. +my @startTime = localtime(time); + +### MAIN +{ + ### ARGS CHECK + if (!$ARGV[0]){ # Device discovery mode + print ("network quosnmp \"Unknown\" \"Accounted Printer (SNMP)\"\n"); + exit 0; + } + if (scalar(@ARGV) < 5 || scalar(@ARGV) > 6){ # Error + print STDERR ("ERROR: Usage: quosnmp job-id user title copies options [file]\n"); + exit 1; + } + # Now that we got this far, let us name the arguments to keep our sanity + my ($jobID,$userName,$jobTitle,$copies,$printOptions,$printFile) = @ARGV; + + ### ENV CHECK + # URI parsing must fit syntax or die + # Ex: quosnmp://lpd://192.168.xxx.xxx + # Also supported: quosnmp://hp:/net/HP_LaserJet_xxxx_Series?ip=192.168.xxx.xxx + $ENV{DEVICE_URI} =~ m#(\S+)://(\S+):/\S+?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\S?# or + cleanExit($jobID,$ENV{PRINTER},"ERROR: URI must be in format: quosnmp://\n"); + my $wrapBackend = $1; + my $realBackend = $2; + my $printerIP = $3; + + ### BLACKLIST/QUOTA CHECKS + if ( length($userName) < 1 ){ # No username + cleanExit($jobID,$ENV{PRINTER},"ERROR: No username for printjob: user must authenticate\n"); + } + + if ($ENFORCE_QUOTA == 1) { + my $printQuota = getPrintQuota($quoDir,$userName); + + if ( $printQuota != -1 ) { # -1 is a special value meaning unlimited printing is allowed. + my $userPagesPrinted = getUserTotal("$accDir/$userName"); + + # If the user is over quota, or is disallowed to print, or no quota file was found at all, then exit. + if ( $userPagesPrinted >= $printQuota || $printQuota == 0 || $printQuota == -2 ) { + cleanExit($jobID,$ENV{PRINTER},"ERROR: Account ($userName) is at or over quota ($printQuota pages) and cannot print\n"); + } + } + } + + if ($JOB_BLACKLIST){ + my $jobStatus = chkJobBlacklist($jobTitle); + if ($jobStatus == -1){ # Job is blacklisted + cleanExit($jobID,$ENV{PRINTER},"ERROR: Jobname ($jobTitle) is blacklisted from printing\n"); + } + } + + + ### SPOOL JOB TO TEMP FILE + my $jid = $jobID; + my $uid = $userName; + $jid =~ s/\W//g; #sanity check + $uid =~ s/\W//g; #sanity check + my $tempFile = "$ENV{TMPDIR}/$jid-$uid-cupsjob$$"; + + if ($printFile){ # Only spool given print file if we want to save + if ($SAVE_JOBS){ + open (OUT, ">$tempFile") or cleanExit($jid,$ENV{PRINTER},"ERROR: Cannot write $tempFile: $!\n"); + open (FH, "$printFile") or cleanExit($jid,$ENV{PRINTER},"ERROR: Cannot read $printFile: $!\n"); + while(){ + print OUT "$_"; + } + close FH; + close OUT; + } + } + else { # Have to spool to temp if STDIN + open (OUT, ">$tempFile") or cleanExit($jid,$ENV{PRINTER},"ERROR: Cannot write $tempFile: $!\n"); + while(){ + print OUT "$_"; + } + close OUT; + } + + + ### PRINTING + # SNMP pagecount: first snmp query + my $prePageCount = snmpGet($printerIP,$PAGECOUNT_OID,$jid); + + + # NOTE: the next several lines are the guts of wrapping a cups backend + # 1) Pull the device URI from the environment and fix it by removing the wrapper + # 2) Tack this onto the front of the arg array to pass to the real backend + # Note: 1 and 2 are required as different backends find the device URI by + # different means. LPD gets it from the arg, whereas IPP gets it from env. + # 3) If the job arrived via STDIN, tack printFile onto the end of the arg array + # This will happen on non-raw queues and needs to be checked, otherwise we + # will dos the printer with a "zero byte" error. + # 4) Call the real backend with this new argument array + + my $deviceURI = $ENV{DEVICE_URI}; + $deviceURI =~ s#$wrapBackend://##; + $ENV{DEVICE_URI} = $deviceURI; + + if (!($printFile)){ + $copies = 1; + $printFile = $tempFile; + } + my @argvNew = ($deviceURI,$jobID,$userName,$jobTitle,$copies,$printOptions,$printFile); + + # Loop until $attempts trying the backend + my $attempts = $BACKEND_ATTEMPTS; + my $exitval = 1; + while ($exitval){ + # Override arg0 + $exitval = system {"$backendDir/$realBackend"} @argvNew; + $exitval >>= 8; + if ($attempts > 0){ + $attempts--; + if ($attempts == 0){ + unlink $tempFile; + cleanExit($jid,$ENV{PRINTER},"ERROR: Backend failed!\n"); + } + } + } + + # Now the real backend is processing the job, and we loop to keep an eye + # on the printer status until it is done. + sleep 1; + my $waitCount = 0; + my $somethingPrinted = 0; + $SIG{ALRM} = sub { cleanExit($jid,$ENV{PRINTER},"ERROR: Printer is stalled!\n") }; + while (1){ + alarm ($STALL_TIMEOUT); + + # 3 is idle, 4 is printing, 5 is warmup, 1 is other + my $prStatus = snmpGet($printerIP,$PRINTERSTATUS_OID,$jid); + if ($prStatus == 4){ + print STDERR "INFO: Printer status: printing\n"; + $somethingPrinted = 1; + } + elsif (($prStatus != 4) && ($somethingPrinted)){ + $waitCount += 1; + # Wait until status is idle for several counts + if ($waitCount == 3){ + print STDERR "INFO: Job printed successfully\n"; + last; + } + } + else{ + print STDERR "INFO: Printer status: other\n"; + } + sleep 2; + } + + # SNMP pagecount: last snmp query + my $postPageCount = snmpGet($printerIP,$PAGECOUNT_OID,$jid); + + + ### ACCOUNTING + # Delta of our pagecounts + my $totalPages = $postPageCount - $prePageCount; + # Give a discount for header pages + if ($headerDiscount > 0){ + $totalPages = $totalPages - $headerDiscount; + if ($totalPages < 1){ + $totalPages = 0; + } + } + # If no error from real backend (non-zero is error)... + if (!$exitval){ + accounting($userName,$totalPages); + } + + + ### CLEANUP/EXIT + # If requested, write out a system log. + if ( $LOGGING ) { + open (LOG_FH, ">>$LOGGING_FILE") or $LOGGING = 0; + flock LOG_FH, 2; + seek LOG_FH, 0 , 2; + printf LOG_FH "%04d-%02d-%02d\t%02d:%02d:%02d\t",$startTime[5]+1900,$startTime[4]+1,$startTime[3],$startTime[2],$startTime[1],$startTime[0]; + print LOG_FH "$printerIP\t$jobID\t$userName\t$jobTitle\t$copies\t$prePageCount\t$postPageCount\t$exitval\t$totalPages\t$headerDiscount\n"; + flock LOG_FH, 8; + close (LOG_FH); + } + if ($DEBUG == 1){ + #print STDERR ("ERROR: $postPageCount minus $prePageCount equals $totalPages\n"); + debug($DEBUG_FILE); + } + if (!$SAVE_JOBS){ + unlink $tempFile; + } + exit $exitval; +} + + +sub cleanExit{ + # Args: jobid, queuename, error message to print + # Returns: nothing, deletes job and re-enables queue + my $jobid = shift; + my $queue = shift; + my $errorMsg = shift; + + if ( length($errorMsg) > 0 ) { + print STDERR $errorMsg; + + if ( $ERROR_LOGGING == 1 ) { + my @errorTime = localtime(time); + + open (ERR_LOG_FH, ">>$ERROR_LOGGING_FILE") or $ERROR_LOGGING = 0; + flock ERR_LOG_FH, 2; + seek ERR_LOG_FH, 0 , 2; + printf LOG_FH "%04d-%02d-%02d\t%02d:%02d:%02d\t",$errorTime[5]+1900,$errorTime[4]+1,$errorTime[3],$errorTime[2],$errorTime[1],$errorTime[0]; + print ERR_LOG_FH "$jobid\t$queue\t$errorMsg\n"; + flock ERR_LOG_FH, 8; + close (ERR_LOG_FH); + } + } + sleep 1; + system("/usr/bin/lprm","$jobid"); + sleep 1; + system("/usr/sbin/cupsenable","$queue"); + sleep 1; + exit 1; +} + + +sub snmpGet{ + # Args: ip, oid, jid + # Returns: value of SNMP query. JobID needed only for exiting script cleanly if this fails. + my $ip = shift; + my $oid = shift; + my $jid = shift; + + # Creating the session should always succeed + my ($session, $error) = Net::SNMP->session( + -hostname => $ip, + -version => 'snmpv1', #or 'snmpv2c' or 'snmpv3' as required + -community => $SNMP_COMMUNITY, + -timeout => $SNMP_TIMEOUT, #default, max: 60 + -retries => $SNMP_RETRIES #default, max: 20 + ); + # Paranoid check + if (!defined($session)) { + cleanExit($jid,$ENV{PRINTER},"ERROR: SNMP session creation error: $error\n"); + } + + # The get request will loop until the alarm is tripped + my $result; + my $err; + + eval{ + while(!defined($result)){ + $result = $session->get_request( + -varbindlist => [$oid] + ); + $err = $session->error; + } + alarm (0); # cancel the alarm + }; + if ($@ =~ /SNMP ERROR/){ + cleanExit($jid,$ENV{PRINTER},"ERROR: SNMP Error: $err\n"); + } + # Paranoid check. This is spurious because the eval loop won't let this happen. + if (!defined($result)) { + my $err = $session->error; + $session->close; + cleanExit($jid,$ENV{PRINTER},"ERROR: SNMP Error: $err\n"); + } + + my $return = $result->{$oid}; + $session->close; + return $return; +} + + +sub chkJobBlacklist{ + # Args: jobname + # Returns: -1/bad | 1/good + # This is not terribly safe, but can be terribly handy + my $jobName = shift; + + foreach my $blackJob (@JobBlacklist) { + if ($blackJob =~ $jobName) { return -1; } + } + + return 1; +} + + +sub accounting{ + # Args: user, totalpages, printername + # Returns: nothing, logs to page_log and writes to user file in accounting directory + my $user = shift; + my $newPages = shift; #what was printed this time + + if ($user eq ""){ + $user = "NO_USER"; + } + my $accFile = "$accDir/$user"; + + # If color printer from our printer accounting list, multiply pagecount by three + # + # Example accPrinterList: + # Every queuename ends with colon, color queues add =COLOR= + # + # SAT104CL:=COLOR= + # SAT325: + # SIS217: + # + if (chkPrinterColor($ENV{PRINTER},$accPrinterList)){ + $newPages = $newPages*3; + } + + # Send nonstandard message to page_log (real wrapped backend will also send standard message) + print STDERR ("PAGE: $user $newPages\n"); + + # And now handle their historical total + # If accFile exists: get previous count, get total, write new count + if (-e $accFile){ + my $histPages = getUserTotal($accFile); + my $totPages = $newPages + $histPages; + setUserTotal($accFile,$totPages); + } + # Else accFile does not exist: write out new accFile + else{ + setUserTotal($accFile,$newPages); + # Modify read permissions so accounting is secure + chmod (0640,"$accFile"); + system ("chown","lp","$accFile"); + system ("chgrp",$user,"$accFile"); # Note: this doesn't work unless CUPS runs this backend as root! + } +} + + +sub getUserTotal{ + # Args: accounting file + # Returns: user's historical pagecount + my $accFile = shift; + my $histPages; + open (FH, "$accFile") or warn "ERROR: Cannot read $accFile: $!\n"; + while(){ + $histPages = $histPages+$_; #extra safety in case of badly formatted file + } + close (FH); + return $histPages; +} + + +sub setUserTotal{ + # Args: accounting file + # Returns: nothing, writes to user's pagecount file + my $accFile = shift; + my $totPages = shift; + open (OUT, ">$accFile") or warn "ERROR: Cannot write $accFile: $!\n"; + flock OUT, 2; + print (OUT "$totPages\n"); + flock OUT, 8; + close (OUT); +} + + +sub chkPrinterColor{ + # Args: printer, printerlistfile + # Returns: 1/color printer | 0/not color printer + my $printer = shift; + my $accPrinterList = shift; + open (FH, "$accPrinterList") or warn "Cannot read $accPrinterList: $!\n"; + while (){ + if (m/^$printer:=COLOR=/i){ + return 1; + } + } + close FH; + return 0; +} + + +sub debug{ + # Args: debugging file + # Returns: nothing, just write out some debug info + my $debugFile = shift; + my $date=`/bin/date +%T%t%D`; + + open (OUT, ">>$debugFile"); + flock OUT, 2; + seek OUT, 0, 2; + print (OUT "\n=======================\n"); + + # print time + print (OUT "\n$date\n"); + + # print args + print (OUT "\narguments passed to backend:\n"); + my $i=0; + foreach (@ARGV){ + print (OUT "$i:$_\t"); + $i++; + } + print (OUT "\n"); + + # print env + print (OUT "\nenvironment variables:\n"); + for(keys(%ENV)) { + print (OUT "$_ = $ENV{$_}\t"); + } + print (OUT "\n"); + + print (OUT "\n=======================\n"); + flock OUT, 8; + close (OUT); +} + + +sub getPrintQuota { + # Args: accounting filedir, username + # Returns: user's print quota + # + # * The user quota _always_ has first priority + # * The group which gives the highest quota has second priority, e.g. will be used if + # no user quota is found. + # * The default quota _always_ has the lowest priority. It will only be used if no + # other quota is found. + # + # Possible return values: + # -2 No quota files found, printing not allowed. + # -1 Unlimited printing allowed (no quota). + # 0 Printing explictly not allowed. + # n>0 Quota is n pages. + + my $quotadir = shift; + my $user = shift; + my $acctQuota = -2; # A "no quota file found" error condition is the default. + + # First, look for a per-user quota. This quota has top priority. + my $quotaFile = ($quotadir,"/",$user,"_user_quota"); + if ( -e $quotaFile ) { + $acctQuota = read_quota_file($quotaFile); + } + + # If there is no user quota, look for a per-group quota for each group the user is in. + # The first one found is used. Otherwise, the default quota is still used. + if ( ! -e $quotaFile ) { + my ($name,$passwd,$gid,$members) = getgrent(); + + while ( length($name)>0 ) { + # This next line will allow me to use a simple pattern match. + my $testmembers = " " . $members . " "; + + if ( $testmembers =~ /\s$user\s/ ) { + my $testquotafile = $quotadir . "/" . $name . "_group_quota"; + my $testquota = read_quota_file($testquotafile); + + if ( $testquota == -1 ) { + $acctQuota = $testquota; + last; + } elsif ( $testquota > $acctQuota ) { + $acctQuota = $testquota; + } + } + + ($name,$passwd,$gid,$members) = getgrent(); + } + + # If no group quota was found either, use the default quota. + if ( length($name) == 0 ) { + $quotaFile = "$quotadir/print_quota"; + $acctQuota = read_quota_file($quotaFile); + } + } + + return $acctQuota; +} + + +sub read_quota_file { + # Arguments: file to read + # Returns: user's current quota + my $quotafile = shift; + my $quota = -2; # An error condition is the default + + open (FH, "$quotafile") or return ($quota); + while() { + $quota = $_; + } + close (FH); + + chomp($quota); # When editing files by hand, many people toss a newline in there. + + return ($quota); +} diff --git a/setcupsbroadcasting b/setcupsbroadcasting new file mode 100644 index 0000000..a880974 --- /dev/null +++ b/setcupsbroadcasting @@ -0,0 +1,185 @@ +#!/usr/bin/perl -w + +# +# Script to automatically restrict the printer information broadcasting the +# accepting of external broadcasts, and the access to the printers to local +# (eth?) networks +# + +# +# Till Kamppeter (till@mandrakesoft.com) +# +# Copyright 2000 MandrakeSoft +# +# This software may be freely redistributed under the terms of the GNU +# General Public License. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +# Do not do any changes during the installation + +if ($ENV{'DURING_INSTALL'}) {exit 0}; + +# Read CUPS config file + +my $cups_conf = "/etc/cups/cupsd.conf"; +if (!(-f $cups_conf)) {die "No CUPS configuration file $cups_conf!"}; +open CONF_CUPS, "$cups_conf" or die "Can't open $cups_conf!"; +my @cups_conf_content = ; +close CONF_CUPS; + +# If it contains at least one "BrowseAddress" line broadcasting is already +# configured and we are done, stop silently here. + +grep(/^\s*BrowseAddress[^:]/, @cups_conf_content) and exit 0; + +# Read the output of "ifconfig" to look for local networks + +my $dev_is_localnet = 0; +my @local_networks = (); +my @local_bcasts = (); +my $current_ip = ""; +my $current_mask = ""; +my $current_bcast = ""; + +if (-x "/sbin/ifconfig") { + open IFCONFIG_OUT, "/sbin/ifconfig|" or die "Couldn't run \"ifconfig\"!"; + while (defined($readline = )) { + # New entry ... + if ($readline =~ /^(\S+)\s/) { + $dev = $1; + # ... for a local network? + if ($dev =~ /^eth/) {$dev_is_localnet = 1} + else {$dev_is_localnet = 0}; + # delete previous network data + $current_ip = ""; + $current_mask = ""; + $current_bcast = ""; + } + # Are we in an entry for a local network? + if ($dev_is_localnet == 1) { + # Are we in the important line now? + if ($readline =~ /\sinet addr:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s/) { + # Rip out the network addresses + if ($readline =~ /\sinet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) { + $current_ip = $1; + } + if ($readline =~ /\sBcast:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) { + $current_bcast = $1; + } + if ($readline =~ /\sMask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) { + $current_mask = $1; + } + # Is the entry valid? + if (($current_ip ne "") and ($current_mask ne "")) { + # Is there a broadcast address? + if ($current_bcast eq "") {$current_bcast = $current_ip}; + # Store broadcast address (or current IP if there is none) + push @local_bcasts, $current_bcast; + # Calculate mask fore access restriction + $current_ip =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + ($i1, $i2, $i3, $i4) = ($1, $2, $3, $4); + $current_mask =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/; + ($m1, $m2, $m3, $m4) = ($1, $2, $3, $4); + $current_net = ""; + if ($m1 eq "255") {$current_net = "${current_net}${i1}\."}; + if ($m2 eq "255") {$current_net = "$current_net$i2."}; + if ($m3 eq "255") {$current_net = "$current_net$i3."}; + if ($m4 eq "255") {$current_net = "$current_net$i4"} + else {$current_net = "$current_net*"}; + # Store mask + push @local_networks, $current_net; + } + } + } + } + close(IFCONFIG_OUT); +} + +# Remove all valid "BrowseAddress" lines +($_ =~ /^\s*BrowseAddress[^:]/ and $_="") foreach @cups_conf_content; + +# Insert the new "BrowseAddress" lines +(push @cups_conf_content, "BrowseAddress $_\n") foreach @local_bcasts; + +# Delete all "BrowseOrder", "BrowseAllow" and "BrowseDeny" lines from the file + +($_ =~ /^\s*BrowseOrder/ and $_="") foreach @cups_conf_content; +($_ =~ /^\s*BrowseAllow/ and $_="") foreach @cups_conf_content; +($_ =~ /^\s*BrowseDeny/ and $_="") foreach @cups_conf_content; + +# Add the new "BrowseOrder" and "BrowseDeny" lines + +push(@cups_conf_content,"BrowseOrder Deny,Allow\n"); +push(@cups_conf_content,"BrowseDeny All\n"); + +# Add a "BrowseAllow" line for every local network + +(push(@cups_conf_content,"BrowseAllow $_\n")) foreach @local_networks; + +# Cut out the root location block +# +# +# ... +# +# +# so that it can be treated seperately without affecting the rest of the +# file + +if (grep(m!^\s*!, @cups_conf_content)) { + $root_location_start = -1; + $root_location_end = -1; + # Go through all the lines, bail out when start and end line found + for ($i = 0; + ($i <= $#cups_conf_content) and ($root_location_end == -1); + $i++) { + if ($cups_conf_content[$i] =~ m!^\s*<\s*Location\s+/\s*>!) { + # Start line of block + $root_location_start = $i; + } elsif (($cups_conf_content[$i] =~ m!^\s*<\s*/Location\s*>!) and + ($root_location_start != -1)) { + # End line of block + $root_location_end = $i; + } + } + # Rip out the block and store it seperately + @root_location = + splice(@cups_conf_content,$root_location_start, + $root_location_end - $root_location_start + 1); +} else { + # If there is no root location block, create one + $root_location_start = $#cups_conf_content + 1; + @root_location = (); + push @root_location, "\n"; + push @root_location, "\n"; +} + +# Delete all former "Order", "Allow", and "Deny" lines from the root location +# block + +($_ =~ /^\s*Order/ and $_="") foreach @root_location; +($_ =~ /^\s*Allow/ and $_="") foreach @root_location; +($_ =~ /^\s*Deny/ and $_="") foreach @root_location; + +# Add the new "Order" and "Deny" lines + +splice(@root_location,-1,0,"Order Deny,Allow\n"); +splice(@root_location,-1,0,"Deny From All\n"); +splice(@root_location,-1,0,"Allow From 127.0.0.1\n"); + +# Add an "Allow" line for every local network + +(splice(@root_location,-1,0,"Allow From $_\n")) foreach @local_networks; + +# Put the changed root location block back into the file + +splice(@cups_conf_content,$root_location_start,0,@root_location); + +# Write back the modified CUPS config file + +open CONF_CUPS, ">$cups_conf" or die "Can't open $cups_conf"; +print CONF_CUPS @cups_conf_content; +close CONF_CUPS;