summaryrefslogtreecommitdiffstats
path: root/patches/source/cups
diff options
context:
space:
mode:
Diffstat (limited to 'patches/source/cups')
-rwxr-xr-xpatches/source/cups/cups.SlackBuild206
-rw-r--r--patches/source/cups/cups.fix_broken_locking.diff256
-rw-r--r--patches/source/cups/doinst.sh34
-rw-r--r--patches/source/cups/slack-desc19
-rw-r--r--patches/source/cups/str4609-1.4.patch332
-rw-r--r--patches/source/cups/usb-backend-both-usblp-and-libusb.dpatch574
6 files changed, 1421 insertions, 0 deletions
diff --git a/patches/source/cups/cups.SlackBuild b/patches/source/cups/cups.SlackBuild
new file mode 100755
index 000000000..7263742c6
--- /dev/null
+++ b/patches/source/cups/cups.SlackBuild
@@ -0,0 +1,206 @@
+#!/bin/sh
+
+# Copyright 2008, 2009, 2010, 2011 Patrick J. Volkerding, Sebeka, Minnesota, USA
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# CUPS build script by volkerdi@slackware.com.
+
+VERSION=1.4.6
+BUILD=${BUILD:-2_slack13.37}
+
+# Automatically determine the architecture we're building on:
+if [ -z "$ARCH" ]; then
+ case "$( uname -m )" in
+ i?86) export ARCH=i486 ;;
+ arm*) export ARCH=arm ;;
+ # Unless $ARCH is already set, use uname -m for all other archs:
+ *) export ARCH=$( uname -m ) ;;
+ esac
+fi
+
+if [ "$ARCH" = "x86_64" ]; then
+ LIBDIRSUFFIX="64"
+else
+ LIBDIRSUFFIX=""
+fi
+
+NUMJOBS=${NUMJOBS:-" -j7 "}
+
+CWD=$(pwd)
+TMP=${TMP:-/tmp}
+PKG=$TMP/package-cups
+
+rm -rf $PKG
+mkdir -p $TMP $PKG
+
+cd $TMP
+rm -rf cups-$VERSION
+tar xvf $CWD/cups-$VERSION-source.tar.?z* || exit 1
+cd cups-$VERSION
+
+# Fix the USB backend to use either usblp or libusb:
+zcat $CWD/usb-backend-both-usblp-and-libusb.dpatch.gz | patch -p1 --verbose || exit 1
+
+# Fix locking to avoid crashes with OpenSSL:
+zcat $CWD/cups.fix_broken_locking.diff.gz | patch -p1 --verbose || exit 1
+
+zcat $CWD/str4609-1.4.patch.gz | patch -p0 --verbose || exit 1
+
+sed -i.orig -e 's#$exec_prefix/lib/cups#$libdir/cups#g' configure
+./configure \
+ --libdir=/usr/lib${LIBDIRSUFFIX} \
+ --enable-ssl \
+ --enable-openssl=yes \
+ --enable-gnutls=no \
+ --enable-cdsassl=no \
+ --docdir=/usr/doc \
+ --without-php \
+ --disable-pam \
+ --build=$ARCH-slackware-linux
+
+make $NUMJOBS || exit 1
+mkdir -p $PKG/etc/cups
+mkdir -p $PKG/var/spool
+make BUILDROOT=$PKG install || exit 1
+
+# I've added so many things like /etc/init.d/ to Slackware that CUPS
+# is now installing init scripts to the Red Hat locations. We'll move
+# them to the usual locations:
+mkdir -p $PKG/etc/rc.d
+# Handle this as a config file, and non-executable in a default install:
+mv $PKG/etc/init.d/cups $PKG/etc/rc.d/rc.cups.new
+chmod 644 $PKG/etc/rc.d/rc.cups.new
+# Clear out the additions:
+rm -rf $PKG/etc/init.d $PKG/etc/rc{0,2,3,5}.d
+
+### OBSOLETE. The USB backend is patched to support usblp again. ###
+## From 1.4.x, CUPS no longer uses usblp, and having the module loaded
+## will interfere with USB printers. So, we will add a blacklist rule
+## so that the module is not loaded:
+#mkdir -p $PKG/etc/modprobe.d
+#cat << EOF > $PKG/etc/modprobe.d/cups.blacklist.usblp.conf.new
+## Do not load the kernel usblp module, since it interferes with
+## versions of CUPS 1.4.0 and newer:
+#blacklist usblp
+#EOF
+
+# I'm not sure if overwriting this blindly could have ill effects,
+# but it never hurts to play it safe. According to the dbus-daemon
+# manpage, only files ending in .conf will be used, so there won't
+# be any unintended doubling up.
+mv $PKG/etc/dbus-1/system.d/cups.conf $PKG/etc/dbus-1/system.d/cups.conf.new
+
+# For full CUPS SMB support, you'll need to install the cups-samba
+# package from the source in this directory. There's no easy way
+# to add that to a package build, and the requests aren't pouring in,
+# so you'll have to install it yourself. It's easy to do.
+
+# However, this will get you the most useful SMB support for free.
+# Thanks to Boris Kurktchiev for the tip. :-)
+( cd $PKG/usr/lib${LIBDIRSUFFIX}/cups/backend
+ if [ ! -e smb ]; then
+ ln -sf /usr/bin/smbspool smb
+ fi
+)
+
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+
+# Remove preformatted manpages and move the manpages to /usr/man:
+( cd $PKG/usr/share/man
+ find . -type d -name "cat*" | xargs rm -rf
+ cd ..
+ mv man ..
+)
+
+# Adjust/expand docs:
+( mkdir -p $PKG/usr/doc
+ mv $PKG/usr/share/doc/cups $PKG/usr/doc/cups-$VERSION
+ rmdir $PKG/usr/share/doc
+ cd $PKG/usr/doc
+ ln -sf cups-$VERSION cups )
+
+# If there's a ChangeLog, installing at least part of the recent history
+# is useful, but don't let it get totally out of control:
+if [ -r CHANGES.txt ]; then
+ DOCSDIR=$(echo $PKG/usr/doc/*-$VERSION)
+ cat CHANGES.txt | head -n 1000 > $DOCSDIR/CHANGES.txt
+ touch -r CHANGES.txt $DOCSDIR/CHANGES.txt
+fi
+
+# I'm sorry, but PDF files are almost as bloated and annoying as
+# MS Word documents. We'll retain the HTML files in /usr/doc.
+( cd $PKG/usr/doc
+ find . -name "*.pdf" -exec rm -f {} \; )
+
+# Apply no-clobber fix to conffiles:
+( cd $PKG/etc/cups
+ for file in * ; do
+ if [ -f $file ]; then
+ mv $file $file.new
+ fi
+ done )
+
+# Strip stuff:
+find $PKG | xargs file | grep -e "executable" -e "shared object" \
+ | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+
+# Use symlinks to certain binaries so that CUPS and LPRng can coexist:
+SUFFIX=cups
+for file in \
+usr/bin/cancel \
+usr/bin/lp \
+usr/bin/lpq \
+usr/bin/lpr \
+usr/bin/lprm \
+usr/bin/lpstat \
+usr/sbin/lpc ; do
+ ( cd $PKG
+ mv ${file} ${file}-${SUFFIX}
+ ( cd `dirname ${file}` ; ln -sf `basename ${file}`-${SUFFIX} `basename ${file}` )
+ )
+done
+# Now fix the associated man pages:
+mv $PKG/usr/man/man1/cancel.1.gz $PKG/usr/man/man1/cancel-${SUFFIX}.1.gz
+mv $PKG/usr/man/man1/lp.1.gz $PKG/usr/man/man1/lp-${SUFFIX}.1.gz
+mv $PKG/usr/man/man1/lpq.1.gz $PKG/usr/man/man1/lpq-${SUFFIX}.1.gz
+mv $PKG/usr/man/man1/lpr.1.gz $PKG/usr/man/man1/lpr-${SUFFIX}.1.gz
+mv $PKG/usr/man/man1/lprm.1.gz $PKG/usr/man/man1/lprm-${SUFFIX}.1.gz
+mv $PKG/usr/man/man1/lpstat.1.gz $PKG/usr/man/man1/lpstat-${SUFFIX}.1.gz
+mv $PKG/usr/man/man8/lpc.8.gz $PKG/usr/man/man8/lpc-${SUFFIX}.8.gz
+( cd $PKG/usr/man/man1
+ ln -sf cancel-${SUFFIX}.1.gz cancel.1.gz
+ ln -sf lp-${SUFFIX}.1.gz lp.1.gz
+ ln -sf lpq-${SUFFIX}.1.gz lpq.1.gz
+ ln -sf lpr-${SUFFIX}.1.gz lpr.1.gz
+ ln -sf lprm-${SUFFIX}.1.gz lprm.1.gz
+ ln -sf lpstat-${SUFFIX}.1.gz lpstat.1.gz
+)
+( cd $PKG/usr/man/man8
+ ln -sf lpc-${SUFFIX}.8.gz lpc.8.gz
+)
+
+# Add the doinst.sh that installs the .new conffiles:
+zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
+
+# Build the package:
+cd $PKG
+/sbin/makepkg -l y -c n $TMP/cups-$VERSION-$ARCH-$BUILD.txz
+
diff --git a/patches/source/cups/cups.fix_broken_locking.diff b/patches/source/cups/cups.fix_broken_locking.diff
new file mode 100644
index 000000000..44f97533f
--- /dev/null
+++ b/patches/source/cups/cups.fix_broken_locking.diff
@@ -0,0 +1,256 @@
+Submitted By: DJ Lucas <robert AT linuxfromscratch DOT org>
+Date: 2010-09-13
+Initial Package Version: 1.4.4
+Upstream Status: Unknown
+Origin: https://bugzilla.redhat.com/show_bug.cgi?id=553834
+Description: Bug fix for invalid locking with GCrypt.
+
+diff -Naurp cups-1.4.4-orig/cups/http.c cups-1.4.4/cups/http.c
+--- cups-1.4.4-orig/cups/http.c 2010-06-16 00:27:41.000000000 -0500
++++ cups-1.4.4/cups/http.c 2010-09-13 01:27:03.000000000 -0500
+@@ -83,12 +83,10 @@
+ * http_debug_hex() - Do a hex dump of a buffer.
+ * http_field() - Return the field index for a field name.
+ * http_read_ssl() - Read from a SSL/TLS connection.
+- * http_locking_cb() - Lock/unlock a thread's mutex.
+ * http_send() - Send a request with all fields and the trailing
+ * blank line.
+ * http_setup_ssl() - Set up SSL/TLS support on a connection.
+ * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
+- * http_threadid_cb() - Return the current thread ID.
+ * http_upgrade() - Force upgrade to TLS encryption.
+ * http_write() - Write a buffer to a HTTP connection.
+ * http_write_chunk() - Write a chunked buffer.
+@@ -146,19 +144,6 @@ static int http_setup_ssl(http_t *http)
+ static void http_shutdown_ssl(http_t *http);
+ static int http_upgrade(http_t *http);
+ static int http_write_ssl(http_t *http, const char *buf, int len);
+-
+-# ifdef HAVE_GNUTLS
+-# ifdef HAVE_PTHREAD_H
+-GCRY_THREAD_OPTION_PTHREAD_IMPL;
+-# endif /* HAVE_PTHREAD_H */
+-
+-# elif defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
+-static pthread_mutex_t *http_locks; /* OpenSSL lock mutexes */
+-
+-static void http_locking_cb(int mode, int type, const char *file,
+- int line);
+-static unsigned long http_threadid_cb(void);
+-# endif /* HAVE_GNUTLS */
+ #endif /* HAVE_SSL */
+
+
+@@ -1188,22 +1173,21 @@ httpHead(http_t *http, /* I - Conne
+ void
+ httpInitialize(void)
+ {
+- static int initialized = 0; /* Have we been called before? */
+-#ifdef WIN32
+- WSADATA winsockdata; /* WinSock data */
+-#endif /* WIN32 */
+ #ifdef HAVE_LIBSSL
+- int i; /* Looping var */
+- unsigned char data[1024]; /* Seed data */
++# ifndef WIN32
++ struct timeval curtime; /* Current time in microseconds */
++# endif /* !WIN32 */
++ int i; /* Looping var */
++ unsigned char data[1024]; /* Seed data */
+ #endif /* HAVE_LIBSSL */
+
+-
+- if (initialized)
+- return;
+-
+ #ifdef WIN32
+- WSAStartup(MAKEWORD(2,2), &winsockdata);
++ WSADATA winsockdata; /* WinSock data */
++
+
++ static int initialized = 0; /* Has WinSock been initialized? */
++ if (!initialized)
++ WSAStartup(MAKEWORD(1,1), &winsockdata);
+ #elif !defined(SO_NOSIGPIPE)
+ /*
+ * Ignore SIGPIPE signals...
+@@ -1226,21 +1210,15 @@ httpInitialize(void)
+ #endif /* WIN32 */
+
+ #ifdef HAVE_GNUTLS
+- /*
+- * Make sure we handle threading properly...
+- */
+-
+-# ifdef HAVE_PTHREAD_H
+- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+-# endif /* HAVE_PTHREAD_H */
+
+ /*
+ * Initialize GNU TLS...
+ */
+
+ gnutls_global_init();
++#endif /* HAVE_GNUTLS */
+
+-#elif defined(HAVE_LIBSSL)
++#ifdef HAVE_LIBSSL
+ /*
+ * Initialize OpenSSL...
+ */
+@@ -1249,33 +1227,21 @@ httpInitialize(void)
+ SSL_library_init();
+
+ /*
+- * Set the threading callbacks...
+- */
+-
+-# ifdef HAVE_PTHREAD_H
+- http_locks = calloc(CRYPTO_num_locks(), sizeof(pthread_mutex_t));
+-
+- for (i = 0; i < CRYPTO_num_locks(); i ++)
+- pthread_mutex_init(http_locks + i, NULL);
+-
+- CRYPTO_set_id_callback(http_threadid_cb);
+- CRYPTO_set_locking_callback(http_locking_cb);
+-# endif /* HAVE_PTHREAD_H */
+-
+- /*
+ * Using the current time is a dubious random seed, but on some systems
+ * it is the best we can do (on others, this seed isn't even used...)
+ */
+
+- CUPS_SRAND(time(NULL));
++# ifdef WIN32
++# else
++ gettimeofday(&curtime, NULL);
++ srand(curtime.tv_sec + curtime.tv_usec);
++# endif /* WIN32 */
+
+ for (i = 0; i < sizeof(data); i ++)
+- data[i] = CUPS_RAND();
++ data[i] = rand();
+
+ RAND_seed(data, sizeof(data));
+-#endif /* HAVE_GNUTLS */
+-
+- initialized = 1;
++#endif /* HAVE_LIBSSL */
+ }
+
+
+@@ -2834,25 +2800,6 @@ http_read_ssl(http_t *http, /* I - Conn
+ #endif /* HAVE_SSL */
+
+
+-#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
+-/*
+- * 'http_locking_cb()' - Lock/unlock a thread's mutex.
+- */
+-
+-static void
+-http_locking_cb(int mode, /* I - Lock mode */
+- int type, /* I - Lock type */
+- const char *file, /* I - Source file */
+- int line) /* I - Line number */
+-{
+- if (mode & CRYPTO_LOCK)
+- pthread_mutex_lock(http_locks + type);
+- else
+- pthread_mutex_unlock(http_locks + type);
+-}
+-#endif /* HAVE_LIBSSL && HAVE_PTHREAD_H */
+-
+-
+ /*
+ * 'http_send()' - Send a request with all fields and the trailing blank line.
+ */
+@@ -3224,19 +3171,6 @@ http_shutdown_ssl(http_t *http) /* I -
+ #endif /* HAVE_SSL */
+
+
+-#if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H)
+-/*
+- * 'http_threadid_cb()' - Return the current thread ID.
+- */
+-
+-static unsigned long /* O - Thread ID */
+-http_threadid_cb(void)
+-{
+- return ((unsigned long)pthread_self());
+-}
+-#endif /* HAVE_LIBSSL && HAVE_PTHREAD_H */
+-
+-
+ #ifdef HAVE_SSL
+ /*
+ * 'http_upgrade()' - Force upgrade to TLS encryption.
+diff -Naurp cups-1.4.4-orig/cups/http-private.h cups-1.4.4/cups/http-private.h
+--- cups-1.4.4-orig/cups/http-private.h 2010-04-11 23:03:53.000000000 -0500
++++ cups-1.4.4/cups/http-private.h 2010-09-13 01:27:24.000000000 -0500
+@@ -98,7 +98,6 @@ extern BIO_METHOD *_httpBIOMethods(void)
+ * The GNU TLS library is more of a "bare metal" SSL/TLS library...
+ */
+ # include <gnutls/gnutls.h>
+-# include <gcrypt.h>
+
+ typedef struct
+ {
+diff -Naurp cups-1.4.4-orig/scheduler/main.c cups-1.4.4/scheduler/main.c
+--- cups-1.4.4-orig/scheduler/main.c 2010-04-23 13:56:34.000000000 -0500
++++ cups-1.4.4/scheduler/main.c 2010-09-13 01:27:36.000000000 -0500
+@@ -549,8 +549,6 @@ main(int argc, /* I - Number of comm
+ * Startup the server...
+ */
+
+- httpInitialize();
+-
+ cupsdStartServer();
+
+ /*
+diff -Naurp cups-1.4.4-orig/scheduler/server.c cups-1.4.4/scheduler/server.c
+--- cups-1.4.4-orig/scheduler/server.c 2010-04-11 23:03:53.000000000 -0500
++++ cups-1.4.4/scheduler/server.c 2010-09-13 01:27:49.000000000 -0500
+@@ -44,6 +44,42 @@ static int started = 0;
+ void
+ cupsdStartServer(void)
+ {
++#ifdef HAVE_LIBSSL
++ int i; /* Looping var */
++ struct timeval curtime; /* Current time in microseconds */
++ unsigned char data[1024]; /* Seed data */
++#endif /* HAVE_LIBSSL */
++
++
++#ifdef HAVE_LIBSSL
++ /*
++ * Initialize the encryption libraries...
++ */
++
++ SSL_library_init();
++ SSL_load_error_strings();
++
++ /*
++ * Using the current time is a dubious random seed, but on some systems
++ * it is the best we can do (on others, this seed isn't even used...)
++ */
++
++ gettimeofday(&curtime, NULL);
++ srand(curtime.tv_sec + curtime.tv_usec);
++
++ for (i = 0; i < sizeof(data); i ++)
++ data[i] = rand(); /* Yes, this is a poor source of random data... */
++
++ RAND_seed(&data, sizeof(data));
++#elif defined(HAVE_GNUTLS)
++ /*
++ * Initialize the encryption libraries...
++ */
++
++ gnutls_global_init();
++#endif /* HAVE_LIBSSL */
++
++
+ /*
+ * Create the default security profile...
+ */
diff --git a/patches/source/cups/doinst.sh b/patches/source/cups/doinst.sh
new file mode 100644
index 000000000..6807cc3ac
--- /dev/null
+++ b/patches/source/cups/doinst.sh
@@ -0,0 +1,34 @@
+config() {
+ NEW="$1"
+ OLD="`dirname $NEW`/`basename $NEW .new`"
+ # If there's no config file by that name, mv it over:
+ if [ ! -r $OLD ]; then
+ mv $NEW $OLD
+ elif [ "`cat $OLD | md5sum`" = "`cat $NEW | md5sum`" ]; then # toss the redundant copy
+ rm $NEW
+ fi
+ # Otherwise, we leave the .new copy for the admin to consider...
+}
+for file in etc/cups/*.new ; do
+ config $file
+done
+config etc/dbus-1/system.d/cups.conf.new
+
+# This file will just have to go. It appeared for a while during a -current
+# devel period and has never been part of a stable release.
+#config etc/modprobe.d/cups.blacklist.usblp.conf.new
+rm -f etc/modprobe.d/cups.blacklist.usblp.conf.new
+rm -f etc/modprobe.d/cups.blacklist.usblp.conf
+
+# Leave any new rc.cups with the same permissions as the old one:
+# This is a kludge, but it's because there's no --reference option
+# on busybox's 'chmod':
+if [ -e etc/rc.d/rc.cups ]; then
+ if [ -x etc/rc.d/rc.cups ]; then
+ chmod 755 etc/rc.d/rc.cups.new
+ else
+ chmod 644 etc/rc.d/rc.cups.new
+ fi
+fi
+# Then config() it:
+config etc/rc.d/rc.cups.new
diff --git a/patches/source/cups/slack-desc b/patches/source/cups/slack-desc
new file mode 100644
index 000000000..c2e1643c9
--- /dev/null
+++ b/patches/source/cups/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|' on
+# the right side marks the last column you can put a character in. You must make
+# exactly 11 lines for the formatting to be correct. It's also customary to
+# leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+cups: CUPS (Common UNIX Printing System)
+cups:
+cups: The Common UNIX Printing System provides a portable printing layer for
+cups: UNIX(R)-like operating systems. It has been developed by Easy Software
+cups: Products to promote a standard printing solution for all UNIX vendors
+cups: and users. CUPS uses the Internet Printing Protocol ("IPP") as the
+cups: basis for managing print jobs and queues. The CUPS package includes
+cups: System V and Berkeley command-line interfaces, a PostScript RIP
+cups: package for supporting non-PostScript printer drivers, and tools for
+cups: creating additional printer drivers and other CUPS services.
+cups:
diff --git a/patches/source/cups/str4609-1.4.patch b/patches/source/cups/str4609-1.4.patch
new file mode 100644
index 000000000..d896b6bd0
--- /dev/null
+++ b/patches/source/cups/str4609-1.4.patch
@@ -0,0 +1,332 @@
+Index: cgi-bin/ipp-var.c
+===================================================================
+--- cgi-bin/ipp-var.c (revision 12588)
++++ cgi-bin/ipp-var.c (working copy)
+@@ -1230,21 +1230,7 @@
+ * Rewrite URIs...
+ */
+
+- if (!strcmp(name, "member_uris"))
+- {
+- char url[1024]; /* URL for class member... */
+-
+-
+- cgiRewriteURL(attr->values[i].string.text, url,
+- sizeof(url), NULL);
+-
+- snprintf(valptr, sizeof(value) - (valptr - value),
+- "<A HREF=\"%s\">%s</A>", url,
+- strrchr(attr->values[i].string.text, '/') + 1);
+- }
+- else
+- cgiRewriteURL(attr->values[i].string.text, valptr,
+- sizeof(value) - (valptr - value), NULL);
++ cgiRewriteURL(attr->values[i].string.text, valptr, sizeof(value) - (valptr - value), NULL);
+ break;
+ }
+
+Index: cgi-bin/template.c
+===================================================================
+--- cgi-bin/template.c (revision 12588)
++++ cgi-bin/template.c (working copy)
+@@ -659,39 +659,7 @@
+ while (*s)
+ {
+ if (*s == '<')
+- {
+- /*
+- * Pass <A HREF="url"> and </A>, otherwise quote it...
+- */
+-
+- if (!strncasecmp(s, "<A HREF=\"", 9))
+- {
+- fputs("<A HREF=\"", out);
+- s += 9;
+-
+- while (*s && *s != '\"')
+- {
+- if (*s == '&')
+- fputs("&amp;", out);
+- else
+- putc(*s, out);
+-
+- s ++;
+- }
+-
+- if (*s)
+- s ++;
+-
+- fputs("\">", out);
+- }
+- else if (!strncasecmp(s, "</A>", 4))
+- {
+- fputs("</A>", out);
+- s += 3;
+- }
+- else
+- fputs("&lt;", out);
+- }
++ fputs("&lt;", out);
+ else if (*s == '>')
+ fputs("&gt;", out);
+ else if (*s == '\"')
+Index: scheduler/ipp.c
+===================================================================
+--- scheduler/ipp.c (revision 12588)
++++ scheduler/ipp.c (working copy)
+@@ -498,8 +498,8 @@
+ * Remote unauthenticated user masquerading as local root...
+ */
+
+- _cupsStrFree(username->values[0].string.text);
+- username->values[0].string.text = _cupsStrAlloc(RemoteRoot);
++ _cupsStrFree(username->values[0].string.text);
++ username->values[0].string.text = _cupsStrAlloc(RemoteRoot);
+ }
+ }
+
+@@ -1638,7 +1638,10 @@
+ cupsdSetString(&job->username, con->username);
+
+ if (attr)
+- cupsdSetString(&attr->values[0].string.text, con->username);
++ {
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(con->username);
++ }
+ }
+ else if (attr)
+ {
+@@ -1689,48 +1692,11 @@
+ * Also, we can only have 1 value and it must be a name value.
+ */
+
+- switch (attr->value_tag)
+- {
+- case IPP_TAG_STRING :
+- case IPP_TAG_TEXTLANG :
+- case IPP_TAG_NAMELANG :
+- case IPP_TAG_TEXT :
+- case IPP_TAG_NAME :
+- case IPP_TAG_KEYWORD :
+- case IPP_TAG_URI :
+- case IPP_TAG_URISCHEME :
+- case IPP_TAG_CHARSET :
+- case IPP_TAG_LANGUAGE :
+- case IPP_TAG_MIMETYPE :
+- /*
+- * Free old strings...
+- */
+-
+- for (i = 0; i < attr->num_values; i ++)
+- {
+- _cupsStrFree(attr->values[i].string.text);
+- attr->values[i].string.text = NULL;
+- if (attr->values[i].string.charset)
+- {
+- _cupsStrFree(attr->values[i].string.charset);
+- attr->values[i].string.charset = NULL;
+- }
+- }
+-
+- default :
+- break;
+- }
+-
+- /*
+- * Use the default connection hostname instead...
+- */
+-
+- attr->value_tag = IPP_TAG_NAME;
+- attr->num_values = 1;
+- attr->values[0].string.text = _cupsStrAlloc(con->http.hostname);
++ ippDeleteAttribute(job->attrs, attr);
++ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-host-name", NULL, con->http.hostname);
+ }
+-
+- attr->group_tag = IPP_TAG_JOB;
++ else
++ attr->group_tag = IPP_TAG_JOB;
+ }
+ else
+ {
+@@ -1822,8 +1788,8 @@
+
+ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets",
+ 2, NULL, NULL);
+- attr->values[0].string.text = _cupsStrRetain(printer->job_sheets[0]);
+- attr->values[1].string.text = _cupsStrRetain(printer->job_sheets[1]);
++ attr->values[0].string.text = _cupsStrAlloc(printer->job_sheets[0]);
++ attr->values[1].string.text = _cupsStrAlloc(printer->job_sheets[1]);
+ }
+
+ job->job_sheets = attr;
+@@ -1849,7 +1815,8 @@
+ * Force the leading banner to have the classification on it...
+ */
+
+- cupsdSetString(&attr->values[0].string.text, Classification);
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(Classification);
+
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,none\", "
+@@ -1866,7 +1833,8 @@
+ * Can't put two different security markings on the same document!
+ */
+
+- cupsdSetString(&attr->values[1].string.text, attr->values[0].string.text);
++ _cupsStrFree(attr->values[1].string.text);
++ attr->values[1].string.text = _cupsStrAlloc(attr->values[0].string.text);
+
+ cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED "
+ "job-sheets=\"%s,%s\", "
+@@ -1906,18 +1874,26 @@
+ if (attr->num_values > 1 &&
+ !strcmp(attr->values[0].string.text, attr->values[1].string.text))
+ {
+- cupsdSetString(&(attr->values[0].string.text), Classification);
+- cupsdSetString(&(attr->values[1].string.text), Classification);
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(Classification);
++ _cupsStrFree(attr->values[1].string.text);
++ attr->values[1].string.text = _cupsStrAlloc(Classification);
+ }
+ else
+ {
+ if (attr->num_values == 1 ||
+ strcmp(attr->values[0].string.text, "none"))
+- cupsdSetString(&(attr->values[0].string.text), Classification);
++ {
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(Classification);
++ }
+
+ if (attr->num_values > 1 &&
+ strcmp(attr->values[1].string.text, "none"))
+- cupsdSetString(&(attr->values[1].string.text), Classification);
++ {
++ _cupsStrFree(attr->values[1].string.text);
++ attr->values[1].string.text = _cupsStrAlloc(Classification);
++ }
+ }
+
+ if (attr->num_values > 1)
+@@ -3845,7 +3821,8 @@
+ if (attr)
+ {
+ attr->value_tag = IPP_TAG_KEYWORD;
+- cupsdSetString(&(attr->values[0].string.text), "no-hold");
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc("no-hold");
+ }
+
+ /*
+@@ -8832,7 +8809,6 @@
+ if (format)
+ {
+ _cupsStrFree(format->values[0].string.text);
+-
+ format->values[0].string.text = _cupsStrAlloc(mimetype);
+ }
+ else
+@@ -9371,9 +9347,8 @@
+
+ if (attr)
+ {
++ attr->value_tag = IPP_TAG_KEYWORD;
+ _cupsStrFree(attr->values[0].string.text);
+-
+- attr->value_tag = IPP_TAG_KEYWORD;
+ attr->values[0].string.text = _cupsStrAlloc("no-hold");
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job,
+@@ -10065,7 +10040,6 @@
+ IPP_TAG_MIMETYPE)) != NULL)
+ {
+ _cupsStrFree(jformat->values[0].string.text);
+-
+ jformat->values[0].string.text = _cupsStrAlloc(mimetype);
+ }
+ else
+Index: scheduler/job.c
+===================================================================
+--- scheduler/job.c (revision 12588)
++++ scheduler/job.c (working copy)
+@@ -397,7 +397,10 @@
+
+ if ((attr = ippFindAttribute(job->attrs, "job-actual-printer-uri",
+ IPP_TAG_URI)) != NULL)
+- cupsdSetString(&attr->values[0].string.text, printer->uri);
++ {
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(printer->uri);
++ }
+ else
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-actual-printer-uri", NULL, printer->uri);
+@@ -1830,7 +1833,10 @@
+
+ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
+ IPP_TAG_URI)) != NULL)
+- cupsdSetString(&(attr->values[0].string.text), p->uri);
++ {
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(p->uri);
++ }
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
+ "Job #%d moved from %s to %s.", job->id, olddest,
+@@ -2026,7 +2032,10 @@
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr)
+- cupsdSetString(&(attr->values[0].string.text), when);
++ {
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc(when);
++ }
+ else
+ attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
+ "job-hold-until", NULL, when);
+@@ -2272,7 +2281,8 @@
+ if (attr)
+ {
+ attr->value_tag = IPP_TAG_KEYWORD;
+- cupsdSetString(&(attr->values[0].string.text), "no-hold");
++ _cupsStrFree(attr->values[0].string.text);
++ attr->values[0].string.text = _cupsStrAlloc("no-hold");
+ }
+
+ default :
+@@ -3989,7 +3999,10 @@
+ job->status_level = CUPSD_LOG_INFO;
+
+ if (job->printer_message)
+- cupsdSetString(&(job->printer_message->values[0].string.text), "");
++ {
++ _cupsStrFree(job->printer_message->values[0].string.text);
++ job->printer_message->values[0].string.text = _cupsStrAlloc("");
++ }
+
+ /*
+ * Create the backchannel pipes and make them non-blocking...
+@@ -4547,10 +4560,15 @@
+
+ if (job->state_value != IPP_JOB_PROCESSING &&
+ job->status_level == CUPSD_LOG_INFO)
+- cupsdSetString(&(job->printer_message->values[0].string.text), "");
++ {
++ _cupsStrFree(job->printer_message->values[0].string.text);
++ job->printer_message->values[0].string.text = _cupsStrAlloc("");
++ }
+ else if (job->printer->state_message[0] && do_message)
+- cupsdSetString(&(job->printer_message->values[0].string.text),
+- job->printer->state_message);
++ {
++ _cupsStrFree(job->printer_message->values[0].string.text);
++ job->printer_message->values[0].string.text = _cupsStrAlloc(job->printer->state_message);
++ }
+
+ /*
+ * ... and the printer-state-reasons value...
diff --git a/patches/source/cups/usb-backend-both-usblp-and-libusb.dpatch b/patches/source/cups/usb-backend-both-usblp-and-libusb.dpatch
new file mode 100644
index 000000000..88ae9d077
--- /dev/null
+++ b/patches/source/cups/usb-backend-both-usblp-and-libusb.dpatch
@@ -0,0 +1,574 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## usb-backend-both-usblp-and-libusb.dpatch by <till.kamppeter@gmail.com>
+##
+## DP: http://www.cups.org/str.php?L3357
+
+@DPATCH@
+diff -urNad cups-1.4.3~/backend/Makefile cups-1.4.3/backend/Makefile
+--- cups-1.4.3~/backend/Makefile 2010-04-09 15:56:03.735720821 +0200
++++ cups-1.4.3/backend/Makefile 2010-04-09 15:56:04.335705387 +0200
+@@ -267,7 +267,7 @@
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o usb usb.o libbackend.a $(LIBUSB) \
+ $(BACKLIBS) $(LIBS)
+-usb.o: usb.c usb-darwin.c usb-libusb.c usb-unix.c
++usb.o: usb.c usb-darwin.c usb-hybrid.c usb-libusb.c usb-unix.c
+
+
+ #
+diff -urNad cups-1.4.3~/backend/ieee1284.c cups-1.4.3/backend/ieee1284.c
+--- cups-1.4.3~/backend/ieee1284.c 2009-12-08 03:13:42.000000000 +0100
++++ cups-1.4.3/backend/ieee1284.c 2010-04-09 15:56:04.335705387 +0200
+@@ -255,6 +255,7 @@
+ cups_option_t *values; /* Keys and values in device ID */
+ const char *mfg, /* Manufacturer */
+ *mdl, /* Model */
++ *des, /* Description */
+ *sern; /* Serial number */
+ char temp[256], /* Temporary manufacturer string */
+ *tempptr; /* Pointer into temp string */
+@@ -285,10 +286,20 @@
+ }
+ else
+ {
+- strlcpy(temp, make_model, sizeof(temp));
++ /*
++ * No manufacturer? Use the model string or description...
++ */
++
++ if (mdl)
++ _ppdNormalizeMakeAndModel(mdl, temp, sizeof(temp));
++ else if ((des = cupsGetOption("DESCRIPTION", num_values, values)) != NULL ||
++ (des = cupsGetOption("DES", num_values, values)) != NULL)
++ _ppdNormalizeMakeAndModel(des, temp, sizeof(temp));
++ else
++ strlcpy(temp, "Unknown", sizeof(temp));
+
+ if ((tempptr = strchr(temp, ' ')) != NULL)
+- *tempptr = '\0';
++ *tempptr = '\0';
+
+ mfg = temp;
+ }
+diff -urNad cups-1.4.3~/backend/usb-hybrid.c cups-1.4.3/backend/usb-hybrid.c
+--- cups-1.4.3~/backend/usb-hybrid.c 1970-01-01 01:00:00.000000000 +0100
++++ cups-1.4.3/backend/usb-hybrid.c 2010-04-09 15:56:04.345707078 +0200
+@@ -0,0 +1,87 @@
++/*
++ * "$Id: usb-hybrid.c 8807 2009-08-31 18:45:43Z mike $"
++ *
++ * USB port backend for the Common UNIX Printing System (CUPS).
++ *
++ * This file is included from "usb.c" when compiled on Linux.
++ *
++ * Copyright 2007-2008 by Apple Inc.
++ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
++ *
++ * 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"
++ * "LICENSE" which should have been included with this file. If this
++ * file is missing or damaged, see the license at "http://www.cups.org/".
++ *
++ * This file is subject to the Apple OS-Developed Software exception.
++ *
++ * Contents:
++ *
++ * print_device() - Print a file to a USB device.
++ * list_devices() - List all USB devices.
++ */
++
++/*
++ * Include necessary headers.
++ */
++
++#include <sys/select.h>
++
++/*
++ * Include the two USB implementations used under Linux ...
++ */
++
++#include "usb-libusb.c"
++#include "usb-unix.c"
++
++/*
++ * 'print_device()' - Print a file to a USB device.
++ */
++
++int /* O - Exit status */
++print_device(const char *uri, /* I - Device URI */
++ const char *hostname, /* I - Hostname/manufacturer */
++ const char *resource, /* I - Resource/modelname */
++ char *options, /* I - Device options/serial number */
++ int print_fd, /* I - File descriptor to print */
++ int copies, /* I - Copies to print */
++ int argc, /* I - Number of command-line arguments (6 or 7) */
++ char *argv[]) /* I - Command-line arguments */
++{
++ int result;
++ for(;;)
++ {
++ result = print_device_unix(uri, hostname, resource, options, print_fd,
++ copies, argc, argv);
++ if (result == -1)
++ {
++ result = print_device_libusb(uri, hostname, resource, options, print_fd,
++ copies, argc, argv);
++ if (result == -1)
++ sleep(5);
++ else
++ return(result);
++ }
++ else
++ return(result);
++ }
++}
++
++/*
++ * 'list_devices()' - List all USB devices.
++ */
++
++void
++list_devices(void)
++{
++ /* Try both discovery methods, each device will appear only under one
++ of them */
++ list_devices_libusb();
++ list_devices_unix();
++}
++
++
++/*
++ * End of "$Id: usb-hybrid.c 8807 2009-08-31 18:45:43Z mike $".
++ */
+diff -urNad cups-1.4.3~/backend/usb-libusb.c cups-1.4.3/backend/usb-libusb.c
+--- cups-1.4.3~/backend/usb-libusb.c 2009-09-11 22:03:31.000000000 +0200
++++ cups-1.4.3/backend/usb-libusb.c 2010-04-09 15:56:04.345707078 +0200
+@@ -13,16 +13,16 @@
+ *
+ * Contents:
+ *
+- * list_devices() - List the available printers.
+- * print_device() - Print a file to a USB device.
++ * list_devices_libusb() - List the available printers.
++ * print_device_libusb() - Print a file to a USB device.
+ * close_device() - Close the connection to the USB printer.
+ * find_device() - Find or enumerate USB printers.
+ * get_device_id() - Get the IEEE-1284 device ID for the printer.
+ * list_cb() - List USB printers for discovery.
+ * make_device_uri() - Create a device URI for a USB printer.
+- * open_device() - Open a connection to the USB printer.
++ * open_device_libusb() - Open a connection to the USB printer.
+ * print_cb() - Find a USB printer for printing.
+- * side_cb() - Handle side-channel requests.
++ * side_cb_libusb() - Handle side-channel requests.
+ */
+
+ /*
+@@ -65,30 +65,30 @@
+ static char *make_device_uri(usb_printer_t *printer,
+ const char *device_id,
+ char *uri, size_t uri_size);
+-static int open_device(usb_printer_t *printer, int verbose);
++static int open_device_libusb(usb_printer_t *printer, int verbose);
+ static int print_cb(usb_printer_t *printer, const char *device_uri,
+ const char *device_id, const void *data);
+-static ssize_t side_cb(usb_printer_t *printer, int print_fd);
++static ssize_t side_cb_libusb(usb_printer_t *printer, int print_fd);
+
+
+ /*
+- * 'list_devices()' - List the available printers.
++ * 'list_devices_libusb()' - List the available printers.
+ */
+
+ void
+-list_devices(void)
++list_devices_libusb(void)
+ {
+- fputs("DEBUG: list_devices\n", stderr);
++ fputs("DEBUG: list_devices_libusb\n", stderr);
+ find_device(list_cb, NULL);
+ }
+
+
+ /*
+- * 'print_device()' - Print a file to a USB device.
++ * 'print_device_libusb()' - Print a file to a USB device.
+ */
+
+ int /* O - Exit status */
+-print_device(const char *uri, /* I - Device URI */
++print_device_libusb(const char *uri, /* I - Device URI */
+ const char *hostname, /* I - Hostname/manufacturer */
+ const char *resource, /* I - Resource/modelname */
+ char *options, /* I - Device options/serial number */
+@@ -105,19 +105,23 @@
+ struct pollfd pfds[2]; /* Poll descriptors */
+
+
+- fputs("DEBUG: print_device\n", stderr);
++ fputs("DEBUG: print_device_libusb\n", stderr);
+
+ /*
+ * Connect to the printer...
+ */
+
++#if defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
++ if ((printer = find_device(print_cb, uri)) == NULL)
++ return(-1);
++#else
+ while ((printer = find_device(print_cb, uri)) == NULL)
+ {
+ _cupsLangPuts(stderr,
+ _("INFO: Waiting for printer to become available...\n"));
+ sleep(5);
+ }
+-
++#endif
+
+ /*
+ * If we are printing data from a print driver on stdin, ignore SIGTERM
+@@ -189,7 +193,7 @@
+
+ if (pfds[1].revents & (POLLIN | POLLHUP))
+ {
+- if ((bytes = side_cb(printer, print_fd)) < 0)
++ if ((bytes = side_cb_libusb(printer, print_fd)) < 0)
+ pfds[1].events = 0; /* Filter has gone away... */
+ else
+ tbytes += bytes;
+@@ -359,7 +363,7 @@
+ printer.iface = iface;
+ printer.handle = NULL;
+
+- if (!open_device(&printer, data != NULL))
++ if (!open_device_libusb(&printer, data != NULL))
+ {
+ if (!get_device_id(&printer, device_id, sizeof(device_id)))
+ {
+@@ -583,6 +587,14 @@
+ mfg = tempmfg;
+ }
+
++ if (!strncasecmp(mdl, mfg, strlen(mfg)))
++ {
++ mdl += strlen(mfg);
++
++ while (isspace(*mdl & 255))
++ mdl ++;
++ }
++
+ /*
+ * Generate the device URI from the manufacturer, model, serial number,
+ * and interface number...
+@@ -611,11 +623,11 @@
+
+
+ /*
+- * 'open_device()' - Open a connection to the USB printer.
++ * 'open_device_libusb()' - Open a connection to the USB printer.
+ */
+
+ static int /* O - 0 on success, -1 on error */
+-open_device(usb_printer_t *printer, /* I - Printer */
++open_device_libusb(usb_printer_t *printer, /* I - Printer */
+ int verbose) /* I - Update connecting-to-device state? */
+ {
+ int number; /* Configuration/interface/altset numbers */
+@@ -733,16 +745,73 @@
+ const char *device_id, /* I - IEEE-1284 device ID */
+ const void *data) /* I - User data (make, model, S/N) */
+ {
+- return (!strcmp((char *)data, device_uri));
++ char *uri = (char *)data,
++ *str1,
++ *str2,
++ buf[255],
++ requested_uri[1024];
++
++ /* Work on a copy of uri */
++ strncpy(requested_uri, uri, sizeof(requested_uri));
++ requested_uri[sizeof(requested_uri) - 1] = '\0';
++
++ /*
++ * libusb-discovered URIs can have an "interface" specification and this
++ * never happens for usblp-discovered URIs, so remove the "interface"
++ * specification from the URI which we are checking currently. This way a
++ * queue for a usblp-discovered printer can now be accessed via libusb
++ */
++ if (((str1 = strstr(requested_uri, "interface=")) == NULL) &&
++ ((str2 = strstr(device_uri, "interface=")) != NULL))
++ {
++ *(str2 - 1) = '\0';
++ }
++
++ /*
++ * Old URI with "serial=?". Cut this part off and consider this as
++ * an URI without serial number
++ */
++ if ((str1 = strstr(requested_uri, "serial=?")) != NULL)
++ *(str1 - 1) = '\0';
++
++ /*
++ * Old URI without serial number. Match it also with URIs with serial
++ * number
++ */
++ if (((str1 = strstr(requested_uri, "serial=")) == NULL) &&
++ ((str2 = strstr(device_uri, "serial=")) != NULL))
++ *(str2 - 1) = '\0';
++
++ /*
++ * libusb-discovered URIs can have a "serial" specification when the
++ * usblp-discovered URI for the same printer does not have one, as
++ * with libusb we can discover serial numbers also with other methods
++ * than only via the device ID. Therefore we accept also a
++ * usblp-discovered printer without serial number as a match. This we
++ * do by removing the serial number from the queue's (libusb-discovered)
++ * URI before comparing. Also warn the user because of the incapability
++ * of the usblp-based access to distinguish printers by the serial
++ * number.
++ */
++ if (((str1 = strstr(requested_uri, "serial=")) == NULL) &&
++ ((str2 = strstr(device_uri, "serial=")) != NULL))
++ {
++ *(str2 - 1) = '\0';
++ if (backendGetMakeModel(device_id, buf, sizeof(buf)) == 0)
++ fprintf(stderr, "WARNING: If you have more than one %s printer connected to this machine, please make sure that the \"usblp\" kernel module is always unloaded (and blacklisted) and re-create the queues for these printers. Otherwise CUPS will not be able to distinguish them.\n",
++ buf);
++ }
++
++ return (!strcmp(requested_uri, device_uri));
+ }
+
+
+ /*
+- * 'side_cb()' - Handle side-channel requests.
++ * 'side_cb_libusb()' - Handle side-channel requests.
+ */
+
+ static ssize_t /* O - Number of bytes written */
+-side_cb(usb_printer_t *printer, /* I - Printer */
++side_cb_libusb(usb_printer_t *printer, /* I - Printer */
+ int print_fd) /* I - File to print */
+ {
+ ssize_t bytes, /* Bytes read/written */
+diff -urNad cups-1.4.3~/backend/usb-unix.c cups-1.4.3/backend/usb-unix.c
+--- cups-1.4.3~/backend/usb-unix.c 2009-12-08 03:13:42.000000000 +0100
++++ cups-1.4.3/backend/usb-unix.c 2010-04-09 15:56:30.799666933 +0200
+@@ -18,10 +18,10 @@
+ *
+ * Contents:
+ *
+- * print_device() - Print a file to a USB device.
+- * list_devices() - List all USB devices.
+- * open_device() - Open a USB device...
+- * side_cb() - Handle side-channel requests...
++ * print_device_unix() - Print a file to a USB device.
++ * list_devices_unix() - List all USB devices.
++ * open_device_unix() - Open a USB device...
++ * side_cb_unix() - Handle side-channel requests...
+ */
+
+ /*
+@@ -35,17 +35,17 @@
+ * Local functions...
+ */
+
+-static int open_device(const char *uri, int *use_bc);
+-static int side_cb(int print_fd, int device_fd, int snmp_fd,
++static int open_device_unix(const char *uri, int *use_bc);
++static int side_cb_unix(int print_fd, int device_fd, int snmp_fd,
+ http_addr_t *addr, int use_bc);
+
+
+ /*
+- * 'print_device()' - Print a file to a USB device.
++ * 'print_device_unix()' - Print a file to a USB device.
+ */
+
+ int /* O - Exit status */
+-print_device(const char *uri, /* I - Device URI */
++print_device_unix(const char *uri, /* I - Device URI */
+ const char *hostname, /* I - Hostname/manufacturer */
+ const char *resource, /* I - Resource/modelname */
+ char *options, /* I - Device options/serial number */
+@@ -102,7 +102,7 @@
+ strncasecmp(hostname, "Minolta", 7);
+ #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */
+
+- if ((device_fd = open_device(uri, &use_bc)) == -1)
++ if ((device_fd = open_device_unix(uri, &use_bc)) == -1)
+ {
+ if (getenv("CLASS") != NULL)
+ {
+@@ -132,6 +132,10 @@
+ _("INFO: Printer busy; will retry in 10 seconds...\n"));
+ sleep(10);
+ }
++#ifdef HAVE_USB_H
++ else
++ return (-1);
++#else
+ else if (errno == ENXIO || errno == EIO || errno == ENOENT ||
+ errno == ENODEV)
+ {
+@@ -147,6 +151,7 @@
+ resource, strerror(errno));
+ return (CUPS_BACKEND_FAILED);
+ }
++#endif
+ }
+ }
+ while (device_fd < 0);
+@@ -190,7 +195,7 @@
+ tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, NULL);
+
+ #else
+- tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb);
++ tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb_unix);
+ #endif /* __sun */
+
+ if (print_fd != 0 && tbytes >= 0)
+@@ -214,11 +219,11 @@
+
+
+ /*
+- * 'list_devices()' - List all USB devices.
++ * 'list_devices_unix()' - List all USB devices.
+ */
+
+ void
+-list_devices(void)
++list_devices_unix(void)
+ {
+ #ifdef __linux
+ int i; /* Looping var */
+@@ -320,11 +325,11 @@
+
+
+ /*
+- * 'open_device()' - Open a USB device...
++ * 'open_device_unix()' - Open a USB device...
+ */
+
+ static int /* O - File descriptor or -1 on error */
+-open_device(const char *uri, /* I - Device URI */
++open_device_unix(const char *uri, /* I - Device URI */
+ int *use_bc) /* O - Set to 0 for unidirectional */
+ {
+ int fd; /* File descriptor */
+@@ -357,9 +362,12 @@
+ char device[255], /* Device filename */
+ device_id[1024], /* Device ID string */
+ make_model[1024], /* Make and model */
+- device_uri[1024]; /* Device URI string */
+-
++ device_uri[1024], /* Device URI string */
++ requested_uri[1024], /* Device URI string */
++ *str1,
++ *str2;
+
++
+ /*
+ * Find the correct USB device...
+ */
+@@ -407,7 +415,55 @@
+ device_uri[0] = '\0';
+ }
+
+- if (!strcmp(uri, device_uri))
++ /* Work on a copy of uri */
++ strncpy(requested_uri, uri, sizeof(requested_uri));
++ requested_uri[sizeof(requested_uri) - 1] = '\0';
++
++ /*
++ * libusb-discovered URIs can have an "interface" specification and this
++ * never happens for usblp-discovered URIs, so remove the "interface"
++ * specification from the URI of the print queue. This way a queue for
++ * a libusb-discovered printer can now be accessed via the usblip kernel
++ * module
++ */
++ if ((str1 = strstr(requested_uri, "interface=")) != NULL)
++ *(str1 - 1) = '\0';
++
++ /*
++ * Old URI with "serial=?". Cut this part off and consider this as
++ * an URI without serial number
++ */
++ if ((str1 = strstr(requested_uri, "serial=?")) != NULL)
++ *(str1 - 1) = '\0';
++
++ /*
++ * Old URI without serial number. Match it also with URIs with serial
++ * number
++ */
++ if (((str1 = strstr(requested_uri, "serial=")) == NULL) &&
++ ((str2 = strstr(device_uri, "serial=")) != NULL))
++ *(str2 - 1) = '\0';
++
++ /*
++ * libusb-discovered URIs can have a "serial" specification when the
++ * usblp-discovered URI for the same printer does not have one, as
++ * with libusb we can discover serial numbers also with other methods
++ * than only via the device ID. Therefore we accept also a
++ * usblp-discovered printer without serial number as a match. This we
++ * do by removing the serial number from the queue's (libusb-discovered)
++ * URI before comparing. Also warn the user because of the incapability
++ * of the usblp-based access to distinguish printers by the serial
++ * number.
++ */
++ if (((str1 = strstr(requested_uri, "serial=")) != NULL) &&
++ ((str2 = strstr(device_uri, "serial=")) == NULL))
++ {
++ *(str1 - 1) = '\0';
++ fprintf(stderr, "WARNING: If you have more than one %s printer connected to this machine, please unload (and blacklist) the \"usblp\" kernel module as otherwise CUPS will not be able to distinguish your printers.\n",
++ make_model);
++ }
++
++ if (!strcmp(requested_uri, device_uri))
+ {
+ /*
+ * Yes, return this file descriptor...
+@@ -433,10 +489,14 @@
+ */
+
+ if (busy)
++ {
+ _cupsLangPuts(stderr,
+ _("INFO: Printer busy; will retry in 5 seconds...\n"));
+
+- sleep(5);
++ sleep(5);
++ }
++ else
++ return -1;
+ }
+ }
+ #elif defined(__sun) && defined(ECPPIOC_GETDEVID)
+@@ -557,11 +617,11 @@
+
+
+ /*
+- * 'side_cb()' - Handle side-channel requests...
++ * 'side_cb_unix()' - Handle side-channel requests...
+ */
+
+ static int /* O - 0 on success, -1 on error */
+-side_cb(int print_fd, /* I - Print file */
++side_cb_unix(int print_fd, /* I - Print file */
+ int device_fd, /* I - Device file */
+ int snmp_fd, /* I - SNMP socket (unused) */
+ http_addr_t *addr, /* I - Device address (unused) */
+diff -urNad cups-1.4.3~/backend/usb.c cups-1.4.3/backend/usb.c
+--- cups-1.4.3~/backend/usb.c 2008-06-24 03:28:36.000000000 +0200
++++ cups-1.4.3/backend/usb.c 2010-04-09 15:56:04.345707078 +0200
+@@ -56,7 +56,7 @@
+ */
+
+ #ifdef HAVE_USB_H
+-# include "usb-libusb.c"
++# include "usb-hybrid.c"
+ #elif defined(__APPLE__)
+ # include "usb-darwin.c"
+ #elif defined(__linux) || defined(__sun) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)