diff --git a/SOURCES/cups-autostart-when-enabled.patch b/SOURCES/cups-autostart-when-enabled.patch
new file mode 100644
index 0000000..1cdefb6
--- /dev/null
+++ b/SOURCES/cups-autostart-when-enabled.patch
@@ -0,0 +1,10 @@
+diff --git a/scheduler/org.cups.cupsd.service.in b/scheduler/org.cups.cupsd.service.in
+index 307d69b..add238b 100644
+--- a/scheduler/org.cups.cupsd.service.in
++++ b/scheduler/org.cups.cupsd.service.in
+@@ -10,4 +10,4 @@ Restart=on-failure
+ 
+ [Install]
+ Also=cups.socket cups.path
+-WantedBy=printer.target
++WantedBy=printer.target multi-user.target
diff --git a/SOURCES/cups-dirtyclean.patch b/SOURCES/cups-dirtyclean.patch
new file mode 100644
index 0000000..390ed19
--- /dev/null
+++ b/SOURCES/cups-dirtyclean.patch
@@ -0,0 +1,13 @@
+diff --git a/scheduler/main.c b/scheduler/main.c
+index 592531a..a6e2c3a 100644
+--- a/scheduler/main.c
++++ b/scheduler/main.c
+@@ -947,7 +947,7 @@ main(int  argc,				/* I - Number of command-line args */
+     * Write dirty config/state files...
+     */
+ 
+-    if (DirtyCleanTime && current_time >= DirtyCleanTime && cupsArrayCount(Clients) == 0)
++    if (DirtyCleanTime && current_time >= DirtyCleanTime)
+       cupsdCleanDirty();
+ 
+ #ifdef __APPLE__
diff --git a/SOURCES/cups-etimedout.patch b/SOURCES/cups-etimedout.patch
new file mode 100644
index 0000000..31defda
--- /dev/null
+++ b/SOURCES/cups-etimedout.patch
@@ -0,0 +1,25 @@
+diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c
+index e4ffc3d..a989055 100644
+--- a/cups/http-addrlist.c
++++ b/cups/http-addrlist.c
+@@ -240,7 +240,10 @@ httpAddrConnect2(
+     }
+ 
+     if (!addrlist && nfds == 0)
++    {
++      errno = EHOSTDOWN;
+       break;
++    }
+ 
+    /*
+     * See if we can connect to any of the addresses so far...
+@@ -371,6 +374,9 @@ httpAddrConnect2(
+       remaining -= 250;
+   }
+ 
++  if (remaining <= 0)
++    errno = ETIMEDOUT;
++
+   while (nfds > 0)
+   {
+     nfds --;
diff --git a/SOURCES/cups-failover-backend.patch b/SOURCES/cups-failover-backend.patch
new file mode 100644
index 0000000..a92dad8
--- /dev/null
+++ b/SOURCES/cups-failover-backend.patch
@@ -0,0 +1,877 @@
+diff --git a/backend/Makefile b/backend/Makefile
+index 3038682..6642016 100644
+--- a/backend/Makefile
++++ b/backend/Makefile
+@@ -28,6 +28,7 @@ include ../Makedefs
+ RBACKENDS =	\
+ 		ipp \
+ 		lpd \
++		failover \
+ 		$(DNSSD_BACKEND)
+ UBACKENDS =	\
+ 		snmp \
+@@ -51,6 +52,7 @@ LIBOBJS	=	\
+ OBJS	=	\
+ 		ipp.o \
+ 		lpd.o \
++		failover.o \
+ 		dnssd.o \
+ 		snmp.o \
+ 		socket.o \
+@@ -275,6 +277,13 @@ lpd:	lpd.o ../cups/$(LIBCUPS) libbackend.a
+ 	echo Linking $@...
+ 	$(LD_CC) $(LDFLAGS) -o lpd lpd.o libbackend.a $(LIBS)
+ 
++#
++# failover
++#
++
++failover:	failover.o ../cups/$(LIBCUPS) libbackend.a
++	echo Linking $@...
++	$(LD_CC) $(LDFLAGS) -o failover failover.o libbackend.a $(LIBS)
+ 
+ #
+ # snmp
+diff --git a/backend/failover.c b/backend/failover.c
+new file mode 100644
+index 0000000..9affd8f
+--- /dev/null
++++ b/backend/failover.c
+@@ -0,0 +1,837 @@
++/*
++ * Failover Backend for the Common UNIX Printing System (CUPS).
++ *
++ * Copyright (c) 2014, Red Hat, Inc.
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * * Redistributions of source code must retain the above copyright
++ *   notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ *   notice, this list of conditions and the following disclaimer in the
++ *   documentation and/or other materials provided with the distribution.
++ * * Neither the name of Red Hat, Inc. nor the names of its contributors
++ *   may be used to endorse or promote products derived from this software
++ *   without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "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 RED HAT,
++ * INC.  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.
++ *
++ * Original version by Clark Hale, Red Hat, Inc.
++ *
++ * This backend presents a fake printer that will choose the first
++ * available printer from a list of IPP URIs.
++ *
++ * Option failover contains a comma separated list of IPP URIs.  The
++ * URIs are attempted in-order.
++ *
++ * Option failover-retries contains an integer that indicates how many
++ * times to iterate through the failover list before completely
++ * failing.
++ *
++ * Contents:
++ *   main()                   - Checks each printer in a failover list, and
++ *                              sends job data to the first available printer
++ *   move_job()               - Sends and IPP Move-Job request
++ *   check_printer()          - Checks a printer's attributes to see
++ *                              if it's enabled and accepting jobs
++ *   read_config()            - Read the backends configuration from
++ *                              options
++ *   get_printer_attributes() - Sends an IPP Get-Attributes request to
++ *                              a URI
++ *   sigterm_handler()        - Handle SIGTERM that cancels the job
++ *   password_cb()            - Password call back used to disable password
++ *                              prompt
++ */
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/wait.h>
++#include <cups/http-private.h>
++#include <cups/http.h>
++#include "backend-private.h"
++
++/*
++ * Return Values
++ */
++typedef enum fo_state_e
++{
++  FO_PRINTER_GOOD = 0,
++  FO_PRINTER_BAD,
++  FO_PRINTER_BUSY,
++  FO_AUTH_REQUIRED
++} fo_state_t;
++
++/*
++ * Constants
++ */
++#define FAILOVER_DEFAULT_RETRIES        (3)
++#define FAILOVER_PASSWORD_RETRIES_MAX   (3)
++
++/*
++ * Local Functions
++ */
++static       int   check_printer(const char *device_uri);
++static       int   read_config(cups_array_t *printer_array, int *retries,
++                               const char *options);
++static       int   get_printer_attributes(const char *device_uri,
++                                          ipp_t **attributes);
++static       int   move_job(int jobid, const char *dest);
++static       void  sigterm_handler(int sig);
++static const char *password_cb(const char *);
++
++/*
++ * Global Variables
++ */
++static int         job_canceled = 0;     /* Job canceled */
++static char       *password = NULL;      /* password for device */
++static int         password_retries = 0;
++static const char *auth_info_required = "none";
++
++/*
++ * 'main()' - Checks each printer in a failover list, and
++ *            sends job data to the first available printer
++ * Usage:
++ *    printer-uri job-id user title copies options [file]
++ *
++ *    The printer-uri option is not used, but it still required to fit
++ *    to the backend(7) standards.
++ */
++int
++main(int argc, char *argv[])
++{
++  const char   *selected_uri = NULL;      /* URI of selected printer     */
++  const char   *tmp_device_uri;           /* Device URI to check         */
++  cups_array_t *printer_array;            /* Array of available printers */
++  int           printer_count = 0;        /* current printer array index */
++  int           retry_max = 1;            /* maximum retries before exit */
++  int           retry_count = 0;          /* current retry number        */
++  int           auth_failed_count = 0;    /* auth failures per loop      */
++  int           rc = CUPS_BACKEND_OK;
++#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
++  struct        sigaction action;       /* Actions for POSIX signals */
++#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
++
++ /*
++  * Check args
++  */
++  if (argc == 1)
++  {
++   /*
++    * print out discovery data
++    */
++    char *backendName;
++
++    if ((backendName = strrchr(argv[0], '/')) != NULL)
++      backendName++;
++    else
++      backendName = argv[0];
++
++    _cupsLangPrintf(stderr,"network %s \"Unknown\" \"%s (%s)\"\n",
++                    backendName,
++                    _cupsLangString(cupsLangDefault(), _("Failover Printer")),
++                    backendName);
++
++    return (CUPS_BACKEND_OK);
++  }
++  else if (argc < 6)
++  {
++    _cupsLangPrintf(stderr,
++                    _("Usage: %s job-id user title copies options [file]"),
++                    argv[0]);
++    return (CUPS_BACKEND_STOP);
++  }
++
++  fprintf(stderr, "DEBUG: Failover backend starting up.\n");
++
++ /*
++  * Don't buffer status messages
++  */
++  setbuf(stderr, NULL);
++
++ /*
++  * Ignore SIGPIPE and catch SIGTERM signals...
++  */
++#ifdef HAVE_SIGSET
++  sigset(SIGPIPE, SIG_IGN);
++  sigset(SIGTERM, sigterm_handler);
++#elif defined(HAVE_SIGACTION)
++  memset(&action, 0, sizeof(action));
++  action.sa_handler = SIG_IGN;
++  sigaction(SIGPIPE, &action, NULL);
++
++  sigemptyset(&action.sa_mask);
++  sigaddset(&action.sa_mask, SIGTERM);
++  action.sa_handler = sigterm_handler;
++  sigaction(SIGTERM, &action, NULL);
++#else
++  signal(SIGPIPE, SIG_IGN);
++  signal(SIGTERM, sigterm_handler);
++#endif /* HAVE_SIGSET */
++
++  printer_array = cupsArrayNew(NULL, NULL);
++
++ /*
++  * Read Configuration
++  */
++  if ((rc = read_config(printer_array, &retry_max,
++                        argv[5])) != CUPS_BACKEND_OK)
++  {
++    fprintf(stderr, "ERROR: Failed to read configuration options!\n");
++    goto cleanup;
++  }
++
++ /*
++  * Main Retry Loop
++  */
++  for (retry_count = 0; retry_count < retry_max; retry_count++)
++  {
++    fprintf(stderr, "DEBUG: Retry loop #%d\n", retry_count + 1);
++
++   /*
++    * Reset Counters
++    */
++    printer_count = 0;
++    auth_failed_count = 0;
++
++    tmp_device_uri = (char *)cupsArrayFirst(printer_array);
++
++    do
++    {
++      if (job_canceled)
++      {
++        fprintf(stderr, "DEBUG: Job Canceled\n");
++        goto cleanup;
++      }
++
++      fprintf(stderr,"DEBUG: Checking printer #%d: %s\n",
++              printer_count+1, tmp_device_uri);
++
++      rc = check_printer(tmp_device_uri);
++
++      // Printer is available and not busy.
++      if ( rc == FO_PRINTER_GOOD )
++      {
++        selected_uri = tmp_device_uri;
++        break;
++      }
++      // Printer is busy
++      else if (rc == FO_PRINTER_BUSY)
++      {
++        fprintf(stderr, "DEBUG: Waiting for job to complete.\n");
++        sleep(2);
++        continue;
++      }
++      // Authorization is required to access the printer.
++      else if (rc == FO_AUTH_REQUIRED)
++      {
++        auth_failed_count++;
++        fprintf(stderr, "DEBUG: auth_failed_count = %d\n", auth_failed_count);
++      }
++      // Printer is stopped or not accepting jobs
++      else
++      {
++        if (!printer_count)
++          fprintf(stderr, "INFO: Primary Printer, %s, not available.  "
++                  "Attempting Failovers...\n",
++                  tmp_device_uri);
++        else
++          fprintf(stderr, "INFO: Failover Printer, %s, not available.  "
++                  "Attempting Failovers..\n",
++                  tmp_device_uri);
++        printer_count++;
++        tmp_device_uri = (char *)cupsArrayNext(printer_array);
++      }
++    } while (tmp_device_uri != NULL);
++
++    if (selected_uri && !printer_count)
++      fprintf(stderr, "STATE: -primary-printer-failed\n");
++    else
++      fprintf(stderr, "STATE: +primary-printer-failed\n");
++
++    if (job_canceled)
++    {
++      fprintf(stderr, "DEBUG: Job Canceled\n");
++      goto cleanup;
++    }
++
++    if (!selected_uri && auth_failed_count == printer_count)
++    {
++      fprintf(stderr, "ERROR:  All failover printers failed with "
++              "authorization issues.\n");
++      rc = CUPS_BACKEND_AUTH_REQUIRED;
++      fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
++      goto cleanup;
++    }
++    else if (!selected_uri && retry_count + 1 < retry_max)
++    {
++      fprintf(stderr, "INFO: No suitable printer found...retrying...\n");
++      sleep(2);
++      continue;
++    }
++    else if (selected_uri)
++    {
++      fprintf(stderr, "DEBUG: Using printer, %s.\n", selected_uri);
++      break;
++    }
++  }
++
++  if (!selected_uri)
++  {
++    fprintf(stderr, "ERROR: No suitable printer found.  Aborting print\n");
++    rc = CUPS_BACKEND_FAILED;
++    goto cleanup;
++  }
++
++  rc = move_job(atoi(argv[1]), selected_uri);
++
++  if (job_canceled)
++    rc = CUPS_BACKEND_OK;
++
++cleanup :
++  if (job_canceled)
++    rc = CUPS_BACKEND_OK;
++
++  tmp_device_uri = (char *)cupsArrayFirst(printer_array);
++  do
++  {
++    free((void *)tmp_device_uri);
++  } while ((tmp_device_uri = (char *)cupsArrayNext(printer_array)) != NULL);
++
++  cupsArrayDelete(printer_array);
++  sleep(2);
++  return (rc);
++}
++
++/*
++ * 'check_printer()' - Checks the status of a remote printer and returns
++ *                     back a good/bad/busy status.
++ */
++int
++check_printer(const char *device_uri)
++{
++  ipp_t           *attributes = NULL;     /* attributes for device_uri */
++  ipp_attribute_t *tmp_attribute;         /* for examining attribs     */
++  int              rc = FO_PRINTER_GOOD;  /* return code               */
++  char            *reason;                /* printer state reason */
++  int              i;
++
++  fprintf(stderr, "DEBUG: Checking printer %s\n",device_uri);
++
++  rc = get_printer_attributes(device_uri, &attributes);
++  if ( rc != CUPS_BACKEND_OK )
++  {
++    fprintf(stderr, "DEBUG: Failed to get attributes from printer: %s\n",
++            device_uri);
++    if ( rc == CUPS_BACKEND_AUTH_REQUIRED )
++      return (FO_AUTH_REQUIRED);
++    else
++      return (FO_PRINTER_BAD);
++  }
++
++ /*
++  * Check if printer is accepting jobs
++  */
++  if ((tmp_attribute = ippFindAttribute(attributes,
++                                        "printer-is-accepting-jobs",
++                                        IPP_TAG_BOOLEAN)) != NULL &&
++      !tmp_attribute->values[0].boolean)
++  {
++    fprintf(stderr,
++            "DEBUG: Printer, %s, is not accepting jobs.\n",
++            device_uri);
++
++    rc = FO_PRINTER_BAD;
++  }
++
++ /*
++  * Check if printer is stopped or busy processing
++  */
++  if ((tmp_attribute = ippFindAttribute(attributes,
++                                        "printer-state",
++                                        IPP_TAG_ENUM)) != NULL)
++  {
++    // Printer Stopped
++    if ( tmp_attribute->values[0].integer == IPP_PRINTER_STOPPED )
++    {
++      fprintf(stderr, "DEBUG: Printer, %s, stopped.\n", device_uri);
++      rc = FO_PRINTER_BAD;
++    }
++    // Printer Busy
++    else if ( tmp_attribute->values[0].integer == IPP_PRINTER_PROCESSING )
++    {
++      fprintf(stderr, "DEBUG: Printer %s is busy.\n", device_uri);
++      rc = FO_PRINTER_BUSY;
++    }
++  }
++
++  /*
++   * Parse through the printer-state-reasons
++   */
++  if ((tmp_attribute = ippFindAttribute(attributes, "printer-state-reasons",
++                                        IPP_TAG_KEYWORD)) != NULL)
++  {
++    for (i = 0; i < tmp_attribute->num_values; i++)
++    {
++      reason = tmp_attribute->values[i].string.text;
++      int len = strlen(reason);
++
++      if (len > 8 && !strcmp(reason + len - 8, "-warning"))
++      {
++        fprintf(stderr, "DEBUG: Printer Supply Warning, %s\n", reason);
++        rc = FO_PRINTER_BAD;
++      }
++      else if (len > 6 && !strcmp(reason + len - 6, "-error"))
++      {
++        fprintf(stderr, "DEBUG: Printer Supply Error, %s\n", reason);
++        rc = FO_PRINTER_BAD;
++      }
++    }
++  }
++
++  return (rc);
++}
++
++/*
++ * 'read_config()' - Parses the failover and failover-retries options
++ *
++ */
++static int
++read_config(cups_array_t *printer_array, int *retries, const char *options)
++{
++
++  const char    *tmp;                   /* temporary ptr                     */
++  char          *tok_tmp;               /* temporary ptr for option  parsing */
++  int            jobopts_count = 0;     /* number of options                 */
++  cups_option_t *jobopts = NULL;        /* job options                       */
++
++
++  fprintf(stderr, "DEBUG: Reading Configuration.\n");
++  jobopts_count = cupsParseOptions(options, 0, &jobopts);
++
++  if (!jobopts_count)
++  {
++    fprintf(stderr,
++            "ERROR: No job options!  Cannot find failover options!\n");
++    return (CUPS_BACKEND_STOP);
++  }
++
++ /*
++  * Get attributes from the primary printer
++  */
++  fprintf(stderr, "DEBUG: Searching for failover option.\n");
++
++  if ((tmp = cupsGetOption("failover", jobopts_count, jobopts)) != NULL)
++  {
++    fprintf(stderr, "DEBUG: Failover option contents: %s.\n", tmp);
++
++    tok_tmp = strdup(tmp);
++
++    tmp = strtok(tok_tmp, ",");
++    do
++    {
++      cupsArrayAdd(printer_array, strdup(tmp));
++    } while ((tmp = strtok(NULL,",")) != NULL);
++
++    free(tok_tmp);
++  }
++  else
++  {
++   /*
++    * The queue is misconfigured, so return back CUPS_BACKEND_STOP
++    */
++    fprintf(stderr, "ERROR: failover option not specified!\n");
++    return (CUPS_BACKEND_STOP);
++  }
++
++ /*
++  * Get the failover-retries value, if it exists.
++  */
++  fprintf(stderr, "DEBUG: Searching for failover-retries option.\n");
++
++  if ((tmp = cupsGetOption("failover-retries",
++                           jobopts_count, jobopts)) != NULL)
++  {
++    fprintf(stderr, "DEBUG: failover-retries option contents: %s.\n", tmp);
++    *retries = atoi(tmp);
++  }
++  else
++  {
++    *retries = FAILOVER_DEFAULT_RETRIES;
++    fprintf(stderr, "DEBUG: Failed to get failover-retries option\n");
++    fprintf(stderr, "DEBUG: Defaulted to %d retries\n", *retries);
++  }
++
++  return (CUPS_BACKEND_OK);
++}
++
++/*
++ * 'get_printer_attributes()' - Sends an IPP Get-Attributes request to
++ *                              a URI
++ */
++int
++get_printer_attributes(const char *device_uri, ipp_t **attributes)
++{
++  char               uri[HTTP_MAX_URI];         /* Updated URI without login */
++  int                version;                   /* IPP version */
++  char               scheme[256];               /* Scheme in URI */
++  ipp_status_t       ipp_status;                /* Status of IPP request */
++  char               hostname[1024];            /* Hostname */
++  char               resource[1024];            /* Resource infoo */
++  char               addrname[256];             /* Address name */
++  int                port;                      /* IPP Port number */
++  char               portname[255];             /* Port as string */
++  http_t            *http;                      /* HTTP connection */
++  ipp_t             *request;                   /* IPP request */
++  int                rc = CUPS_BACKEND_OK;      /* Return Code */
++  char               username[256];             /* Username for device URI */
++  char              *option_ptr;                /* for parsing resource opts */
++  const char * const pattrs[] =                 /* Printer attributes wanted */
++    {
++      "printer-is-accepting-jobs",
++      "printer-state",
++      "printer-state-reasons"
++    };
++
++  if (job_canceled)
++    return (CUPS_BACKEND_OK);
++
++  fprintf(stderr, "DEBUG: Getting Printer Attributes.\n");
++  fprintf(stderr, "DEBUG: Device URL %s.\n", device_uri);
++
++ /*
++  * Parse device_uri
++  */
++  if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
++                     username, sizeof(username), hostname, sizeof(hostname),
++                     &port, resource, sizeof(resource)) != HTTP_URI_OK)
++  {
++    fprintf(stderr, "ERROR: Problem parsing device_uri, %s\n", device_uri);
++    return (CUPS_BACKEND_STOP);
++  }
++
++  if (!port)
++    port = IPP_PORT;
++
++  sprintf(portname, "%d", port);
++
++  fprintf(stderr, "DEBUG: Getting Printer Attributes.\n");
++
++ /*
++  * Configure password
++  */
++  cupsSetPasswordCB(password_cb);
++
++ /*
++  * reset, in case a previous attempt for
++  * another printer left residue
++  */
++  cupsSetUser(NULL);
++  password = NULL;
++  password_retries = 0;
++
++  if (*username)
++  {
++    if ((password = strchr(username, ':')) != NULL)
++    {
++      *password = '\0';
++      password++;
++    }
++
++    cupsSetUser(username);
++  }
++  else if (!getuid())
++  {
++    const char *username_env;
++
++    if ((username_env = getenv("AUTH_USERNAME")) != NULL)
++    {
++      cupsSetUser(username_env);
++      password = getenv("AUTH_PASSWORD");
++    }
++  }
++
++ /*
++  * Try connecting to the remote server...
++  */
++  fprintf(stderr, "DEBUG: Connecting to %s:%d\n", hostname, port);
++  _cupsLangPuts(stderr, _("INFO: Connecting to printer...\n"));
++
++  http = httpConnectEncrypt(hostname, port, cupsEncryption());
++
++ /*
++  * Deal the socket not being open.
++  */
++  if (!http)
++  {
++    int error = errno;          /* Connection error */
++
++    switch (error)
++    {
++    case EHOSTDOWN :
++      _cupsLangPuts(stderr, _("WARNING: "
++                              "The printer may not exist or "
++                              "is unavailable at this time.\n"));
++      break;
++    case EHOSTUNREACH :
++      _cupsLangPuts(stderr, _("WARNING: "
++                              "The printer is unreachable at this "
++                              "time.\n"));
++      break;
++    case ECONNREFUSED :
++      _cupsLangPuts(stderr, _("WARNING: "
++                              "Connection Refused.\n"));
++      break;
++    default :
++      fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno));
++      break;
++    }
++
++    rc = CUPS_BACKEND_FAILED;
++    sleep(5);
++    goto prt_available_cleanup;
++  }
++
++
++#ifdef AF_INET6
++  if (http->hostaddr->addr.sa_family == AF_INET6)
++    fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n",
++            httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
++            ntohs(http->hostaddr->ipv6.sin6_port));
++  else
++#endif /* AF_INET6 */
++  if (http->hostaddr->addr.sa_family == AF_INET)
++    fprintf(stderr, "DEBUG: Connected to %s:%d (IPv4)...\n",
++            httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
++            ntohs(http->hostaddr->ipv4.sin_port));
++
++ /*
++  * Search the resource string for options.
++  * We only care about version, for the moment.
++  */
++  version = 11;
++
++  if ((option_ptr = strchr(resource, '?')) != NULL)
++  {
++    *option_ptr++ = '\0';
++
++    if ((option_ptr = strstr(option_ptr, "version="))!=NULL)
++    {
++      int   minor;       /* minor version from URI */
++      int   major;       /* major version from URI */
++      char *version_str; /* ipp version */
++
++      option_ptr += 8;
++      version_str = option_ptr;
++
++      while (*option_ptr && *option_ptr != '&' && *option_ptr != '+')
++        option_ptr++;
++
++      if (*option_ptr)
++        *option_ptr = '\0';
++
++      sscanf(version_str, "%d.%d", &major, &minor);
++
++      version = (major * 10) + minor;
++
++      switch(version)
++      {
++      case 10 :
++      case 11 :
++      case 20 :
++      case 21 :
++        fprintf(stderr,
++                "DEBUG: Set version to %d from URI\n",
++                version);
++        break;
++      default :
++        _cupsLangPrintf(stderr,
++                        _("DEBUG: Invalid version, %d, from URI.  "
++                          "Using default of 1.1 \n"),
++                        version);
++        version = 11;
++      }
++    }
++  }
++
++
++ /*
++  * Build a URI for the printer.  We can't use the URI in argv[0]
++  * because it might contain username:password information...
++  */
++  if (httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, NULL,
++                      hostname, port, resource) != HTTP_URI_OK)
++  {
++    fprintf(stderr, "ERROR: Problem assembling printer URI from host %s, "
++            "port %d, resource %s\n", hostname, port, resource);
++    return (CUPS_BACKEND_STOP);
++  }
++
++ /*
++  * Build the IPP request...
++  */
++  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
++  request->request.op.version[0] = version / 10;
++  request->request.op.version[1] = version % 10;
++
++  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
++               NULL, uri);
++
++  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
++                "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
++                NULL, pattrs);
++
++ /*
++  * Do the request...
++  */
++  fputs("DEBUG: Getting supported attributes...\n", stderr);
++
++  fprintf(stderr, "DEBUG: IPP Request Structure Built.\n");
++
++  *attributes = cupsDoRequest(http, request, resource);
++  ipp_status = cupsLastError();
++
++  fprintf(stderr, "DEBUG: Get-Printer-Attributes: %s (%s)\n",
++          ippErrorString(ipp_status), cupsLastErrorString());
++
++  if (ipp_status > IPP_OK_CONFLICT)
++  {
++    fprintf(stderr, "DEBUG: Get-Printer-Attributes returned %s.\n",
++            ippErrorString(ipp_status));
++    switch(ipp_status)
++    {
++    case IPP_FORBIDDEN :
++    case IPP_NOT_AUTHORIZED :
++      _cupsLangPuts(stderr, _("ERROR: Not Authorized.\n"));
++      rc = CUPS_BACKEND_AUTH_REQUIRED;
++      break;
++    case IPP_PRINTER_BUSY :
++    case IPP_SERVICE_UNAVAILABLE :
++      _cupsLangPuts(stderr, _("ERROR: "
++                              "The printer is not responding.\n"));
++      rc = CUPS_BACKEND_FAILED;
++      break;
++    case IPP_BAD_REQUEST :
++    case IPP_VERSION_NOT_SUPPORTED :
++      fprintf(stderr, "ERROR: Destination does not support IPP version %d\n",
++              version);
++    case IPP_NOT_FOUND :
++      _cupsLangPuts(stderr, _("ERROR: "
++                              "The printer configuration is incorrect or the "
++                              "printer no longer exists.\n"));
++      rc = CUPS_BACKEND_STOP;
++      break;
++    default :
++      rc = CUPS_BACKEND_FAILED;
++    }
++    goto prt_available_cleanup;
++  }
++
++prt_available_cleanup :
++  httpClose(http);
++  return (rc);
++}
++
++static int
++move_job(int        jobid,              /* Job ID */
++         const char *dest)              /* Destination ipp address */
++{
++  ipp_t *request;                       /* IPP Request */
++  char  job_uri[HTTP_MAX_URI];          /* job-uri */
++
++  http_t* http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
++
++  if (!http)
++  {
++    _cupsLangPrintf(stderr,
++                    _("failover: Unable to connect to server: %s\n"),
++                    strerror(errno));
++    return (CUPS_BACKEND_FAILED);
++  }
++
++ /*
++  * Build a CUPS_MOVE_JOB request, which requires the following
++  * attributes:
++  *
++  *    job-uri/printer-uri
++  *    job-printer-uri
++  *    requesting-user-name
++  */
++
++  request = ippNewRequest(CUPS_MOVE_JOB);
++
++  snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", jobid);
++  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
++               job_uri);
++
++  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
++               "requesting-user-name",
++               NULL, cupsUser());
++
++  ippAddString(request, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri",
++               NULL, dest);
++
++ /*
++  * Do the request and get back a response...
++  */
++
++  ippDelete(cupsDoRequest(http, request, "/jobs"));
++
++  httpClose(http);
++
++  if (cupsLastError() > IPP_OK_CONFLICT)
++  {
++    _cupsLangPrintf(stderr, "failover: %s\n", cupsLastErrorString());
++    return (CUPS_BACKEND_FAILED);
++  }
++  else
++    return (CUPS_BACKEND_OK);
++}
++
++/*
++ * 'sigterm_handler()' - handles a sigterm, i.e. job canceled
++ */
++static void
++sigterm_handler(int sig)
++{
++  if (!job_canceled)
++  {
++    write(2, "DEBUG: Got SIGTERM.\n", 20);
++    job_canceled = 1;
++  }
++  else
++  {
++   /*
++    * Job has already been canceled, so just exit
++    */
++    exit(1);
++  }
++}
++
++/*
++ * 'password_cb()' - Disable the password prompt for cupsDoFileRequest().
++ */
++static const char *                     /* O - Password  */
++password_cb(const char *prompt)         /* I - Prompt (not used) */
++{
++  auth_info_required = "username,password";
++  password_retries++;
++
++  if(password_retries < FAILOVER_PASSWORD_RETRIES_MAX)
++    return (password);
++  else
++    return (NULL);
++}
diff --git a/SOURCES/cups-memory-consumption.patch b/SOURCES/cups-memory-consumption.patch
new file mode 100644
index 0000000..5ccfbba
--- /dev/null
+++ b/SOURCES/cups-memory-consumption.patch
@@ -0,0 +1,1220 @@
+diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c
+index 925ab80..e5f89ee 100644
+--- a/cups/ppd-cache.c
++++ b/cups/ppd-cache.c
+@@ -508,24 +508,20 @@ _ppdCacheCreateWithFile(
+     else if (!_cups_strcasecmp(line, "Filter"))
+     {
+       if (!pc->filters)
+-        pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
+-	                            (cups_acopy_func_t)_cupsStrAlloc,
+-				    (cups_afree_func_t)_cupsStrFree);
++        pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+       cupsArrayAdd(pc->filters, value);
+     }
+     else if (!_cups_strcasecmp(line, "PreFilter"))
+     {
+       if (!pc->prefilters)
+-        pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
+-	                               (cups_acopy_func_t)_cupsStrAlloc,
+-				       (cups_afree_func_t)_cupsStrFree);
++        pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+       cupsArrayAdd(pc->prefilters, value);
+     }
+     else if (!_cups_strcasecmp(line, "Product"))
+     {
+-      pc->product = _cupsStrAlloc(value);
++      pc->product = strdup(value);
+     }
+     else if (!_cups_strcasecmp(line, "SingleFile"))
+     {
+@@ -625,8 +621,8 @@ _ppdCacheCreateWithFile(
+       }
+ 
+       map      = pc->bins + pc->num_bins;
+-      map->pwg = _cupsStrAlloc(pwg_keyword);
+-      map->ppd = _cupsStrAlloc(ppd_keyword);
++      map->pwg = strdup(pwg_keyword);
++      map->ppd = strdup(ppd_keyword);
+ 
+       pc->num_bins ++;
+     }
+@@ -680,8 +676,8 @@ _ppdCacheCreateWithFile(
+ 	goto create_error;
+       }
+ 
+-      size->map.pwg = _cupsStrAlloc(pwg_keyword);
+-      size->map.ppd = _cupsStrAlloc(ppd_keyword);
++      size->map.pwg = strdup(pwg_keyword);
++      size->map.ppd = strdup(ppd_keyword);
+ 
+       pc->num_sizes ++;
+     }
+@@ -709,15 +705,15 @@ _ppdCacheCreateWithFile(
+ 
+       pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
+ 		        pc->custom_max_width, pc->custom_max_length, NULL);
+-      pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
++      pc->custom_max_keyword = strdup(pwg_keyword);
+ 
+       pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
+ 		        pc->custom_min_width, pc->custom_min_length, NULL);
+-      pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
++      pc->custom_min_keyword = strdup(pwg_keyword);
+     }
+     else if (!_cups_strcasecmp(line, "SourceOption"))
+     {
+-      pc->source_option = _cupsStrAlloc(value);
++      pc->source_option = strdup(value);
+     }
+     else if (!_cups_strcasecmp(line, "NumSources"))
+     {
+@@ -764,8 +760,8 @@ _ppdCacheCreateWithFile(
+       }
+ 
+       map      = pc->sources + pc->num_sources;
+-      map->pwg = _cupsStrAlloc(pwg_keyword);
+-      map->ppd = _cupsStrAlloc(ppd_keyword);
++      map->pwg = strdup(pwg_keyword);
++      map->ppd = strdup(ppd_keyword);
+ 
+       pc->num_sources ++;
+     }
+@@ -813,8 +809,8 @@ _ppdCacheCreateWithFile(
+       }
+ 
+       map      = pc->types + pc->num_types;
+-      map->pwg = _cupsStrAlloc(pwg_keyword);
+-      map->ppd = _cupsStrAlloc(ppd_keyword);
++      map->pwg = strdup(pwg_keyword);
++      map->ppd = strdup(ppd_keyword);
+ 
+       pc->num_types ++;
+     }
+@@ -844,13 +840,13 @@ _ppdCacheCreateWithFile(
+ 	                   pc->presets[print_color_mode] + print_quality);
+     }
+     else if (!_cups_strcasecmp(line, "SidesOption"))
+-      pc->sides_option = _cupsStrAlloc(value);
++      pc->sides_option = strdup(value);
+     else if (!_cups_strcasecmp(line, "Sides1Sided"))
+-      pc->sides_1sided = _cupsStrAlloc(value);
++      pc->sides_1sided = strdup(value);
+     else if (!_cups_strcasecmp(line, "Sides2SidedLong"))
+-      pc->sides_2sided_long = _cupsStrAlloc(value);
++      pc->sides_2sided_long = strdup(value);
+     else if (!_cups_strcasecmp(line, "Sides2SidedShort"))
+-      pc->sides_2sided_short = _cupsStrAlloc(value);
++      pc->sides_2sided_short = strdup(value);
+     else if (!_cups_strcasecmp(line, "Finishings"))
+     {
+       if (!pc->finishings)
+@@ -871,13 +867,13 @@ _ppdCacheCreateWithFile(
+     else if (!_cups_strcasecmp(line, "MaxCopies"))
+       pc->max_copies = atoi(value);
+     else if (!_cups_strcasecmp(line, "ChargeInfoURI"))
+-      pc->charge_info_uri = _cupsStrAlloc(value);
++      pc->charge_info_uri = strdup(value);
+     else if (!_cups_strcasecmp(line, "JobAccountId"))
+       pc->account_id = !_cups_strcasecmp(value, "true");
+     else if (!_cups_strcasecmp(line, "JobAccountingUserId"))
+       pc->accounting_user_id = !_cups_strcasecmp(value, "true");
+     else if (!_cups_strcasecmp(line, "JobPassword"))
+-      pc->password = _cupsStrAlloc(value);
++      pc->password = strdup(value);
+     else if (!_cups_strcasecmp(line, "Mandatory"))
+     {
+       if (pc->mandatory)
+@@ -888,9 +884,7 @@ _ppdCacheCreateWithFile(
+     else if (!_cups_strcasecmp(line, "SupportFile"))
+     {
+       if (!pc->support_files)
+-        pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+-                                          (cups_acopy_func_t)_cupsStrAlloc,
+-                                          (cups_afree_func_t)_cupsStrFree);
++        pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+       cupsArrayAdd(pc->support_files, value);
+     }
+@@ -1130,8 +1124,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 	  */
+ 
+ 	  new_size = old_size;
+-	  _cupsStrFree(old_size->map.ppd);
+-	  _cupsStrFree(old_size->map.pwg);
++	  free(old_size->map.ppd);
++	  free(old_size->map.pwg);
+ 	}
+       }
+ 
+@@ -1152,8 +1146,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 	* Save this size...
+ 	*/
+ 
+-	new_size->map.ppd = _cupsStrAlloc(ppd_size->name);
+-	new_size->map.pwg = _cupsStrAlloc(pwg_name);
++	new_size->map.ppd = strdup(ppd_size->name);
++	new_size->map.pwg = strdup(pwg_name);
+ 	new_size->width   = new_width;
+ 	new_size->length  = new_length;
+ 	new_size->left    = new_left;
+@@ -1173,14 +1167,14 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+     pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "max",
+ 		      PWG_FROM_POINTS(ppd->custom_max[0]),
+ 		      PWG_FROM_POINTS(ppd->custom_max[1]), NULL);
+-    pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword);
++    pc->custom_max_keyword = strdup(pwg_keyword);
+     pc->custom_max_width   = PWG_FROM_POINTS(ppd->custom_max[0]);
+     pc->custom_max_length  = PWG_FROM_POINTS(ppd->custom_max[1]);
+ 
+     pwgFormatSizeName(pwg_keyword, sizeof(pwg_keyword), "custom", "min",
+ 		      PWG_FROM_POINTS(ppd->custom_min[0]),
+ 		      PWG_FROM_POINTS(ppd->custom_min[1]), NULL);
+-    pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword);
++    pc->custom_min_keyword = strdup(pwg_keyword);
+     pc->custom_min_width   = PWG_FROM_POINTS(ppd->custom_min[0]);
+     pc->custom_min_length  = PWG_FROM_POINTS(ppd->custom_min[1]);
+ 
+@@ -1199,7 +1193,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 
+   if (input_slot)
+   {
+-    pc->source_option = _cupsStrAlloc(input_slot->keyword);
++    pc->source_option = strdup(input_slot->keyword);
+ 
+     if ((pc->sources = calloc((size_t)input_slot->num_choices, sizeof(pwg_map_t))) == NULL)
+     {
+@@ -1251,8 +1245,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 	                  "_");
+       }
+ 
+-      map->pwg = _cupsStrAlloc(pwg_name);
+-      map->ppd = _cupsStrAlloc(choice->choice);
++      map->pwg = strdup(pwg_name);
++      map->ppd = strdup(choice->choice);
+     }
+   }
+ 
+@@ -1315,8 +1309,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 	                  "_");
+       }
+ 
+-      map->pwg = _cupsStrAlloc(pwg_name);
+-      map->ppd = _cupsStrAlloc(choice->choice);
++      map->pwg = strdup(pwg_name);
++      map->ppd = strdup(choice->choice);
+     }
+   }
+ 
+@@ -1342,8 +1336,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+     {
+       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_");
+ 
+-      map->pwg = _cupsStrAlloc(pwg_keyword);
+-      map->ppd = _cupsStrAlloc(choice->choice);
++      map->pwg = strdup(pwg_keyword);
++      map->ppd = strdup(choice->choice);
+     }
+   }
+ 
+@@ -1558,7 +1552,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 
+   if (duplex)
+   {
+-    pc->sides_option = _cupsStrAlloc(duplex->keyword);
++    pc->sides_option = strdup(duplex->keyword);
+ 
+     for (i = duplex->num_choices, choice = duplex->choices;
+          i > 0;
+@@ -1566,16 +1560,16 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+     {
+       if ((!_cups_strcasecmp(choice->choice, "None") ||
+ 	   !_cups_strcasecmp(choice->choice, "False")) && !pc->sides_1sided)
+-        pc->sides_1sided = _cupsStrAlloc(choice->choice);
++        pc->sides_1sided = strdup(choice->choice);
+       else if ((!_cups_strcasecmp(choice->choice, "DuplexNoTumble") ||
+ 	        !_cups_strcasecmp(choice->choice, "LongEdge") ||
+ 	        !_cups_strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long)
+-        pc->sides_2sided_long = _cupsStrAlloc(choice->choice);
++        pc->sides_2sided_long = strdup(choice->choice);
+       else if ((!_cups_strcasecmp(choice->choice, "DuplexTumble") ||
+ 	        !_cups_strcasecmp(choice->choice, "ShortEdge") ||
+ 	        !_cups_strcasecmp(choice->choice, "Bottom")) &&
+ 	       !pc->sides_2sided_short)
+-        pc->sides_2sided_short = _cupsStrAlloc(choice->choice);
++        pc->sides_2sided_short = strdup(choice->choice);
+     }
+   }
+ 
+@@ -1583,9 +1577,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+   * Copy filters and pre-filters...
+   */
+ 
+-  pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0,
+-			      (cups_acopy_func_t)_cupsStrAlloc,
+-			      (cups_afree_func_t)_cupsStrFree);
++  pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+   cupsArrayAdd(pc->filters,
+                "application/vnd.cups-raw application/octet-stream 0 -");
+@@ -1642,9 +1634,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+ 
+   if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
+   {
+-    pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0,
+-				   (cups_acopy_func_t)_cupsStrAlloc,
+-				   (cups_afree_func_t)_cupsStrFree);
++    pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+     do
+     {
+@@ -1661,7 +1651,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+   */
+ 
+   if (ppd->product)
+-    pc->product = _cupsStrAlloc(ppd->product);
++    pc->product = strdup(ppd->product);
+ 
+  /*
+   * Copy finishings mapping data...
+@@ -1818,7 +1808,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+   */
+ 
+   if ((ppd_attr = ppdFindAttr(ppd, "cupsChargeInfoURI", NULL)) != NULL)
+-    pc->charge_info_uri = _cupsStrAlloc(ppd_attr->value);
++    pc->charge_info_uri = strdup(ppd_attr->value);
+ 
+   if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountId", NULL)) != NULL)
+     pc->account_id = !_cups_strcasecmp(ppd_attr->value, "true");
+@@ -1827,7 +1817,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+     pc->accounting_user_id = !_cups_strcasecmp(ppd_attr->value, "true");
+ 
+   if ((ppd_attr = ppdFindAttr(ppd, "cupsJobPassword", NULL)) != NULL)
+-    pc->password = _cupsStrAlloc(ppd_attr->value);
++    pc->password = strdup(ppd_attr->value);
+ 
+   if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
+     pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
+@@ -1836,9 +1826,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)	/* I - PPD file */
+   * Support files...
+   */
+ 
+-  pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+-				    (cups_acopy_func_t)_cupsStrAlloc,
+-				    (cups_afree_func_t)_cupsStrFree);
++  pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free);
+ 
+   for (ppd_attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+        ppd_attr;
+@@ -1894,8 +1882,8 @@ _ppdCacheDestroy(_ppd_cache_t *pc)	/* I - PPD cache and mapping data */
+   {
+     for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++)
+     {
+-      _cupsStrFree(map->pwg);
+-      _cupsStrFree(map->ppd);
++      free(map->pwg);
++      free(map->ppd);
+     }
+ 
+     free(pc->bins);
+@@ -1905,15 +1893,14 @@ _ppdCacheDestroy(_ppd_cache_t *pc)	/* I - PPD cache and mapping data */
+   {
+     for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++)
+     {
+-      _cupsStrFree(size->map.pwg);
+-      _cupsStrFree(size->map.ppd);
++      free(size->map.pwg);
++      free(size->map.ppd);
+     }
+ 
+     free(pc->sizes);
+   }
+ 
+-  if (pc->source_option)
+-    _cupsStrFree(pc->source_option);
++  free(pc->source_option);
+ 
+   if (pc->sources)
+   {
+@@ -1930,26 +1917,23 @@ _ppdCacheDestroy(_ppd_cache_t *pc)	/* I - PPD cache and mapping data */
+   {
+     for (i = pc->num_types, map = pc->types; i > 0; i --, map ++)
+     {
+-      _cupsStrFree(map->pwg);
+-      _cupsStrFree(map->ppd);
++      free(map->pwg);
++      free(map->ppd);
+     }
+ 
+     free(pc->types);
+   }
+ 
+-  if (pc->custom_max_keyword)
+-    _cupsStrFree(pc->custom_max_keyword);
+-
+-  if (pc->custom_min_keyword)
+-    _cupsStrFree(pc->custom_min_keyword);
++  free(pc->custom_max_keyword);
++  free(pc->custom_min_keyword);
+ 
+-  _cupsStrFree(pc->product);
++  free(pc->product);
+   cupsArrayDelete(pc->filters);
+   cupsArrayDelete(pc->prefilters);
+   cupsArrayDelete(pc->finishings);
+ 
+-  _cupsStrFree(pc->charge_info_uri);
+-  _cupsStrFree(pc->password);
++  free(pc->charge_info_uri);
++  free(pc->password);
+ 
+   cupsArrayDelete(pc->mandatory);
+ 
+diff --git a/cups/ppd-mark.c b/cups/ppd-mark.c
+index 464c09a..cb67468 100644
+--- a/cups/ppd-mark.c
++++ b/cups/ppd-mark.c
+@@ -890,9 +890,9 @@ ppd_mark_option(ppd_file_t *ppd,	/* I - PPD file */
+ 	  case PPD_CUSTOM_PASSWORD :
+ 	  case PPD_CUSTOM_STRING :
+ 	      if (cparam->current.custom_string)
+-	        _cupsStrFree(cparam->current.custom_string);
++	        free(cparam->current.custom_string);
+ 
+-	      cparam->current.custom_string = _cupsStrAlloc(choice + 7);
++	      cparam->current.custom_string = strdup(choice + 7);
+ 	      break;
+ 	}
+       }
+@@ -967,9 +967,9 @@ ppd_mark_option(ppd_file_t *ppd,	/* I - PPD file */
+ 	  case PPD_CUSTOM_PASSWORD :
+ 	  case PPD_CUSTOM_STRING :
+ 	      if (cparam->current.custom_string)
+-		_cupsStrFree(cparam->current.custom_string);
++		free(cparam->current.custom_string);
+ 
+-	      cparam->current.custom_string = _cupsStrRetain(val->value);
++	      cparam->current.custom_string = strdup(val->value);
+ 	      break;
+ 	}
+       }
+diff --git a/cups/ppd.c b/cups/ppd.c
+index 8276988..6782a85 100644
+--- a/cups/ppd.c
++++ b/cups/ppd.c
+@@ -34,8 +34,6 @@
+  * Definitions...
+  */
+ 
+-#define ppd_free(p)	if (p) free(p)	/* Safe free macro */
+-
+ #define PPD_KEYWORD	1		/* Line contained a keyword */
+ #define PPD_OPTION	2		/* Line contained an option name */
+ #define PPD_TEXT	4		/* Line contained human-readable text */
+@@ -117,7 +115,6 @@ void
+ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+ {
+   int			i;		/* Looping var */
+-  ppd_emul_t		*emul;		/* Current emulation */
+   ppd_group_t		*group;		/* Current group */
+   char			**font;		/* Current font */
+   ppd_attr_t		**attr;		/* Current attribute */
+@@ -136,28 +133,12 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   * Free all strings at the top level...
+   */
+ 
+-  _cupsStrFree(ppd->lang_encoding);
+-  _cupsStrFree(ppd->nickname);
+-  if (ppd->patches)
+-    free(ppd->patches);
+-  _cupsStrFree(ppd->jcl_begin);
+-  _cupsStrFree(ppd->jcl_end);
+-  _cupsStrFree(ppd->jcl_ps);
+-
+- /*
+-  * Free any emulations...
+-  */
+-
+-  if (ppd->num_emulations > 0)
+-  {
+-    for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++)
+-    {
+-      _cupsStrFree(emul->start);
+-      _cupsStrFree(emul->stop);
+-    }
+-
+-    ppd_free(ppd->emulations);
+-  }
++  free(ppd->lang_encoding);
++  free(ppd->nickname);
++  free(ppd->patches);
++  free(ppd->jcl_begin);
++  free(ppd->jcl_end);
++  free(ppd->jcl_ps);
+ 
+  /*
+   * Free any UI groups, subgroups, and options...
+@@ -168,7 +149,7 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+     for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
+       ppd_free_group(group);
+ 
+-    ppd_free(ppd->groups);
++    free(ppd->groups);
+   }
+ 
+   cupsArrayDelete(ppd->options);
+@@ -179,14 +160,14 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   */
+ 
+   if (ppd->num_sizes > 0)
+-    ppd_free(ppd->sizes);
++    free(ppd->sizes);
+ 
+  /*
+   * Free any constraints...
+   */
+ 
+   if (ppd->num_consts > 0)
+-    ppd_free(ppd->consts);
++    free(ppd->consts);
+ 
+  /*
+   * Free any filters...
+@@ -201,9 +182,9 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   if (ppd->num_fonts > 0)
+   {
+     for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++)
+-      _cupsStrFree(*font);
++      free(*font);
+ 
+-    ppd_free(ppd->fonts);
++    free(ppd->fonts);
+   }
+ 
+  /*
+@@ -211,7 +192,7 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   */
+ 
+   if (ppd->num_profiles > 0)
+-    ppd_free(ppd->profiles);
++    free(ppd->profiles);
+ 
+  /*
+   * Free any attributes...
+@@ -221,11 +202,11 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   {
+     for (i = ppd->num_attrs, attr = ppd->attrs; i > 0; i --, attr ++)
+     {
+-      _cupsStrFree((*attr)->value);
+-      ppd_free(*attr);
++      free((*attr)->value);
++      free(*attr);
+     }
+ 
+-    ppd_free(ppd->attrs);
++    free(ppd->attrs);
+   }
+ 
+   cupsArrayDelete(ppd->sorted_attrs);
+@@ -247,7 +228,7 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+         case PPD_CUSTOM_PASSCODE :
+         case PPD_CUSTOM_PASSWORD :
+         case PPD_CUSTOM_STRING :
+-            _cupsStrFree(cparam->current.custom_string);
++            free(cparam->current.custom_string);
+ 	    break;
+ 
+ 	default :
+@@ -295,7 +276,7 @@ ppdClose(ppd_file_t *ppd)		/* I - PPD file record */
+   * Free the whole record...
+   */
+ 
+-  ppd_free(ppd);
++  free(ppd);
+ }
+ 
+ 
+@@ -441,7 +422,6 @@ _ppdOpen(
+     _ppd_localization_t	localization)	/* I - Localization to load */
+ {
+   int			i, j, k;	/* Looping vars */
+-  int			count;		/* Temporary count */
+   _ppd_line_t		line;		/* Line buffer */
+   ppd_file_t		*ppd;		/* PPD file record */
+   ppd_group_t		*group,		/* Current group */
+@@ -459,7 +439,6 @@ _ppdOpen(
+ 					/* Human-readable text from file */
+ 			*string,	/* Code/text from file */
+ 			*sptr,		/* Pointer into string */
+-			*nameptr,	/* Pointer into name */
+ 			*temp,		/* Temporary string pointer */
+ 			**tempfonts;	/* Temporary fonts pointer */
+   float			order;		/* Order dependency number */
+@@ -633,16 +612,14 @@ _ppdOpen(
+     if (pg->ppd_status == PPD_OK)
+       pg->ppd_status = PPD_MISSING_PPDADOBE4;
+ 
+-    _cupsStrFree(string);
+-    ppd_free(line.buffer);
++    free(string);
++    free(line.buffer);
+ 
+     return (NULL);
+   }
+ 
+   DEBUG_printf(("2_ppdOpen: keyword=%s, string=%p", keyword, string));
+ 
+-  _cupsStrFree(string);
+-
+  /*
+   * Allocate memory for the PPD file record...
+   */
+@@ -651,12 +628,15 @@ _ppdOpen(
+   {
+     pg->ppd_status = PPD_ALLOC_ERROR;
+ 
+-    _cupsStrFree(string);
+-    ppd_free(line.buffer);
++    free(string);
++    free(line.buffer);
+ 
+     return (NULL);
+   }
+ 
++  free(string);
++  string = NULL;
++
+   ppd->language_level = 2;
+   ppd->color_device   = 0;
+   ppd->colorspace     = PPD_CS_N;
+@@ -735,6 +715,8 @@ _ppdOpen(
+ 	   strncmp(ll, keyword, ll_len)))
+       {
+ 	DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
++	free(string);
++	string = NULL;
+ 	continue;
+       }
+       else if (localization == _PPD_LOCALIZATION_ICC_PROFILES)
+@@ -754,6 +736,8 @@ _ppdOpen(
+ 	if (i >= (int)(sizeof(color_keywords) / sizeof(color_keywords[0])))
+ 	{
+ 	  DEBUG_printf(("2_ppdOpen: Ignoring localization: \"%s\"\n", keyword));
++	  free(string);
++	  string = NULL;
+ 	  continue;
+ 	}
+       }
+@@ -849,7 +833,7 @@ _ppdOpen(
+       * Say all PPD files are UTF-8, since we convert to UTF-8...
+       */
+ 
+-      ppd->lang_encoding = _cupsStrAlloc("UTF-8");
++      ppd->lang_encoding = strdup("UTF-8");
+       encoding           = _ppdGetEncoding(string);
+     }
+     else if (!strcmp(keyword, "LanguageVersion"))
+@@ -870,10 +854,10 @@ _ppdOpen(
+ 
+ 
+         cupsCharsetToUTF8(utf8, string, sizeof(utf8), encoding);
+-	ppd->nickname = _cupsStrAlloc((char *)utf8);
++	ppd->nickname = strdup((char *)utf8);
+       }
+       else
+-        ppd->nickname = _cupsStrAlloc(string);
++        ppd->nickname = strdup(string);
+     }
+     else if (!strcmp(keyword, "Product"))
+       ppd->product = string;
+@@ -883,17 +867,17 @@ _ppdOpen(
+       ppd->ttrasterizer = string;
+     else if (!strcmp(keyword, "JCLBegin"))
+     {
+-      ppd->jcl_begin = _cupsStrAlloc(string);
++      ppd->jcl_begin = strdup(string);
+       ppd_decode(ppd->jcl_begin);	/* Decode quoted string */
+     }
+     else if (!strcmp(keyword, "JCLEnd"))
+     {
+-      ppd->jcl_end = _cupsStrAlloc(string);
++      ppd->jcl_end = strdup(string);
+       ppd_decode(ppd->jcl_end);		/* Decode quoted string */
+     }
+     else if (!strcmp(keyword, "JCLToPSInterpreter"))
+     {
+-      ppd->jcl_ps = _cupsStrAlloc(string);
++      ppd->jcl_ps = strdup(string);
+       ppd_decode(ppd->jcl_ps);		/* Decode quoted string */
+     }
+     else if (!strcmp(keyword, "AccurateScreensSupport"))
+@@ -961,10 +945,10 @@ _ppdOpen(
+       ppd->num_filters ++;
+ 
+      /*
+-      * Retain a copy of the filter string...
++      * Make a copy of the filter string...
+       */
+ 
+-      *filter = _cupsStrRetain(string);
++      *filter = strdup(string);
+     }
+     else if (!strcmp(keyword, "Throughput"))
+       ppd->throughput = atoi(string);
+@@ -987,7 +971,7 @@ _ppdOpen(
+       }
+ 
+       ppd->fonts                 = tempfonts;
+-      ppd->fonts[ppd->num_fonts] = _cupsStrAlloc(name);
++      ppd->fonts[ppd->num_fonts] = strdup(name);
+       ppd->num_fonts ++;
+     }
+     else if (!strncmp(keyword, "ParamCustom", 11))
+@@ -1152,7 +1136,7 @@ _ppdOpen(
+ 	strlcpy(choice->text, text[0] ? text : _("Custom"),
+ 		sizeof(choice->text));
+ 
+-	choice->code = _cupsStrAlloc(string);
++	choice->code = strdup(string);
+ 
+ 	if (custom_option->section == PPD_ORDER_JCL)
+ 	  ppd_decode(choice->code);
+@@ -1201,59 +1185,23 @@ _ppdOpen(
+       else if (!strcmp(string, "Plus90"))
+         ppd->landscape = 90;
+     }
+-    else if (!strcmp(keyword, "Emulators") && string)
+-    {
+-      for (count = 1, sptr = string; sptr != NULL;)
+-        if ((sptr = strchr(sptr, ' ')) != NULL)
+-	{
+-	  count ++;
+-	  while (*sptr == ' ')
+-	    sptr ++;
+-	}
+-
+-      ppd->num_emulations = count;
+-      if ((ppd->emulations = calloc((size_t)count, sizeof(ppd_emul_t))) == NULL)
+-      {
+-        pg->ppd_status = PPD_ALLOC_ERROR;
+-
+-	goto error;
+-      }
+-
+-      for (i = 0, sptr = string; i < count; i ++)
+-      {
+-        for (nameptr = ppd->emulations[i].name;
+-	     *sptr != '\0' && *sptr != ' ';
+-	     sptr ++)
+-	  if (nameptr < (ppd->emulations[i].name + sizeof(ppd->emulations[i].name) - 1))
+-	    *nameptr++ = *sptr;
+-
+-	*nameptr = '\0';
+-
+-	while (*sptr == ' ')
+-	  sptr ++;
+-      }
+-    }
+-    else if (!strncmp(keyword, "StartEmulator_", 14))
++    else if (!strcmp(keyword, "Emulators") && string && ppd->num_emulations == 0)
+     {
+-      ppd_decode(string);
++     /*
++      * Issue #5562: Samsung printer drivers incorrectly use Emulators keyword
++      *              to configure themselves
++      *
++      * The Emulators keyword was loaded but never used by anything in CUPS,
++      * and has no valid purpose in CUPS.  The old code was removed due to a
++      * memory leak (Issue #5475), so the following (new) code supports a single
++      * name for the Emulators keyword, allowing these drivers to work until we
++      * remove PPD and driver support entirely in a future version of CUPS.
++      */
+ 
+-      for (i = 0; i < ppd->num_emulations; i ++)
+-        if (!strcmp(keyword + 14, ppd->emulations[i].name))
+-	{
+-	  ppd->emulations[i].start = string;
+-	  string = NULL;
+-	}
+-    }
+-    else if (!strncmp(keyword, "StopEmulator_", 13))
+-    {
+-      ppd_decode(string);
++      ppd->num_emulations = 1;
++      ppd->emulations     = calloc(1, sizeof(ppd_emul_t));
+ 
+-      for (i = 0; i < ppd->num_emulations; i ++)
+-        if (!strcmp(keyword + 13, ppd->emulations[i].name))
+-	{
+-	  ppd->emulations[i].stop = string;
+-	  string = NULL;
+-	}
++      strlcpy(ppd->emulations[0].name, string, sizeof(ppd->emulations[0].name));
+     }
+     else if (!strcmp(keyword, "JobPatchFile"))
+     {
+@@ -1408,7 +1356,7 @@ _ppdOpen(
+ 
+       option->section = PPD_ORDER_ANY;
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+ 
+      /*
+@@ -1436,7 +1384,7 @@ _ppdOpen(
+ 	strlcpy(choice->text,
+ 	        custom_attr->text[0] ? custom_attr->text : _("Custom"),
+ 		sizeof(choice->text));
+-        choice->code = _cupsStrRetain(custom_attr->value);
++        choice->code = strdup(custom_attr->value);
+       }
+     }
+     else if (!strcmp(keyword, "JCLOpenUI"))
+@@ -1515,7 +1463,7 @@ _ppdOpen(
+       option->section = PPD_ORDER_JCL;
+       group = NULL;
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+ 
+      /*
+@@ -1539,14 +1487,14 @@ _ppdOpen(
+ 	strlcpy(choice->text,
+ 	        custom_attr->text[0] ? custom_attr->text : _("Custom"),
+ 		sizeof(choice->text));
+-        choice->code = _cupsStrRetain(custom_attr->value);
++        choice->code = strdup(custom_attr->value);
+       }
+     }
+     else if (!strcmp(keyword, "CloseUI") || !strcmp(keyword, "JCLCloseUI"))
+     {
+       option = NULL;
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strcmp(keyword, "OpenGroup"))
+@@ -1593,14 +1541,14 @@ _ppdOpen(
+       if (group == NULL)
+ 	goto error;
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strcmp(keyword, "CloseGroup"))
+     {
+       group = NULL;
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strcmp(keyword, "OrderDependency"))
+@@ -1658,7 +1606,7 @@ _ppdOpen(
+ 	option->order   = order;
+       }
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strncmp(keyword, "Default", 7))
+@@ -1901,7 +1849,7 @@ _ppdOpen(
+       * Don't add this one as an attribute...
+       */
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strcmp(keyword, "PaperDimension"))
+@@ -1923,7 +1871,7 @@ _ppdOpen(
+       size->width  = (float)_cupsStrScand(string, &sptr, loc);
+       size->length = (float)_cupsStrScand(sptr, NULL, loc);
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (!strcmp(keyword, "ImageableArea"))
+@@ -1947,7 +1895,7 @@ _ppdOpen(
+       size->right  = (float)_cupsStrScand(sptr, &sptr, loc);
+       size->top    = (float)_cupsStrScand(sptr, NULL, loc);
+ 
+-      _cupsStrFree(string);
++      free(string);
+       string = NULL;
+     }
+     else if (option != NULL &&
+@@ -2003,7 +1951,7 @@ _ppdOpen(
+         (mask & (PPD_KEYWORD | PPD_STRING)) == (PPD_KEYWORD | PPD_STRING))
+       ppd_add_attr(ppd, keyword, name, text, string);
+     else
+-      _cupsStrFree(string);
++      free(string);
+   }
+ 
+  /*
+@@ -2016,7 +1964,8 @@ _ppdOpen(
+     goto error;
+   }
+ 
+-  ppd_free(line.buffer);
++  free(string);
++  free(line.buffer);
+ 
+  /*
+   * Reset language preferences...
+@@ -2098,8 +2047,8 @@ _ppdOpen(
+ 
+   error:
+ 
+-  _cupsStrFree(string);
+-  ppd_free(line.buffer);
++  free(string);
++  free(line.buffer);
+ 
+   ppdClose(ppd);
+ 
+@@ -2537,9 +2486,9 @@ ppd_free_filters(ppd_file_t *ppd)	/* I - PPD file */
+   if (ppd->num_filters > 0)
+   {
+     for (i = ppd->num_filters, filter = ppd->filters; i > 0; i --, filter ++)
+-      _cupsStrFree(*filter);
++      free(*filter);
+ 
+-    ppd_free(ppd->filters);
++    free(ppd->filters);
+ 
+     ppd->num_filters = 0;
+     ppd->filters     = NULL;
+@@ -2566,7 +2515,7 @@ ppd_free_group(ppd_group_t *group)	/* I - Group to free */
+ 	 i --, option ++)
+       ppd_free_option(option);
+ 
+-    ppd_free(group->options);
++    free(group->options);
+   }
+ 
+   if (group->num_subgroups > 0)
+@@ -2576,7 +2525,7 @@ ppd_free_group(ppd_group_t *group)	/* I - Group to free */
+ 	 i --, subgroup ++)
+       ppd_free_group(subgroup);
+ 
+-    ppd_free(group->subgroups);
++    free(group->subgroups);
+   }
+ }
+ 
+@@ -2598,10 +2547,10 @@ ppd_free_option(ppd_option_t *option)	/* I - Option to free */
+          i > 0;
+          i --, choice ++)
+     {
+-      _cupsStrFree(choice->code);
++      free(choice->code);
+     }
+ 
+-    ppd_free(option->choices);
++    free(option->choices);
+   }
+ }
+ 
+@@ -3338,7 +3287,7 @@ ppd_read(cups_file_t    *fp,		/* I - File to read from */
+ 	lineptr ++;
+       }
+ 
+-      *string = _cupsStrAlloc(lineptr);
++      *string = strdup(lineptr);
+ 
+       mask |= PPD_STRING;
+     }
+@@ -3460,7 +3409,7 @@ ppd_update_filters(ppd_file_t     *ppd,	/* I - PPD file */
+     filter           += ppd->num_filters;
+     ppd->num_filters ++;
+ 
+-    *filter = _cupsStrAlloc(buffer);
++    *filter = strdup(buffer);
+   }
+   while ((attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL);
+ 
+diff --git a/cups/ppd.h b/cups/ppd.h
+index fb33c08..1c852c7 100644
+--- a/cups/ppd.h
++++ b/cups/ppd.h
+@@ -302,8 +302,8 @@ typedef struct ppd_file_s		/**** PPD File ****/
+   int		throughput;		/* Pages per minute */
+   ppd_cs_t	colorspace;		/* Default colorspace */
+   char		*patches;		/* Patch commands to be sent to printer */
+-  int		num_emulations;		/* Number of emulations supported */
+-  ppd_emul_t	*emulations;		/* Emulations and the code to invoke them */
++  int		num_emulations;		/* Number of emulations supported (no longer supported) @private@ */
++  ppd_emul_t	*emulations;		/* Emulations and the code to invoke them (no longer supported) @private@ */
+   char		*jcl_begin;		/* Start JCL commands */
+   char		*jcl_ps;		/* Enter PostScript interpreter */
+   char		*jcl_end;		/* End JCL commands */
+diff --git a/cups/string.c b/cups/string.c
+index 0d4ed0f..8f37caf 100644
+--- a/cups/string.c
++++ b/cups/string.c
+@@ -316,6 +316,13 @@ _cupsStrFree(const char *s)		/* I - String to free */
+ 
+   key = (_cups_sp_item_t *)(s - offsetof(_cups_sp_item_t, str));
+ 
++  if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL &&
++      item == key)
++  {
++   /*
++    * Found it, dereference...
++    */
++
+ #ifdef DEBUG_GUARDS
+   if (key->guard != _CUPS_STR_GUARD)
+   {
+@@ -325,13 +332,6 @@ _cupsStrFree(const char *s)		/* I - String to free */
+   }
+ #endif /* DEBUG_GUARDS */
+ 
+-  if ((item = (_cups_sp_item_t *)cupsArrayFind(stringpool, key)) != NULL &&
+-      item == key)
+-  {
+-   /*
+-    * Found it, dereference...
+-    */
+-
+     item->ref_count --;
+ 
+     if (!item->ref_count)
+diff --git a/scheduler/ipp.c b/scheduler/ipp.c
+index 298b684..e0dbc4a 100644
+--- a/scheduler/ipp.c
++++ b/scheduler/ipp.c
+@@ -2918,8 +2918,7 @@ add_printer(cupsd_client_t  *con,	/* I - Client connection */
+       if (!strcmp(attr->values[i].string.text, "none"))
+         continue;
+ 
+-      printer->reasons[printer->num_reasons] =
+-          _cupsStrRetain(attr->values[i].string.text);
++      printer->reasons[printer->num_reasons] = _cupsStrAlloc(attr->values[i].string.text);
+       printer->num_reasons ++;
+ 
+       if (!strcmp(attr->values[i].string.text, "paused") &&
+@@ -5437,8 +5436,7 @@ copy_printer_attrs(
+ 
+         if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported",
+ 	                               IPP_TAG_URI)) != NULL)
+-          member_uris->values[i].string.text =
+-	      _cupsStrRetain(p2_uri->values[0].string.text);
++          member_uris->values[i].string.text = _cupsStrAlloc(p2_uri->values[0].string.text);
+         else
+ 	{
+ 	  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri,
+diff --git a/scheduler/printers.c b/scheduler/printers.c
+index 3ec16cf..f16552e 100644
+--- a/scheduler/printers.c
++++ b/scheduler/printers.c
+@@ -54,8 +54,7 @@ static int	compare_printers(void *first, void *second, void *data);
+ static void	delete_printer_filters(cupsd_printer_t *p);
+ static void	dirty_printer(cupsd_printer_t *p);
+ static void	load_ppd(cupsd_printer_t *p);
+-static ipp_t	*new_media_col(pwg_size_t *size, const char *source,
+-		               const char *type);
++static ipp_t	*new_media_col(pwg_size_t *size);
+ static void	write_xml_string(cups_file_t *fp, const char *s);
+ 
+ 
+@@ -3873,21 +3872,19 @@ dirty_printer(cupsd_printer_t *p)	/* I - Printer */
+ static void
+ load_ppd(cupsd_printer_t *p)		/* I - Printer */
+ {
+-  int		i, j, k;		/* Looping vars */
++  int		i, j;			/* Looping vars */
+   char		cache_name[1024];	/* Cache filename */
+   struct stat	cache_info;		/* Cache file info */
+   ppd_file_t	*ppd;			/* PPD file */
+   char		ppd_name[1024];		/* PPD filename */
+   struct stat	ppd_info;		/* PPD file info */
+-  int		num_media;		/* Number of media options */
++  int		num_media;		/* Number of media values */
+   ppd_size_t	*size;			/* Current PPD size */
+   ppd_option_t	*duplex,		/* Duplex option */
+ 		*output_bin,		/* OutputBin option */
+ 		*output_mode,		/* OutputMode option */
+ 		*resolution;		/* (Set|JCL|)Resolution option */
+-  ppd_choice_t	*choice,		/* Current PPD choice */
+-		*input_slot,		/* Current input slot */
+-		*media_type;		/* Current media type */
++  ppd_choice_t	*choice;		/* Current PPD choice */
+   ppd_attr_t	*ppd_attr;		/* PPD attribute */
+   int		xdpi,			/* Horizontal resolution */
+ 		ydpi;			/* Vertical resolution */
+@@ -4147,18 +4144,7 @@ load_ppd(cupsd_printer_t *p)		/* I - Printer */
+       {
+         ipp_t	*col;			/* Collection value */
+ 
+-	input_slot = ppdFindMarkedChoice(ppd, "InputSlot");
+-	media_type = ppdFindMarkedChoice(ppd, "MediaType");
+-	col        = new_media_col(pwgsize,
+-			           input_slot ?
+-				       _ppdCacheGetSource(p->pc,
+-				                          input_slot->choice) :
+-				       NULL,
+-				   media_type ?
+-				       _ppdCacheGetType(p->pc,
+-				                        media_type->choice) :
+-				       NULL);
+-
++	col = new_media_col(pwgsize);
+ 	ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default",
+ 	                 col);
+         ippDelete(col);
+@@ -4354,89 +4340,19 @@ load_ppd(cupsd_printer_t *p)		/* I - Printer */
+       * media-col-database
+       */
+ 
+-      num_media = p->pc->num_sizes;
+-      if (p->pc->num_sources)
++      if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-database", p->pc->num_sizes, NULL)) != NULL)
+       {
+-        if (p->pc->num_types > 0)
+-	  num_media += p->pc->num_sizes * p->pc->num_sources *
+-	               p->pc->num_types;
+-	else
+-          num_media += p->pc->num_sizes * p->pc->num_sources;
+-      }
+-      else if (p->pc->num_types)
+-        num_media += p->pc->num_sizes * p->pc->num_types;
++       /*
++	* Add each page size without source or type...
++	*/
+ 
+-      if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER,
+-                                    "media-col-database", num_media,
+-				    NULL)) != NULL)
+-      {
+-        for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, val = attr->values;
+-	     i > 0;
+-	     i --, pwgsize ++)
++        for (i = 0, pwgsize = p->pc->sizes; i < p->pc->num_sizes; i ++, pwgsize ++)
+ 	{
+-	 /*
+-	  * Start by adding the page size without source or type...
+-	  */
++	  ipp_t *col = new_media_col(pwgsize);
+ 
+-	  ppdMarkOption(ppd, "PageSize", pwgsize->map.ppd);
+-
+-          val->collection = new_media_col(pwgsize, NULL, NULL);
+-	  val ++;
+-
+-         /*
+-	  * Then add the specific, supported combinations of size, source, and
+-	  * type...
+-	  */
+-
+-	  if (p->pc->num_sources > 0)
+-	  {
+-	    for (j = p->pc->num_sources, pwgsource = p->pc->sources;
+-	         j > 0;
+-		 j --, pwgsource ++)
+-	    {
+-	      ppdMarkOption(ppd, "InputSlot", pwgsource->ppd);
+-
+-	      if (p->pc->num_types > 0)
+-	      {
+-	        for (k = p->pc->num_types, pwgtype = p->pc->types;
+-		     k > 0;
+-		     k --, pwgtype ++)
+-		{
+-		  if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd))
+-		  {
+-		    val->collection = new_media_col(pwgsize, pwgsource->pwg,
+-		                                    pwgtype->pwg);
+-		    val ++;
+-		  }
+-		}
+-	      }
+-	      else if (!ppdConflicts(ppd))
+-	      {
+-	        val->collection = new_media_col(pwgsize, pwgsource->pwg, NULL);
+-		val ++;
+-	      }
+-	    }
+-	  }
+-	  else if (p->pc->num_types > 0)
+-	  {
+-	    for (j = p->pc->num_types, pwgtype = p->pc->types;
+-	         j > 0;
+-		 j --, pwgtype ++)
+-	    {
+-	      if (!ppdMarkOption(ppd, "MediaType", pwgtype->ppd))
+-	      {
+-	        val->collection = new_media_col(pwgsize, NULL, pwgtype->pwg);
+-		val ++;
+-	      }
+-	    }
+-	  }
++	  ippSetCollection(p->ppd_attrs, &attr, i, col);
++	  ippDelete(col);
+ 	}
+-
+-       /*
+-        * Update the number of media-col-database values...
+-	*/
+-
+-	attr->num_values = val - attr->values;
+       }
+     }
+ 
+@@ -5134,9 +5050,7 @@ load_ppd(cupsd_printer_t *p)		/* I - Printer */
+  */
+ 
+ static ipp_t *				/* O - Collection value */
+-new_media_col(pwg_size_t *size,	/* I - media-size/margin values */
+-              const char  *source,	/* I - media-source value */
+-              const char  *type)	/* I - media-type value */
++new_media_col(pwg_size_t *size)		/* I - media-size/margin values */
+ {
+   ipp_t	*media_col,			/* Collection value */
+ 	*media_size;			/* media-size value */
+@@ -5145,29 +5059,15 @@ new_media_col(pwg_size_t *size,	/* I - media-size/margin values */
+   media_col = ippNew();
+ 
+   media_size = ippNew();
+-  ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"x-dimension", size->width);
+-  ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"y-dimension", size->length);
++  ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "x-dimension", size->width);
++  ippAddInteger(media_size, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "y-dimension", size->length);
+   ippAddCollection(media_col, IPP_TAG_PRINTER, "media-size", media_size);
+   ippDelete(media_size);
+ 
+-  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"media-bottom-margin", size->bottom);
+-  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"media-left-margin", size->left);
+-  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"media-right-margin", size->right);
+-  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
+-		"media-top-margin", size->top);
+-
+-  if (source)
+-    ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-source",
+-		 NULL, source);
+-
+-  if (type)
+-    ippAddString(media_col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-type",
+-		 NULL, type);
++  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin", size->bottom);
++  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin", size->left);
++  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin", size->right);
++  ippAddInteger(media_col, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin", size->top);
+ 
+   return (media_col);
+ }
diff --git a/SOURCES/cups-ppdopen-heap-overflow.patch b/SOURCES/cups-ppdopen-heap-overflow.patch
new file mode 100644
index 0000000..4b725e1
--- /dev/null
+++ b/SOURCES/cups-ppdopen-heap-overflow.patch
@@ -0,0 +1,42 @@
+diff --git a/cups/ppd.c b/cups/ppd.c
+index ff52df2e..199cf034 100644
+--- a/cups/ppd.c
++++ b/cups/ppd.c
+@@ -1719,8 +1719,7 @@ _ppdOpen(
+                      constraint->choice1, constraint->option2,
+ 		     constraint->choice2))
+       {
+-        case 0 : /* Error */
+-	case 1 : /* Error */
++        default : /* Error */
+ 	    pg->ppd_status = PPD_BAD_UI_CONSTRAINTS;
+ 	    goto error;
+ 
+diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx
+index c25d4966..236c00db 100644
+--- a/ppdc/ppdc-source.cxx
++++ b/ppdc/ppdc-source.cxx
+@@ -1743,15 +1743,17 @@ ppdcSource::get_resolution(ppdcFile *fp)// I - File to read
+ 
+   switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
+   {
+-    case 0 :
+-        _cupsLangPrintf(stderr,
+-	                _("ppdc: Bad resolution name \"%s\" on line %d of "
+-			  "%s."), name, fp->line, fp->filename);
+-        break;
+     case 1 :
+         ydpi = xdpi;
+ 	break;
+-  }
++    case 2 :
++        break;
++    default :
++        _cupsLangPrintf(stderr,
++                  _("ppdc: Bad resolution name \"%s\" on line %d of "
++        "%s."), name, fp->line, fp->filename);
++        break;
++}
+ 
+   // Create the necessary PS commands...
+   snprintf(command, sizeof(command),
diff --git a/SOURCES/cups-rastertoepson-crash.patch b/SOURCES/cups-rastertoepson-crash.patch
new file mode 100644
index 0000000..11f6673
--- /dev/null
+++ b/SOURCES/cups-rastertoepson-crash.patch
@@ -0,0 +1,13 @@
+diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c
+index 4efe669..e8fe0c6 100644
+--- a/filter/rastertoepson.c
++++ b/filter/rastertoepson.c
+@@ -307,7 +307,7 @@ StartPage(
+ 
+   if (DotBytes)
+   {
+-    if ((LineBuffers[0] = calloc((size_t)DotBytes, header->cupsWidth * (size_t)(Shingling + 1))) == NULL)
++    if ((LineBuffers[0] = calloc((size_t)DotBytes, (header->cupsWidth + 7) * (size_t)(Shingling + 1))) == NULL)
+     {
+       fputs("ERROR: Unable to allocate memory\n", stderr);
+       exit(1);
diff --git a/SPECS/cups.spec b/SPECS/cups.spec
index bb99862..5110061 100644
--- a/SPECS/cups.spec
+++ b/SPECS/cups.spec
@@ -15,7 +15,7 @@ Summary: CUPS printing system
 Name: cups
 Epoch: 1
 Version: 2.2.6
-Release: 30%{?dist}
+Release: 38%{?dist}
 License: GPLv2+ and LGPLv2 with exceptions and AML
 Url: http://www.cups.org/
 Source0: https://github.com/apple/cups/releases/download/v%{VERSION}/cups-%{VERSION}-source.tar.gz
@@ -87,6 +87,20 @@ Patch50: cups-do-not-advertise-http-methods.patch
 # 1774462, 1774463 - CVE-2019-8696, CVE-2019-8675 - buffer overflow in SNMP and IPP,
 # memory disclosure and DoS in scheduler
 Patch51: 0001-Multiple-security-disclosure-issues.patch
+# 1775668 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created
+Patch52: cups-memory-consumption.patch
+# 1784884 - cups.service doesn't execute automatically on request
+Patch53: cups-autostart-when-enabled.patch
+# 1825253 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c
+Patch54: cups-ppdopen-heap-overflow.patch
+# 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied)
+Patch55: cups-etimedout.patch
+# 1689207 - Add failover backend
+Patch56: cups-failover-backend.patch
+# 1833516 - DirtyCleanInterval ignored if there are open client connections
+Patch57: cups-dirtyclean.patch
+# 1775590 - rastertoepson filter crashes with paper size A6
+Patch58: cups-rastertoepson-crash.patch
 
 Patch100: cups-lspp.patch
 
@@ -317,6 +331,20 @@ Sends IPP requests to the specified URI and tests and/or displays the results.
 # 1774462, 1774463 - CVE-2019-8696, CVE-2019-8675 - buffer overflow in SNMP and IPP,
 # memory disclosure and DoS in scheduler
 %patch51 -p1 -b .cve-in-scheduler
+# 1775668 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created
+%patch52 -p1 -b .memory-consumption
+# 1784884 - cups.service doesn't execute automatically on request
+%patch53 -p1 -b .autostart-when-enabled
+# 1825253 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c
+%patch54 -p1 -b .ppdopen-heap-overflow
+# 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied)
+%patch55 -p1 -b .etimedout
+# 1689207 - Add failover backend
+%patch56 -p1 -b .failover
+# 1833516 - DirtyCleanInterval ignored if there are open client connections
+%patch57 -p1 -b .dirtyclean
+# 1775590 - rastertoepson filter crashes with paper size A6
+%patch58 -p1 -b .rastertoepson-crash
 
 sed -i -e '1iMaxLogSize 0' conf/cupsd.conf.in
 
@@ -512,6 +540,13 @@ do
 done
 %endif
 
+%{_bindir}/rm /var/cache/cups/*.data > /dev/null 2>&1
+
+if [ -e /etc/systemd/system/printer.target.wants/cups.service ]
+then
+  %{_bindir}/systemctl enable cups.service > /dev/null 2>&1
+fi
+
 exit 0
 
 %post client
@@ -720,6 +755,38 @@ rm -f %{cups_serverbin}/backend/smb
 %{_mandir}/man5/ipptoolfile.5.gz
 
 %changelog
+* Tue May 26 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-38
+- 1775590 - rastertoepson filter crashes with paper size A6
+
+* Mon May 25 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-37
+- forgot to enable optimization - 1833516 
+
+* Fri May 22 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-36
+- 1838449 - ipp/socket backends connect to turned off device for eternity (contimeout is not applied)
+- 1689207 - Add failover backend
+- 1833516 - DirtyCleanInterval ignored if there are open client connections
+
+* Tue Apr 21 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-35
+- 1825254 - CVE-2020-3898 cups: heap based buffer overflow in libcups's ppdFindOption() in ppd-mark.c
+
+* Mon Apr 20 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-34
+- 1809002 - scriptlet issue, /usr/bin/rm: cannot remove '/var/cache/cups/*.data'
+
+* Thu Apr 09 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-34
+- 1784884 - cups.service doesn't execute automatically on request
+
+* Wed Apr 08 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-34
+- 1822135 - _ppdOpen() leaks 'string' variable
+
+* Fri Feb 14 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-33
+- fix more memory leaks found by coverity in 1775668
+
+* Fri Feb 14 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-32
+- fix covscan issues raised by 1775668
+
+* Thu Feb 06 2020 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-31
+- 1775668 - cupsd eats a lot of memory when lots of queue with extensive PPDs are created
+
 * Tue Nov 26 2019 Zdenek Dohnal <zdohnal@redhat.com> - 1:2.2.6-30
 - 1774462 - CVE-2019-8675 - buffer overflow in SNMP and IPP, memory disclosure and DoS in scheduler
 - 1774463 - CVE-2019-8696