a6bd2b8
#!/usr/bin/python
a6bd2b8
a6bd2b8
## gutenprint-foomaticppdupdate
a6bd2b8
a6bd2b8
## A utility for updating foomatic-generated PPDs so that they work with
a6bd2b8
## a newly-installed gutenprint package.
a6bd2b8
4e06115
## Copyright (C) 2007, 2009 Red Hat, Inc.
4e06115
## Copyright (C) 2007, 2009 Tim Waugh 
a6bd2b8
a6bd2b8
## This program is free software; you can redistribute it and/or modify
a6bd2b8
## it under the terms of the GNU General Public License as published by
a6bd2b8
## the Free Software Foundation; either version 2 of the License, or
a6bd2b8
## (at your option) any later version.
a6bd2b8
a6bd2b8
## This program is distributed in the hope that it will be useful,
a6bd2b8
## but WITHOUT ANY WARRANTY; without even the implied warranty of
a6bd2b8
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
a6bd2b8
## GNU General Public License for more details.
a6bd2b8
a6bd2b8
## You should have received a copy of the GNU General Public License
a6bd2b8
## along with this program; if not, write to the Free Software
a6bd2b8
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
a6bd2b8
a6bd2b8
import sys
a6bd2b8
import glob
a6bd2b8
import os
54d7644
import subprocess
a6bd2b8
import tempfile
a6bd2b8
a6bd2b8
import cups
a6bd2b8
a6bd2b8
if len (sys.argv) < 2 or sys.argv[1] == "--help":
a6bd2b8
    print "Usage: gutenprint-foomaticppdupdate <version>"
a6bd2b8
    sys.exit (1)
a6bd2b8
a6bd2b8
gutenprint_version = sys.argv[1]
a6bd2b8
dry_run = True
a6bd2b8
a6bd2b8
def generate_ppd (ppdfile, printer, driver):
54d7644
    p = subprocess.Popen (["foomatic-ppdfile", "-p", printer, "-d", driver],
54d7644
                          stdin=file ("/dev/null"),
54d7644
                          stdout=subprocess.PIPE,
54d7644
                          stderr=subprocess.PIPE)
54d7644
    (ppd, stderr) = p.communicate ()
a6bd2b8
    fname = ppdfile + ".tmp"
a6bd2b8
    try:
54d7644
        file(fname, "w").write (ppd)
a6bd2b8
    except IOError, e:
a6bd2b8
        print e
a6bd2b8
        raise
a6bd2b8
a6bd2b8
    ppdobj = cups.PPD (fname)
a6bd2b8
    os.remove (fname)
a6bd2b8
    return ppdobj
a6bd2b8
a6bd2b8
def update_ppdfile (ppdfile):
cb7a209
    try:
cb7a209
        ppd = cups.PPD (ppdfile)
cb7a209
    except RuntimeError:
cb7a209
        # Invalid PPD in some way.
cb7a209
        return
cb7a209
a6bd2b8
    attr = ppd.findAttr ("FoomaticIDs")
a6bd2b8
    if not attr:
a6bd2b8
        return
a6bd2b8
a6bd2b8
    IDs = attr.value.split (" ")
a6bd2b8
    if len (IDs) != 2:
a6bd2b8
        print "Don't understand FoomaticIDs: %s" % IDs
a6bd2b8
        return
a6bd2b8
a6bd2b8
    if not IDs[1].startswith ("gutenprint"):
a6bd2b8
        return
a6bd2b8
a6bd2b8
    attr = ppd.findAttr ("FoomaticRIPCommandLine")
a6bd2b8
    if not attr:
a6bd2b8
        return
a6bd2b8
a6bd2b8
    cmdline = attr.value
a6bd2b8
    STP_VERSION="STP_VERSION="
a6bd2b8
    i = cmdline.find (STP_VERSION)
a6bd2b8
    if i == -1:
a6bd2b8
        return
a6bd2b8
a6bd2b8
    i += len (STP_VERSION)
a6bd2b8
    j = i + 1
a6bd2b8
    end = len (cmdline)
a6bd2b8
    while j < end:
a6bd2b8
        ch = cmdline[j]
a6bd2b8
        if ch != '.' and not ch.isdigit ():
a6bd2b8
            break
a6bd2b8
        j += 1
a6bd2b8
a6bd2b8
    version = cmdline[i:j]
a6bd2b8
    if gutenprint_version == version:
a6bd2b8
        return
a6bd2b8
a6bd2b8
    # Needs updating.
4e06115
    firstdot = gutenprint_version.find ('.')
4e06115
    seconddot = firstdot + 1 + gutenprint_version[1 + firstdot:].find ('.')
4e06115
    major = gutenprint_version[:seconddot]
4e06115
4e06115
    driver = IDs[1]
4e06115
    dot = driver.find ('.')
4e06115
    driver = driver[:dot] + "." + major
a6bd2b8
    try:
4e06115
        genppd = generate_ppd (ppdfile, IDs[0], driver)
a6bd2b8
    except:
a6bd2b8
        return
a6bd2b8
a6bd2b8
    os.environ['FILE'] = ppdfile
a6bd2b8
    os.system ('cp -af "$FILE" "$FILE".bak')
a6bd2b8
a6bd2b8
    def update_options (options, newppd, origppd):
a6bd2b8
        for newopt in options:
a6bd2b8
            origopt = origppd.findOption (newopt.keyword)
a6bd2b8
            if origopt:
a6bd2b8
                newppd.markOption (newopt.keyword, origopt.defchoice)
a6bd2b8
a6bd2b8
    genppd.markDefaults ()
a6bd2b8
    for group in genppd.optionGroups:
a6bd2b8
        update_options (group.options, genppd, ppd)
a6bd2b8
        for subgroup in group.subgroups:
a6bd2b8
            update_options (subgroup.options, genppd, ppd)
a6bd2b8
a6bd2b8
    ps = genppd.findOption ("PageSize")
a6bd2b8
    if ps:
a6bd2b8
        update_options ([ps], genppd, ppd)
a6bd2b8
a6bd2b8
    f = file (ppdfile, "w")
a6bd2b8
    genppd.writeFd (f.fileno ())
a6bd2b8
    print "Updated PPD file %s" % ppdfile
a6bd2b8
a6bd2b8
for ppdfile in glob.glob ("/etc/cups/ppd/*.ppd"):
a6bd2b8
    update_ppdfile (ppdfile)