From abda923b27c34763d7432d4c4c8e489a9da3d541 Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Mon, 28 Sep 2009 16:53:26 +0000 Subject: [PATCH] - Reimplemented PPD upgrade script in Python to avoid perl dependency (bug #524978). --- cups-genppdupdate.py.in | 1058 +++++++++++++++++++++++++++++++++++++++ gutenprint.spec | 9 +- 2 files changed, 1066 insertions(+), 1 deletion(-) create mode 100755 cups-genppdupdate.py.in diff --git a/cups-genppdupdate.py.in b/cups-genppdupdate.py.in new file mode 100755 index 0000000..e01a322 --- /dev/null +++ b/cups-genppdupdate.py.in @@ -0,0 +1,1058 @@ +#!/usr/bin/python +# $Id$ +# Update CUPS PPDs for Gutenprint queues. +# Copyright (C) 2002-2003 Roger Leigh (rleigh@debian.org) +# Copyright (C) 2009 Red Hat, Inc. +# +# 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, 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. + +import getopt +import glob +import os +import re +import stat +import subprocess +import sys + +global optargs +global debug +global verbose +global interactive +global quiet +global no_action +global reset_defaults +global version +global micro_version +global use_static_ppd +global file_version + +global ppd_dir +global ppd_root_dir +global ppd_base_dir +global ppd_out_dir +global gzext +global updated_ppd_count +global skipped_ppd_count +global failed_ppd_count +global exit_after_parse_args +global languages + +global serverdir +global driver_bin +global driver_version +global server_multicat +global server_multicat_initialized + +global ppd_files +global languagemappings + +def help(): + print """ +Usage: %s [OPTION]... [PPD_FILE]... +Update CUPS+Gutenprint PPD files. + + -d flags Enable debugging + -h Display this help text + -n No-action. Don't overwrite any PPD files. + -q Quiet mode. No messages except errors. + -s ppd_dir Use ppd_dir as the source PPD directory. + -p ppd_dir Update PPD files in ppd_dir. + -P driver Use the specified driver binary to generate PPD files. + -v Verbose messages. + -N Reset options to defaults. + -o out_dir Output PPD files to out_dir. + -r version Use PPD files for Gutenprint major.minor version. + -f Ignore new PPD file safety checks. + -i Prompt (interactively) for each PPD file. + -l language Language choice (Gutenprint 5.1 or below). + Choices: %s + Or -loriginal to preserve original language + with Gutenprint 5.2 or above +""" % (sys.argv[0], + reduce (lambda x,y: "%s %s" % (x,y), languages)) + sys.exit (0) + +def die_if_not_directory (dir): + try: + st = os.stat (dir) + if not st.S_ISDIR (st.st_mode): + os.chdir (dir) + except OSError, (e, s): + print "%s: invalid directory: %s" % (dir, s) + sys.exit (1) + +def get_driver_version(): + global server_multicat + global driver_version + + def run_with_arg (arg): + try: + p = subprocess.Popen ([driver_bin, arg], + stdin=file("/dev/null"), + stdout=subprocess.PIPE, + stderr=file("/dev/null", "w"), + shell=False) + (stdout, stderr) = p.communicate () + except OSError: + return None + + return stdout + + stdout = run_with_arg ("org.gutenprint.extensions") + if stdout == None: + return + for line in stdout.split ("\n"): + if line == "org.gutenprint.multicat": + server_multicat = 1 + break + + stdout = run_with_arg ("VERSION") + if stdout == None: + return + + driver_version = stdout.strip () + +def parse_options(): + try: + opts, args = getopt.getopt (sys.argv[1:], "d:hnqs:vNo:p:P:r:ifl:") + except getopt.GetoptError: + help () + + global optargs + global debug + global verbose + global interactive + global quiet + global no_action + global reset_defaults + global version + global micro_version + global use_static_ppd + global file_version + global ppd_dir + global ppd_out_dir + global ppd_base_dir + global ppd_root_dir + global serverdir + global driver_bin + global driver_version + global server_multicat + global languages + optargs = dict() + for opt, optarg in opts: + optargs[opt[1]] = optarg + + if optargs.has_key ('n'): + no_action = 1 + + if optargs.has_key ('d'): + try: + debug = int (optargs['d']) + except ValueError: + d = 0 + + if optargs.has_key ('v'): + verbose = 1 + quiet = 0 + + if optargs.has_key ('q'): + verbose = 0 + quiet = 1 + + if optargs.has_key ('N'): + reset_defaults = 1 + + if optargs.has_key ('o'): + opt_o = optargs['o'] + die_if_not_directory (opt_o) + ppd_out_dir = opt_o + + if optargs.has_key ('r'): + opt_r = optargs['r'] + if version != opt_r: + version = opt_r + if optargs.has_key ('s'): + opt_s = optargs['s'] + die_if_not_directory (opt_s) + ppd_base_dir = opt_s + driver_bin = "" + server_multicat = 0 + use_static_ppd = "yes" + else: + ppd_base_dir = ppd_root_dir + "/gutenprint/" + version + driver_bin = serverdir + "/driver/gutenprint." + version + + driver_version = "" + # If user specifies version, we're not going to be able to check + # for an exact match. + file_version = '"' + version + if os.access (driver_bin, os.X_OK): + get_driver_version () + use_static_ppd = "no" + file_version = "\"%s\"$" % driver_version + else: + print "Gutenprint %s does not appear to be installed!" % version + sys.exit (1) + + if optargs.has_key ('s'): + opt_s = optargs['s'] + die_if_not_directory (opt_s) + ppd_base_dir = opt_s + driver_bin = "" + server_multicat = 0 + driver_version = "" + use_static_ppd = "yes" + + if optargs.has_key ('p'): + opt_p = optargs['p'] + die_if_not_directory (opt_p) + ppd_dir = opt_p + + if optargs.has_key ('P'): + opt_P = optargs['P'] + if os.access (opt_P, os.X_OK): + driver_bin = opt_P + get_driver_version () + use_static_ppd = "no" + else: + print "%s: invalid executable" % opt_P + + if optargs.has_key ('h'): + help () + + if (optargs.has_key ('l') and + optargs['l'].lower () != "original" and + optargs['l'].lower () not in languages): + print >>sys.stderr, "Unknown language '%s'" % optargs['l'] + + if optargs.has_key ('i'): + interactive = 1 + + if exit_after_parse_args: + sys.exit (0) + + if verbose and driver_version != "": + print "Updating PPD files from Gutenprint %s" % driver_version + + return args + +def update_ppd (ppd_source_filename): + global ppd_dest_filename + global ppd_out_dir + global optargs + global languagemappings + global interactive + global server_multicat + global no_action + global quiet, verbose + global reset_defaults + + ppd_dest_filename = ppd_source_filename + if ppd_out_dir: + ppd_dest_filename = "%s/%s" % (ppd_out_dir, + os.path.basename (ppd_dest_filename)) + + orig = file (ppd_source_filename) + orig_metadata = os.fstat (orig.fileno ()) + if debug & 1: + print "Source Filename: %s" % ppd_source_filename + + filename = "" + driver = "" + gutenprintdriver = "" + locale = "" + lingo = "" + region = "" + valid = 0 + orig_locale = "" + for line in orig.readlines (): + line.rstrip () + if line.find ("*StpLocale:") != -1: + match = re.search ("\*StpLocale:\s*\"(.*)\"$", line) + if match: + groups = match.groups () + if len (groups) >= 1: + locale = groups[0] + orig_locale = locale + valid = 1 + elif line.startswith ("*LanguageVersion"): + match = re.search ("^\*LanguageVersion:\s*(.*)$", line) + if match: + groups = match.groups () + if len (groups) >= 1: + lingo = groups[0] + elif line.startswith ("*StpDriverName:"): + match = re.search ("^\*StpDriverName:\s*\"(.*)\"$", line) + if match: + groups = match.groups () + if len (groups) >= 1: + driver = groups[0] + valid = 1 + elif line.find ("*%End of ") != -1 and driver == "": + match = re.search ("^\*%End of\s*(.*).ppd$", line) + if match: + groups = match.groups () + if len (groups) >= 1: + driver = groups[0] + elif line.startswith ("*StpPPDLocation:"): + match = re.search ("^\*StpPPDLocation:\s*\"(.*)\"$", line) + if match: + groups = match.groups () + if len (groups) >= 1: + filename = groups[0] + valid = 1 + elif line.startswith ("*%Gutenprint Filename:"): + valid = 1 + + if filename and driver and lingo and locale: + break + + if not valid and line.startswith ("*OpenUI"): + break + + if not valid: + #print >>sys.stderr, ("Skipping %s: not a Gutenprint PPD file" % + # ppd_source_filename) + return -1 + + if (optargs.has_key ('l') and + optargs['l'] != "" and + optargs['l'].lower () != "original"): + locale = optargs['l'] + orig_locale = locale + + if debug & 2: + print "Gutenprint Filename: %s" % filename + if optargs.has_key ('l'): + print "Locale: %s (from -l)" % locale + else: + print "Locale: %s" % locale + + print "Language: %s" % lingo + print "Driver: %s" % driver + + if locale: + # Split into the language and territory. + s = locale.split ("_", 1) + locale = s[0] + try: + region = s[1] + except IndexError: + region = "" + else: + # Split into the language and territory. + s = lingo.split ("_", 1) + locale = s[0] + try: + region = s[1] + except IndexError: + region = "" + + # Convert language into language code. + locale = languagemappings.get (lingo.lower (), "C") + + if debug & 2: + print "Base Locale: %s" % locale + print "Region: %s" % region + + # Read in the new PPD, decompressing it if needed... + (new_ppd_filename, source_fd) = get_ppd_fh (ppd_source_filename, + filename, + driver, + locale, + region) + if source_fd == None: + print "Unable to retrieve PPD file!" + return 0 + + if interactive: + inp = raw_input ("Update PPD %s from %s [nyq]? " % ppd_source_filename) + inp = inp.lower () + if inp.startswith ("q"): + if not server_multicat: + source_fd.close () + + print "Skipping all..." + return -2 + elif not inp.startswith ("y"): + if not server_multicat: + source_fd.close () + + print "Skipping..." + return -1 + + # Extract the default values from the original PPD... + + orig.seek (0) + (odt, oopt, ores, odef, unused) = get_ppd_data (orig, 1, 0, 1, 1, 0) + (ndt, nopt, nres, ndef, source_data) = get_ppd_data (source_fd, + 1, 1, 1, 1, 1) + + # Close original and temporary files... + + orig.close () + if not server_multicat: + source_fd.close () + + orig_default_types = odt + new_default_types = ndt + defaults = odef + new_defaults = ndef + options = nopt + resolution_map = nres + old_resolution_map = dict() + for key, value in resolution_map.iteritems (): + old_resolution_map[value] = key + + # Store previous language in the PPD file so that -l original works + # correctly. + + if orig_locale != "": + lines = source_data.rstrip ().split ("\n") + source_data = "" + for line in lines: + m = re.search ("(\*StpLocale:\s*\")(.*)(\")", line) + if m: + groups = m.groups () + line = groups[0] + orig_locale + groups[2] + + source_data += line + "\n" + + if debug & 4: + print "Options (Old->New Default Type):" + keys = options.keys () + keys.sort () + for t in keys: + old_type = orig_default_types.get (t, "(New)") + new_type = new_default_types.get (t) + if old_type != new_type: + out = " %s (%s -> %s) : " % (t, old_type, new_type) + else: + out = " %s (%s) : " % (t, new_type) + + dft = defaults.get ("Default%s" % t) + for opt in options.get (t, []): + if dft != None and dft == opt: + out += "*" + + out += "%s " % opt + + print out + + if len (resolution_map.keys ()) > 0: + print "Resolution Map:" + keys = resolution_map.keys () + keys.sort () + for key in keys: + print " %s: %s" % (key, resolution_map[key]) + + if len (old_resolution_map.keys ()) > 0: + print "Old Resolution Map:" + keys = old_resolution_map.keys () + keys.sort () + for key in keys: + print " %s: %s" % (key, old_resolution_map[key]) + + print "Non-UI Defaults:" + keys = defaults.keys () + keys.sort () + for key in keys: + xkey = key + if xkey.startswith ("Default"): + xkey = xkey[7:] + if not options.has_key (xkey): + print " %s: %s" % (key, defaults[key]) + + print "Default Types of dropped options:" + keys = orig_default_types.keys () + keys.sort () + for t in keys: + if not options.has_key (t): + print " %s: %s" % (t, orig_default_types[t]) + + if no_action: + if not quiet or verbose: + if ppd_dest_filename == ppd_source_filename: + print "Would update %s using %s" % (ppd_source_filename, + new_ppd_filename) + else: + print "Would update %s to %s using %s" % (ppd_source_filename, + ppd_dest_filename, + new_ppd_filename) + + return 0 + + if not reset_defaults: + # Update source buffer with old defaults... + + # Loop through each default in turn. + keys = defaults.keys () + keys.sort () + for default_option in keys: + default_option_value = defaults[default_option] + option = default_option + if option.startswith ("Default"): + # Strip off `Default' + option = option[7:] + + # Check method is valid + orig_method = orig_default_types.get (option) + new_method = new_default_types.get (option) + new_default = new_defaults.get (default_option) + if (orig_method == None or new_method == None or + orig_method != new_method): + continue + + if (new_default != None and + default_option_value == new_default): + if verbose: + print "%s: Preserve *%s (%s)" % (ppd_source_filename, + default_option, + default_option_value) + + continue + + if new_method == "PickOne": + next_default = False + + # Check the old setting is valid + for opt in options.get (option, []): + def_option = default_option_value + odef_option = def_option + if (option == "Resolution" and + old_resolution_map.has_key (def_option)): + if debug & 4: + print ("Intermapping old resolution %s to %s" % + def_option, old_resolution_map[def_option]) + + def_option = old_resolution_map[def_option] + + dopts = [def_option] + if def_option != odef_option: + dopts.append (odef_option) + + for dopt in dopts: + valid = False + if dopt == opt: + valid = True + elif (option == "Resolution" and + resolution_map.has_key (dopt)): + dopt = resolution_map[dopt] + if dopt == opt: + valid = True + + if valid: + # Valid option + + # Set the option in the new PPD + lines = source_data.rstrip ().split ("\n") + source_data = "" + attr = "*%s" % default_option + for line in lines: + if line.startswith (attr): + line = "%s:%s" % (attr, dopt) + + source_data += line + "\n" + + if verbose: + print "%s: Set *%s to %s" % (ppd_source_filename, + default_option, + dopt) + + next_default = True + break + if next_default: + break + + if next_default: + continue + + print ("Warning: %s: Invalid option: *%s: %s. Using default " + "setting %s." % (ppd_source_filename, default_option, + defaults[default_option], + new_defaults[default_option])) + continue + + print ("Warning: %s: PPD OpenUI method %s not understood." % + (ppd_source_filename, new_default_types[default_option])) + + # Write new PPD... + tmpnew = "%s.new" % ppd_dest_filename + try: + newppd = file (tmpnew, "w") + except IOError, (e, s): + print "Can't create %s: %s" % (tmpnew, s) + return 0 + + newppd.writelines (source_data) + try: + newppd.close () + except IOError, (e, s): + print "Can't write to %s: %s" % (tmpnew, s) + return 0 + + chcon = subprocess.Popen (["chcon", "--reference=%s" % ppd_dest_filename, + tmpnew], shell=False, + stdin=file("/dev/null"), + stdout=file("/dev/null", "w"), + stderr=subprocess.STDOUT) + chcon.communicate () + + try: + os.rename (tmpnew, ppd_dest_filename) + except OSError, (e, s): + print "Can't rename %s to %s: %s" % (tmpnew, ppd_dest_filename, s) + try: + os.unlink (tmpnew) + except OSError: + pass + + return 0 + + try: + os.chown (ppd_dest_filename, + orig_metadata.st_uid, + orig_metadata.st_gid) + except OSError: + pass + + try: + os.chmod (ppd_dest_filename, + orig_metadata.st_mode & 0777) + except OSError: + pass + + if not quiet or verbose: + if ppd_dest_filename == ppd_source_filename: + print "Updated %s using %s" % (ppd_source_filename, + new_ppd_filename) + else: + print "Updated %s to %s using %s" % (ppd_source_filename, + ppd_dest_filename, + new_ppd_filename) + + # All done! + return 1 + +def get_ppd_data (fh, types, opts, resolutions, defaults, data): + options_map = dict() + defaults_map = dict() + resolution_map = dict() + default_types = dict() + cur_opt = "" + optionlist = [] + source_data = "" + + if reset_defaults: + types = 0 + opts = 0 + resolutions = 0 + defaults = 0 + + if resolutions or types or opts or defaults or data: + while True: + line = fh.readline () + if line == '': + break + if line == "*%*%EOFEOF\n": + break + source_data += line + line = line.strip () + + if (types or opts) and line.startswith ("*OpenUI"): + m = re.search ("^\*OpenUI\s\*(\w+).*:\s(\w+)", + line) + if m: + groups = m.groups () + key = groups[0] + value = groups[1] + default_types[key] = value + cur_opt = key + elif opts and line.startswith ("*CloseUI"): + if cur_opt != "": + options_map[cur_opt] = optionlist + cur_opt = "" + + optionlist = [] + elif opts and line.startswith ("*%s" % cur_opt): + m = re.search ("^\*%s\s*(\w+)[\/:]" % cur_opt, line) + if m: + groups = m.groups() + if len (groups) >= 1: + value = m.groups ()[0] + optionlist.append (value) + elif resolutions and line.startswith ("*StpResolutionMap:"): + s = line.split (None, 3) + if len (s) == 3: + new = s[1] + old = s[2] + resolution_map[old] = new + elif defaults and line.startswith ("*Default"): + m = re.search ("^\*(\w+):\s*(\w+)", line) + if m: + groups = m.groups () + key = groups[0] + value = groups[1] + defaults_map[key] = value + + return (default_types, options_map, resolution_map, + defaults_map, source_data) + +def get_ppd_fh (ppd_source_filename, filename, driver, locale, region): + global use_static_ppd + global driver_version + global optargs + global driver_bin + global debug + global server_multicat, server_multicat_initialized + global gzext + + if use_static_ppd == "no" and driver_version != "": + if re.search (".*/([^/]*)(.sim)(.ppd)?(.gz)?$", filename): + simplified = "simple" + else: + simplified = "expert" + + opt_r = optargs.get ('r') + if opt_r: + try: + opt_r = float (opt_r) + except ValueError: + opt_r = None + + url_list = [] + if (((opt_r != None and opt_r < 5.2) or + (optargs.has_key ('l') and optargs['l'] != "")) and + locale != ""): + if region: + url_list.append ("gutenprint.%s://%s/%s/%s_%s" % + version, driver, simplified, locale, region) + url_list.append ("gutenprint.%s://%s/%s/%s" % + version, driver, simplified, locale) + + url_list.append ("gutenprint.%s://%s/%s" % (version, driver, + simplified)) + for url in url_list: + new_ppd_filename = url + if debug & 8: + if server_multicat: + cat = "" + else: + cat = "%s cat " % driver_bin + + print ("Trying %s%s for %s, %s, %s, %s" % + (cat, url, driver, simplified, locale, region)) + + if server_multicat: + try: + if not server_multicat_initialized: + mc_proc = subprocess.Popen ([driver_bin, + "org.gutenprint.multicat"], + shell=False, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=file("/dev/null", + "w")) + server_multicat_initialized = mc_proc + + print >>server_multicat_initialized.stdin, "%s\n" % url + server_multicat_initialized.stdin.flush () + return (new_ppd_filename, + server_multicat_initialized.stdout) + except OSError: + pass + + try: + proc = subprocess.Popen ([driver_bin, "cat", url], + shell=False, + stdin=file("/dev/null"), + stdout=subprocess.PIPE, + stderr=file("/dev/null", "w")) + return (new_ppd_filename, proc.stdout) + except OSError: + pass + + # Otherwise fall through and try to find a static PPD + + # Search for a PPD matching our criteria... + + new_ppd_filename = find_ppd (filename, driver, locale, region) + if not new_ppd_filename: + # There wasn't a valid source PPD file, so give up. + print >>sys.stderr, ("%s: no valid candidate for replacement. " + "Skipping" % ppd_source_filename) + print >>sys.stderr, ("%s: please upgrade this PPD manually" % + ppd_source_filename) + return ("", None) + + if debug & 1: + print "Candidate PPD: %s" % new_ppd_filename + + suffix = "\\" + gzext # Add '\' so the regexp matches the '.' + if new_ppd_filename.endswith (".gz"): + # Decompress input buffer + try: + proc = subprocess.Popen (['gunzip', '-c', new_ppd_filename], + shell=False, + stdin=file("/dev/null"), + stdout=subprocess.PIPE, + stderr=file("/dev/null", "w")) + except OSError, (e, s): + print "can't open for decompression: %s" % s + sys.exit (1) + + return (new_ppd_filename, proc.stdout) + else: + return (new_ppd_filename, file (new_ppd_filename)) + +def find_ppd (gutenprintfilename, drivername, lang, region): + global file_version + global optargs + global ppd_base_dir + global ppd_root_dir + global debug + + key = '^\\*FileVersion:[ ]*' + file_version + match = re.search (".*/([^/]+\.[0-9]+\.[0-9]+)(\.sim)?(\.ppd)?(\.gz)?$", + gutenprintfilename) + if not match: + return None + + stored_name = match.groups ()[0] + if re.search (".*/([^/]*)(\.sim)(\.ppd)?(\.gz)?$", gutenprintfilename): + simplified = ".sim" + else: + simplified = "" + + stored_dir = os.path.dirname (gutenprintfilename) + + current_best_file = "" + current_best_time = 0 + if optargs.has_key ('s'): + basedirs = [optargs['s']] + else: + basedirs = [ppd_base_dir, stored_dir, ppd_root_dir] + + lingos = [] + if region != "": + lingos.append ("%s_%s/" % (lang, region)) + + lingos.append ("%s/" % lang) + if lang != "C": + lingos.append ("C/") + + lingos.append ("en/") + lingos.append ("") + lingos.append ("Global/") + bases = ["stp-%s.%s%s" % (drivername, version, simplified), + "%s.%s%s" % (drivername, version, simplified)] + if stored_name not in bases: + bases.append (stored_name) + + bases.append (drivername) + + # All possible candidates, in order of usefulness and gzippedness + for lingo in lingos: + for suffix in (".ppd%s" % gzext, + ".ppd"): + for base in bases: + for basedir in basedirs: + if basedir == "" or base == "": + continue + + fn = "%s/%s%s%s" % (basedir, lingo, base, suffix) + if debug & 8: + print ("Trying %s for %s, %s, %s" % + (fn, gutenprintfilename, lang, region)) + + try: + st = os.stat (fn) + except OSError: + continue + + if (optargs.has_key ('f') or + (stat.S_ISREG (st.st_mode) and + st.st_uid == 0)): + # Check that the file is a valid Gutenprint PPD file + # of the correct version. + if fn.endswith (".gz"): + cmdline = "gunzip -c '%s' | grep '%s'" % (fn, key) + else: + cmdline = "cat '%s' | grep '%s'" % (fn, key) + + try: + p = subprocess.Popen (cmdline, + stdin=file("/dev/null"), + stdout=subprocess.PIPE, + stderr=file("/dev/null", "w")) + except OSError: + new_file_version = "" + else: + (stdin, stderr) = p.communicate () + new_file_version = stdin.rstrip () + + if new_file_version != "": + if debug & 8: + print (" Format valid: time %s best %s " + "prev %s cur %s!" % + (st.st_mtime, current_best_time, + current_best_file, fn)) + + if st.st_mtime > current_best_time: + current_best_time = st.st_mtime + current_best_file = fn + if debug & 8: + print >>sys.stderr, ("***current_best_file " + " is %s" % fn) + elif debug & 8: + print " Format invalid" + else: + if (not stat.S_ISDIR (st.st_mode) and + not fn.endswith ("/")): + print >>sys.stderr, ("%s: not a regular file, " + "or insecure ownership and " + "permissions. Skipped" % fn) + + if current_best_file: + return current_best_file + + # Yikes! Cannot find a valid PPD file! + return None + +debug=0 +verbose=0 +interactive=0 +quiet=0 +no_action=0 +reset_defaults=0 +version="@GUTENPRINT_MAJOR_VERSION@.@GUTENPRINT_MINOR_VERSION@" +micro_version="@GUTENPRINT_VERSION@" +use_static_ppd="@BUILD_CUPS_PPDS@" +file_version='"@VERSION@"$' + +ppd_dir = "@cups_conf_serverroot@/ppd" +ppd_root_dir = "@cups_conf_datadir@/model"; +ppd_base_dir = ppd_root_dir + "/gutenprint/" + version +ppd_out_dir = "" +gzext = ".gz" +updated_ppd_count = 0 +skipped_ppd_count = 0 +failed_ppd_count = 0 +exit_after_parse_args = 0 +languages=["Global", "C"] + "@ALL_LINGUAS@".split (' ') + +serverdir = "@cups_conf_serverbin@" +driver_bin = serverdir + "/driver/gutenprint." + version +driver_version = "" +server_multicat = 0 +server_multicat_initialized = 0 + +if os.access (driver_bin, os.X_OK): + get_driver_version () + +ppd_files = [] +languagemappings = { "chinese": "cn", + "danish": "da", + "dutch": "nl", + "english": "en", + "finnish": "fi", + "french": "fr", + "german": "de", + "greek": "el", + "hungarian": "hu", + "italian": "it", + "japanese": "jp", + "norwegian": "no", + "polish": "pl", + "portuguese": "pt", + "russian": "ru", + "slovak": "sk", + "spanish": "es", + "swedish": "sv", + "turkish": "tr" } + +# Check command-line options... +args = parse_options() + +# Set a secure umask... +os.umask (0177) + + +# Find all in-use Gutenprint PPD files... +# For case-insensitive filesystems, use only one of .ppd and .PPD +# (bug 1929738) + +for f in args: + if (os.access (f, os.F_OK) and + (f.lower ().endswith (".ppd") or + f.find ("/") != -1)): + ppd_files.append (f) + elif os.access ("%s/%s" % (ppd_dir, f), os.F_OK): + ppd_files.append ("%s/%s" % (ppd_dir, f)) + elif os.access ("%s/%s.ppd" % (ppd_dir, f), os.F_OK): + ppd_files.append ("%s/%s.ppd" % (ppd_dir, f)) + elif os.access ("%s/%s.PPD" % (ppd_dir, f), os.F_OK): + ppd_files.append ("%s/%s.PPD" % (ppd_dir, f)) + else: + print >>sys.stderr, ("Cannot find file %s/%s, %s/%s.ppd, or %s/%s.PPD" % + ppd_dir, f, ppd_dir, f, ppd_dir, f) + +if len (args) == 0: + ppdtmp = glob.glob ("%s/*.ppd" % ppd_dir) + ppdtmp += glob.glob ("%s/*.PPD" % ppd_dir) + ppd_map = dict() + for each in ppdtmp: + ppd_map[each] = 1 + + for f in ppdtmp: + if f.endswith (".PPD"): + g = f[:-4] + ".ppd" + if not ppd_map.has_key (g): + ppd_files.append (f) + else: + ppd_files.append (f) + +# Update each of the Gutenprint PPDs, where possible... + +for ppd_file in ppd_files: + status = update_ppd (ppd_file) + if status == -2: + break + elif status == 0: + failed_ppd_count += 1 + elif status == 1: + updated_ppd_count += 1 + elif status == -1: + skipped_ppd_count += 1 + +if (not quiet) or verbose: + if len (ppd_files) == 0: + print "No Gutenprint PPD files to update." + elif updated_ppd_count > 0: + plural = "" + if updated_ppd_count != 1: + plural = "s" + + print "Updated %d PPD file%s" % (updated_ppd_count, plural) + if ((not optargs.has_key ('o')) or + optargs['o'] != ""): + print "Restart cupsd for the changes to take effect." + else: + if failed_ppd_count > 0: + print "Failed to update any PPD files" + else: + print "Did not update any PPD files" + +sys.exit (failed_ppd_count > 0) diff --git a/gutenprint.spec b/gutenprint.spec index 4b49e32..e0c05be 100644 --- a/gutenprint.spec +++ b/gutenprint.spec @@ -4,11 +4,12 @@ Name: gutenprint Summary: Printer Drivers Package. Version: 5.2.4 -Release: 5%{?dist} +Release: 6%{?dist} Group: System Environment/Base URL: http://gimp-print.sourceforge.net/ Source0: http://dl.sf.net/gimp-print/gutenprint-%{version}.tar.bz2 Source1: gutenprint-foomaticppdupdate +Source2: cups-genppdupdate.py.in Patch0: gutenprint-menu.patch Patch1: gutenprint-O6.patch Patch2: gutenprint-selinux.patch @@ -139,6 +140,8 @@ Epson, HP and compatible printers. %patch2 -p1 -b .selinux %patch3 -p1 -b .deviceid +cp %{SOURCE2} src/cups/cups-genppdupdate.in + %build %configure --disable-static --disable-dependency-tracking \ --with-foomatic --with-ghostscript \ @@ -264,6 +267,10 @@ fi /bin/rm -f /var/cache/foomatic/* %changelog +* Mon Sep 28 2009 Tim Waugh 5.2.4-6 +- Reimplemented PPD upgrade script in Python to avoid perl + dependency (bug #524978). + * Tue Sep 1 2009 Tim Waugh 5.2.4-5 - Provide IEEE 1284 Device IDs in CUPS model list.