diff options
author | CoprDistGit <infra@openeuler.org> | 2025-03-24 13:58:49 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2025-03-24 13:58:49 +0000 |
commit | a0749a3273bba247e73c7c620d97ba2d77ad5e40 (patch) | |
tree | f3be6f61b155227d5efa52c8696253e0eb9c3176 | |
parent | f2f443387aa1f754263a00c8664563817ac14b8e (diff) |
automatic import of gutenprintopeneuler24.03_LTS
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | cups-genppdupdate.py.in | 1106 | ||||
-rw-r--r-- | gutenprint-manpage.patch | 27 | ||||
-rw-r--r-- | gutenprint-menu.patch | 11 | ||||
-rw-r--r-- | gutenprint-postscriptdriver.patch | 98 | ||||
-rw-r--r-- | gutenprint-yyin.patch | 26 | ||||
-rw-r--r-- | gutenprint.spec | 159 | ||||
-rw-r--r-- | sources | 1 |
8 files changed, 1429 insertions, 0 deletions
@@ -0,0 +1 @@ +/gutenprint-5.3.5.tar.xz diff --git a/cups-genppdupdate.py.in b/cups-genppdupdate.py.in new file mode 100755 index 0000000..1f9e350 --- /dev/null +++ b/cups-genppdupdate.py.in @@ -0,0 +1,1106 @@ +#!/usr/bin/python3 +# $Id$ +# Update CUPS PPDs for Gutenprint queues. +# Copyright (C) 2002-2003 Roger Leigh (rleigh@debian.org) +# Copyright (C) 2009, 2011, 2014 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 io +import os +import re +import stat +import subprocess +import sys +from functools import reduce + +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 stat.S_ISDIR (st.st_mode): + os.chdir (dir) + except OSError as err: + (e, s) = err.args + 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=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + shell=False) + (stdout, stderr) = p.communicate () + except OSError: + return None + + if stdout != None: + stdout = stdout.decode () + + 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 'n' in optargs: + no_action = 1 + + if 'd' in optargs: + try: + debug = int (optargs['d']) + except ValueError: + d = 0 + + if 'v' in optargs: + verbose = 1 + quiet = 0 + + if 'q' in optargs: + verbose = 0 + quiet = 1 + + if 'N' in optargs: + reset_defaults = 1 + + if 'o' in optargs: + opt_o = optargs['o'] + die_if_not_directory (opt_o) + ppd_out_dir = opt_o + + if 'r' in optargs: + opt_r = optargs['r'] + if version != opt_r: + version = opt_r + if 's' in optargs: + 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 's' in optargs: + 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 'p' in optargs: + opt_p = optargs['p'] + die_if_not_directory (opt_p) + ppd_dir = opt_p + + if 'P' in optargs: + 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 'h' in optargs: + help () + + if ('l' in optargs and + optargs['l'].lower () != "original" and + optargs['l'].lower () not in languages): + print ("Unknown language '%s'" % optargs['l'], file=sys.stderr) + + if 'i' in optargs: + 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 check_encoding(filename): + import charset_normalizer + + with open(filename, 'rb') as f: + charenc = charset_normalizer.detect(f.read())['encoding'] + + if debug & 1: + print("File encoding: {}".format(charenc)) + + if charenc in ['ascii', 'utf-8']: + return 'utf-8' + else: + if debug & 1: + print("Trying to use latin1 for decoding {}".format(charenc)) + + return 'latin1' + +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)) + + fenc = check_encoding(ppd_source_filename) + orig = open(ppd_source_filename, encoding=fenc) + 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 = "" + + try: + orig_lines = orig.readlines() + except UnicodeDecodeError: + if debug & 1: + print('PPD {} has an unexpected enconding, ' + 'skipping.'.format(ppd_source_filename)) + + return -1 + + for line in orig_lines: + line.rstrip () + if line.find ("*StpLocale:") != -1: + match = re.search (r'\*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 (r'^\*LanguageVersion:\s*(.*)$', line) + if match: + groups = match.groups () + if len (groups) >= 1: + lingo = groups[0] + elif line.startswith ("*StpDriverName:"): + match = re.search (r'^\*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 (r'^\*%End of\s*(.*).ppd$', line) + if match: + groups = match.groups () + if len (groups) >= 1: + driver = groups[0] + elif line.startswith ("*StpPPDLocation:"): + match = re.search (r'^\*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 (("Skipping %s: not a Gutenprint PPD file" % + # ppd_source_filename), file=sys.stderr) + return -1 + + if ('l' in optargs and + optargs['l'] != "" and + optargs['l'].lower () != "original"): + locale = optargs['l'] + orig_locale = locale + + if debug & 2: + print ("Gutenprint Filename: %s" % filename) + if 'l' in optargs: + 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 = input ("Update PPD %s from %s [nyq]? " % ppd_source_filename) + inp = inp.lower () + if inp.startswith ("q"): + if server_multicat: + source_fd.detach () + else: + source_fd.close () + + print ("Skipping all...") + return -2 + elif not inp.startswith ("y"): + if server_multicat: + source_fd.detach () + else: + 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 server_multicat: + source_fd.detach () + else: + 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.items (): + 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 (r'(\*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 = list(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 (list(resolution_map.keys ())) > 0: + print ("Resolution Map:") + keys = list(resolution_map.keys ()) + keys.sort () + for key in keys: + print (" %s: %s" % (key, resolution_map[key])) + + if len (list(old_resolution_map.keys ())) > 0: + print ("Old Resolution Map:") + keys = list(old_resolution_map.keys ()) + keys.sort () + for key in keys: + print (" %s: %s" % (key, old_resolution_map[key])) + + print ("Non-UI Defaults:") + keys = list(defaults.keys ()) + keys.sort () + for key in keys: + xkey = key + if xkey.startswith ("Default"): + xkey = xkey[7:] + if xkey not in options: + print (" %s: %s" % (key, defaults[key])) + + print ("Default Types of dropped options:") + keys = list(orig_default_types.keys ()) + keys.sort () + for t in keys: + if t not in options: + 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 = list(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 + def_option in old_resolution_map): + 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 + dopt in resolution_map): + 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 = open (tmpnew, "w") + except IOError as err: + (e, s) = err.args + print ("Can't create %s: %s" % (tmpnew, s)) + return 0 + + newppd.writelines (source_data) + try: + newppd.close () + except IOError as err: + (e, s) = err.args + print ("Can't write to %s: %s" % (tmpnew, s)) + return 0 + + chcon = subprocess.Popen (["chcon", "--reference=%s" % ppd_dest_filename, + tmpnew], shell=False, + stdin=subprocess.DEVNULL, + stdout=subprocess.DEVNULL, + stderr=subprocess.STDOUT) + chcon.communicate () + + try: + os.rename (tmpnew, ppd_dest_filename) + except OSError as err: + (e, s) = err.args + 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 & 0o777) + 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 (r'^\*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 (r'^\*%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 (r'^\*(\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 + ('l' in optargs 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=subprocess.DEVNULL) + server_multicat_initialized = mc_proc + + mc_in = io.TextIOWrapper (server_multicat_initialized.stdin) + print ("%s" % url, file=mc_in) + mc_in.flush () + mc_in.detach () + return (new_ppd_filename, + io.TextIOWrapper (server_multicat_initialized.stdout)) + except OSError: + pass + + try: + proc = subprocess.Popen ([driver_bin, "cat", url], + shell=False, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + return (new_ppd_filename, io.TextIOWrapper (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 (("%s: no valid candidate for replacement. Skipping" % + ppd_source_filename), file=sys.stderr) + print (("%s: please upgrade this PPD manually" % + ppd_source_filename), file=sys.stderr) + 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=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + except OSError as err: + (e, s) = err.args + print ("can't open for decompression: %s" % s) + sys.exit (1) + + return (new_ppd_filename, io.TextIOWrapper (proc.stdout)) + else: + return (new_ppd_filename, open (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 (r'.*/([^/]+\.[0-9]+\.[0-9]+)(\.sim)?(\.ppd)?(\.gz)?$', + gutenprintfilename) + if not match: + return None + + stored_name = match.groups ()[0] + if re.search (r'.*/([^/]*)(\.sim)(\.ppd)?(\.gz)?$', gutenprintfilename): + simplified = ".sim" + else: + simplified = "" + + stored_dir = os.path.dirname (gutenprintfilename) + + current_best_file = "" + current_best_time = 0 + if 's' in optargs: + 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 ('f' in optargs 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=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + except OSError: + new_file_version = "" + else: + (stdin, stderr) = p.communicate () + new_file_version = stdin.decode ().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 (("***current_best_file " + " is %s" % fn), file=sys.stderr) + elif debug & 8: + print (" Format invalid") + else: + if (not stat.S_ISDIR (st.st_mode) and + not fn.endswith ("/")): + print (("%s: not a regular file, " + "or insecure ownership and " + "permissions. Skipped" % fn), + file=sys.stderr) + + 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 (0o177) + + +# 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 (("Cannot find file %s/%s, %s/%s.ppd, or %s/%s.PPD" % + ppd_dir, f, ppd_dir, f, ppd_dir, f), file=sys.stderr) + +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 g not in ppd_map: + 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 (('o' not in optargs) 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-manpage.patch b/gutenprint-manpage.patch new file mode 100644 index 0000000..07689ad --- /dev/null +++ b/gutenprint-manpage.patch @@ -0,0 +1,27 @@ +diff -up gutenprint-5.2.9/man/escputil.1.in.manpage gutenprint-5.2.9/man/escputil.1.in +--- gutenprint-5.2.9/man/escputil.1.in.manpage 2013-06-27 15:02:09.997386927 +0100 ++++ gutenprint-5.2.9/man/escputil.1.in 2013-06-27 15:08:16.236046768 +0100 +@@ -20,6 +20,7 @@ escputil \- maintain Epson Stylus inkjet + .SH SYNOPSIS + .B escputil + [ \fI\-P\fP \fIprinter\fP | \fI\-r\fP \fIdevice\fP ] [ \fI\-m\fP \fImodel\fP ] [ ++\fI\-S\fP ] [ \fI\-C\fP ] [ \fI\-p\fP ] [ + \fI\-u\fP ] [ \fI\-c\fP | \fI\-n\fP | \fI\-a\fP | \fI\-i\fP | \fI\-d\fP | + \fI\-o\fP | \fI\-s\fP | \fI\-l\fP | \fI\-M\fP | \fI\-h\fP ] [ \fI\-q\fP ] + .SH DESCRIPTION +@@ -46,6 +47,15 @@ Specify the precise printer model for he + .B \-u, \-\-new + The printer is a new printer (Stylus Color 740 or newer). + .TP ++.B \-S, \-\-short\-name ++Print the short name of the printer with \-\-identify. ++.TP ++.B \-C, \-\-choices ++Specify the number of pattern choices for alignment. ++.TP ++.B \-p, \-\-patterns ++Specify the number of sets of patterns for alignment. ++.TP + .B \-c, \-\-clean\-head + Clean the print head. This can also be performed from the printer + front panel. diff --git a/gutenprint-menu.patch b/gutenprint-menu.patch new file mode 100644 index 0000000..2c76a41 --- /dev/null +++ b/gutenprint-menu.patch @@ -0,0 +1,11 @@ +--- gutenprint-5.0.0/src/gimp2/print-print.c.menu 2007-03-02 17:08:51.000000000 +0000 ++++ gutenprint-5.0.0/src/gimp2/print-print.c 2007-03-02 17:09:10.000000000 +0000 +@@ -43,7 +43,7 @@ + (BAD_CONST_CHAR) copy, + (BAD_CONST_CHAR) VERSION " - " RELEASE_DATE, + /* Do not translate the prefix "<Image>" */ +- (BAD_CONST_CHAR) N_("<Image>/File/Print..."), ++ (BAD_CONST_CHAR) N_("<Image>/File/Send/Print..."), + (BAD_CONST_CHAR) types, + GIMP_PLUGIN, + n_args, 0, diff --git a/gutenprint-postscriptdriver.patch b/gutenprint-postscriptdriver.patch new file mode 100644 index 0000000..d4b5ff7 --- /dev/null +++ b/gutenprint-postscriptdriver.patch @@ -0,0 +1,98 @@ +diff -up gutenprint-5.3.3/src/main/gutenprint-internal.h.postscriptdriver gutenprint-5.3.3/src/main/gutenprint-internal.h +--- gutenprint-5.3.3/src/main/gutenprint-internal.h.postscriptdriver 2018-01-28 03:32:45.000000000 +0100 ++++ gutenprint-5.3.3/src/main/gutenprint-internal.h 2019-11-06 12:13:29.936061606 +0100 +@@ -54,6 +54,8 @@ extern void stpi_init_printer(void); + #define BUFFER_FLAG_FLIP_X 0x1 + #define BUFFER_FLAG_FLIP_Y 0x2 + extern stp_image_t* stpi_buffer_image(stp_image_t* image, unsigned int flags); ++extern stp_list_t *stp_paths_copy_with_prefix(stp_list_t* list, ++ const char *prefix); + + #define STPI_ASSERT(x,v) \ + do \ +diff -up gutenprint-5.3.3/src/main/module.c.postscriptdriver gutenprint-5.3.3/src/main/module.c +--- gutenprint-5.3.3/src/main/module.c.postscriptdriver 2019-05-25 16:34:21.000000000 +0200 ++++ gutenprint-5.3.3/src/main/module.c 2019-11-06 12:13:29.936061606 +0100 +@@ -159,12 +159,20 @@ int stp_module_load(void) + } + else + { ++ const char *prefix = getenv("DESTDIR"); + #ifdef USE_LTDL + stp_path_split(dir_list, getenv("LTDL_LIBRARY_PATH")); + stp_path_split(dir_list, lt_dlgetsearchpath()); + #else + stp_path_split(dir_list, PKGMODULEDIR); + #endif ++ if (prefix) ++ { ++ stp_list_t *prefix_list; ++ prefix_list = stp_paths_copy_with_prefix(dir_list, prefix); ++ stp_list_destroy(dir_list); ++ dir_list = prefix_list; ++ } + } + #ifdef USE_LTDL + file_list = stp_path_search(dir_list, ".la"); +diff -up gutenprint-5.3.3/src/main/path.c.postscriptdriver gutenprint-5.3.3/src/main/path.c +--- gutenprint-5.3.3/src/main/path.c.postscriptdriver 2019-05-25 16:34:21.000000000 +0200 ++++ gutenprint-5.3.3/src/main/path.c 2019-11-06 12:29:30.709190171 +0100 +@@ -154,6 +154,17 @@ stp_generate_path(const char *path) + return NULL; + stp_list_set_freefunc(dir_list, stp_list_node_free_data); + stp_path_split(dir_list, path); ++ if (!strncmp(PKGXMLDATADIR, path, strlen(path))) ++ { ++ const char *prefix = getenv("DESTDIR"); ++ if (prefix) ++ { ++ stp_list_t *prefix_list; ++ prefix_list = stp_paths_copy_with_prefix(dir_list, prefix); ++ stp_list_destroy(dir_list); ++ dir_list = prefix_list; ++ } ++ } + return dir_list; + } + +@@ -262,6 +273,40 @@ stp_path_split(stp_list_t *list, /* List + } + } + ++/* ++ * Split a PATH-type string (colon-delimited) into separate ++ * directories. ++ */ ++stp_list_t * ++stp_paths_copy_with_prefix(stp_list_t *list, /* List to add prefix to */ ++ const char *prefix) /* Prefix to add */ ++{ ++ stp_list_t *new_list; ++ stp_list_item_t *item; ++ int prefixlen = strlen (prefix); ++ if (!(new_list = stp_list_create())) ++ return NULL; ++ ++ item = stp_list_get_start (list); ++ while (item) ++ { ++ const char *data; ++ char *new_data; ++ int len; ++ data = stp_list_item_get_data (item); ++ len = strlen (data); ++ new_data = (char *) stp_malloc(prefixlen + 1 + len + 1); ++ strncpy(new_data, prefix, prefixlen); ++ new_data[prefixlen] = '/'; ++ strcpy(new_data + prefixlen + 1, data); ++ stp_list_item_create(new_list, NULL, new_data); ++ ++ item = stp_list_item_next (item); ++ } ++ ++ return new_list; ++} ++ + /* Adapted from GNU libc <dirent.h> + These macros extract size information from a `struct dirent *'. + They may evaluate their argument multiple times, so it must not diff --git a/gutenprint-yyin.patch b/gutenprint-yyin.patch new file mode 100644 index 0000000..79658ca --- /dev/null +++ b/gutenprint-yyin.patch @@ -0,0 +1,26 @@ +diff -up gutenprint-5.2.9/src/gutenprintui2/Makefile.am.yyin gutenprint-5.2.9/src/gutenprintui2/Makefile.am +--- gutenprint-5.2.9/src/gutenprintui2/Makefile.am.yyin 2010-09-12 14:52:53.000000000 +0100 ++++ gutenprint-5.2.9/src/gutenprintui2/Makefile.am 2012-12-18 16:27:11.705127153 +0000 +@@ -55,7 +55,8 @@ libgutenprintui2_la_CFLAGS = $(AM_CFLAGS + # Uncomment to build a versioned library + libgutenprintui2_la_LDFLAGS = \ + -version-info $(GUTENPRINTUI2_CURRENT_INTERFACE):$(GUTENPRINTUI2_INTERFACE_AGE):$(GUTENPRINTUI2_BINARY_AGE) \ +- -rpath $(libdir) -no-undefined ++ -rpath $(libdir) -no-undefined \ ++ -export-symbols-regex '^([^y]|y[^y])' + + AM_LFLAGS = -i + AM_YFLAGS = -d +diff -up gutenprint-5.2.9/src/gutenprintui2/Makefile.in.yyin gutenprint-5.2.9/src/gutenprintui2/Makefile.in +--- gutenprint-5.2.9/src/gutenprintui2/Makefile.in.yyin 2012-07-07 16:36:19.000000000 +0100 ++++ gutenprint-5.2.9/src/gutenprintui2/Makefile.in 2012-12-18 16:27:11.705127153 +0000 +@@ -367,7 +367,8 @@ libgutenprintui2_la_CFLAGS = $(AM_CFLAGS + # Uncomment to build a versioned library + libgutenprintui2_la_LDFLAGS = \ + -version-info $(GUTENPRINTUI2_CURRENT_INTERFACE):$(GUTENPRINTUI2_INTERFACE_AGE):$(GUTENPRINTUI2_BINARY_AGE) \ +- -rpath $(libdir) -no-undefined ++ -rpath $(libdir) -no-undefined \ ++ -export-symbols-regex '^([^y]|y[^y])' + + AM_LFLAGS = -i + AM_YFLAGS = -d diff --git a/gutenprint.spec b/gutenprint.spec new file mode 100644 index 0000000..edfda66 --- /dev/null +++ b/gutenprint.spec @@ -0,0 +1,159 @@ +%bcond_with gimp + +Name: gutenprint +Version: 5.3.5 +Release: 1 +Summary: A suite of printer drivers +License: GPL-2.0-or-later AND LGPL-2.0-or-later AND MIT AND GPL-3.0-or-later WITH Bison-exception-2.2 +URL: https://gimp-print.sourceforge.io/ +Source0: https://downloads.sourceforge.net/gimp-print/%{name}-%{version}.tar.xz +Source1: cups-genppdupdate.py.in +Patch0: gutenprint-menu.patch +Patch1: gutenprint-postscriptdriver.patch +Patch2: gutenprint-yyin.patch +Patch3: gutenprint-manpage.patch + +%if %{with gimp} +BuildRequires: pkgconfig(gimpui-2.0), gimp +Requires: gimp +Provides: %{name}-plugin%{?_isa} %{name}-plugin +Obsoletes: %{name}-plugin +%endif + +BuildRequires: cups-libs, cups-devel, cups, gettext-devel, pkgconfig, libtiff-devel, libjpeg-devel, libpng-devel +BuildRequires: pkgconfig(libusb-1.0), pkgconfig(gtk+-2.0), chrpath, python3-cups +BuildRequires: autoconf, automake, libtool, python3-devel +Requires: cups +Provides: %{name}-doc%{?_isa} %{name}-doc +Obsoletes: %{name}-doc +Provides: %{name}-libs%{?_isa} %{name}-libs +Obsoletes: %{name}-libs +Provides: %{name}-libs-ui%{?_isa} %{name}-libs-ui +Obsoletes: %{name}-libs-ui +Provides: %{name}-extras%{?_isa} %{name}-extras +Obsoletes: %{name}-extras +Provides: %{name}-cups%{?_isa} %{name}-cups +Obsoletes: %{name}-cups + +%description +Gutenprint, formerly named Gimp-Print, is a suite of printer drivers that may be used with CUPS, +the Common UNIX Printing System. CUPS is the printing system used by all modern Linux and UNIX systems. +These drivers provide high quality printing for UNIX (including Macintosh OS X 10.2 and later) +and Linux systems that in many cases equal or exceed proprietary vendor-supplied drivers in quality +and functionality, and can be used for demanding printing tasks requiring flexibility and high quality. +This software package include an enhanced Print plugin for the GIMP that replaces the plugin packaged +with the GIMP in addition to the CUPS driver. +Gutenprint has been renamed in order to clearly distinguish it from the GIMP. While this package +started out as the original Print plugin for the GIMP, it has expanded into a collection of general +purpose printer drivers, and the new, enhanced Print plugin for the GIMP is now only a small part of +the package. Furthermore, the name Gutenprint recognizes Johannes Gutenberg, the inventor of the movable +type printing press. Finally, the word guten is the German word for good. +Gutenprint 5.2 incorporates extensive feedback from the beta and release candidate programs. +Gutenprint supports only the printer portion of multi-function devices (devices that typically include +scanning, copying, and fax capabilities). +Gutenprint currently supports over 700 printer models. + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release}, gtk2-devel + +%description devel +This package includes development files for %{name}. + +%package_help + +%prep +%autosetup -p1 -n %{name}-%{version} +cp %{SOURCE1} src/cups/cups-genppdupdate.in + +%build +sed -i -e 's,^\(TESTS *=.*\) run-weavetest,\1,' test/Makefile.in + +%configure --disable-dependency-tracking --disable-static --enable-samples --enable-escputil --enable-test \ + --disable-rpath --enable-cups-1_2-enhancements --disable-cups-ppds --enable-simplified-cups-ppds + +%make_build + +%install +%make_install +%delete_la + +install -d $RPM_BUILD_ROOT%{_sbindir} + +rm -rf $RPM_BUILD_ROOT%{_datadir}/%{name}/doc +rm -rf $RPM_BUILD_ROOT%{_datadir}/foomatic/kitload.log +rm -rf $RPM_BUILD_ROOT%{_libdir}/%{name}/5.2/modules/*.la +rm -rf $RPM_BUILD_ROOT%{_sysconfdir}/cups/command.types + +%find_lang %{name} +sed 's!%{_datadir}/locale/\([^/]*\)/LC_MESSAGES/gutenprint.mo!%{_datadir}/locale/\1/gutenprint_\1.po!g' %{name}.lang >%{name}-po.lang +rm -rf %{name}.lang +%find_lang %{name} --all-name +cat %{name}-po.lang >>%{name}.lang + +echo .so man8/cups-genppd.8 > $RPM_BUILD_ROOT%{_mandir}/man8/cups-genppd.5.2.8 + +chrpath -d $RPM_BUILD_ROOT%{_sbindir}/cups-genppd.5.3 +%if %{with gimp} +chrpath -d $RPM_BUILD_ROOT%{_libdir}/gimp/*/plug-ins/* +%endif +chrpath -d $RPM_BUILD_ROOT%{_libdir}/*.so.* +chrpath -d $RPM_BUILD_ROOT%{_cups_serverbin}/driver/* +chrpath -d $RPM_BUILD_ROOT%{_cups_serverbin}/filter/* +chrpath -d $RPM_BUILD_ROOT%{_bindir}/* + +%post +/usr/sbin/cups-genppdupdate &>/dev/null || : +/sbin/service cups reload &>/dev/null || : +exit 0 + +%files -f %{name}.lang +%license COPYING +%doc AUTHORS NEWS README doc/FAQ.html doc/%{name}-users-manual.odt doc/%{name}-users-manual.pdf +%{_bindir}/escputil +%{_bindir}/testpattern +%{_bindir}/cups-calibrate +%{_sbindir}/cups-genppd* +%{_datadir}/%{name} +%{_datadir}/%{name}/samples/* +%{_datadir}/cups/calibrate.ppm +%{_datadir}/cups/usb/net.sf.gimp-print.usb-quirks +%{_libdir}/%{name} +%{_libdir}/*.so.* +%if %{with gimp} +%{_libdir}/gimp/*/plug-ins/%{name} +%endif +%{_cups_serverbin}/filter/* +%{_cups_serverbin}/driver/* +%{_cups_serverbin}/backend/* + +%files devel +%doc doc/developer/reference-html doc/developer/%{name}.pdf doc/%{name}* +%{_includedir}/%{name}*/ +%{_libdir}/*.so +%{_libdir}/pkgconfig/*.pc + +%files help +%{_mandir}/man*/* + +%changelog +* Mon Mar 24 2025 Funda Wang <fundawang@yeah.net> - 5.3.5-1 +- update to 5.3.5 + +* Mon Oct 09 2023 Ge Wang <wang__Ge@126.com> - 5.3.4-1 +- Update to version 5.3.4 + +* Mon Jan 9 2023 yaoguangzhong <yaoguangzhong@xfusion.com> - 5.2.14-8 +- backport Minor doc issues + +* Sat Jan 7 2023 yaoguangzhong <yaoguangzhong@xfusion.com> - 5.2.14-7 +- backport add Epson Expression ET-2600 EcoTank + +* Sat Feb 20 2021 lingsheng <lingsheng@huawei.com> - 5.2.14-6 +- Disable gimp plugins build + +* Thu Nov 26 2020 liuweibo <liuweibo10@hauwei.com> - 5.2.14-5 +- Fix install warning + +* Sat Nov 30 2019 openEuler Buildteam <buildteam@openeuler.org> - 5.2.14-4 +- Package init @@ -0,0 +1 @@ +18968a1376a0fb0155afea4ce832d7fd gutenprint-5.3.5.tar.xz |