]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cgi-bin/admin.c
Fix build errors on Fedora.
[thirdparty/cups.git] / cgi-bin / admin.c
index 70a57dc5e0e0d7a35bb6fae7101b67b2e4abdb5f..6c794d5de21db6cb46de5aaf290f04b8ed583400 100644 (file)
@@ -1,37 +1,16 @@
 /*
- * "$Id: admin.c 7888 2008-08-29 21:16:56Z mike $"
+ * "$Id$"
  *
- *   Administration CGI for the Common UNIX Printing System (CUPS).
+ * Administration CGI for CUPS.
  *
- *   Copyright 2007-2008 by Apple Inc.
- *   Copyright 1997-2007 by Easy Software Products.
+ * Copyright 2007-2014 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products.
  *
- *   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"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * Contents:
- *
- *   main()                    - Main entry for CGI.
- *   do_add_rss_subscription() - Add a RSS subscription.
- *   do_am_class()             - Add or modify a class.
- *   do_am_printer()           - Add or modify a printer.
- *   do_cancel_subscription()  - Cancel a subscription.
- *   do_config_server()        - Configure server settings.
- *   do_delete_class()         - Delete a class.
- *   do_delete_printer()       - Delete a printer.
- *   do_export()               - Export printers to Samba.
- *   do_list_printers()        - List available printers.
- *   do_menu()                 - Show the main menu.
- *   do_printer_op()           - Do a printer operation.
- *   do_set_allowed_users()    - Set the allowed/denied users for a queue.
- *   do_set_options()          - Configure the default options for a queue.
- *   do_set_sharing()          - Set printer-is-shared value.
- *   get_option_value()        - Return the value of an option.
- *   get_points()              - Get a value in points.
- *   match_string()            - Return the number of matching characters.
+ * 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"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  */
 
 /*
@@ -40,7 +19,7 @@
 
 #include "cgi-private.h"
 #include <cups/adminutil.h>
-#include <cups/file.h>
+#include <cups/ppd.h>
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
 
 
+/*
+ * Local globals...
+ */
+
+static int     current_device = 0;     /* Current device shown */
+
+
 /*
  * Local functions...
  */
 
+static void    choose_device_cb(const char *device_class,
+                                 const char *device_id, const char *device_info,
+                                 const char *device_make_and_model,
+                                 const char *device_uri,
+                                 const char *device_location,
+                                const char *title);
 static void    do_add_rss_subscription(http_t *http);
 static void    do_am_class(http_t *http, int modify);
 static void    do_am_printer(http_t *http, int modify);
 static void    do_cancel_subscription(http_t *http);
-static void    do_set_options(http_t *http, int is_class);
 static void    do_config_server(http_t *http);
 static void    do_delete_class(http_t *http);
 static void    do_delete_printer(http_t *http);
 static void    do_export(http_t *http);
 static void    do_list_printers(http_t *http);
 static void    do_menu(http_t *http);
-static void    do_printer_op(http_t *http,
-                             ipp_op_t op, const char *title);
 static void    do_set_allowed_users(http_t *http);
+static void    do_set_default(http_t *http);
+static void    do_set_options(http_t *http, int is_class);
 static void    do_set_sharing(http_t *http);
 static char    *get_option_value(ppd_file_t *ppd, const char *name,
                                  char *buffer, size_t bufsize);
 static double  get_points(double number, const char *uval);
-static int     match_string(const char *a, const char *b);
 
 
 /*
@@ -78,8 +68,7 @@ static int    match_string(const char *a, const char *b);
  */
 
 int                                    /* O - Exit status */
-main(int  argc,                                /* I - Number of command-line arguments */
-     char *argv[])                     /* I - Command-line arguments */
+main(void)
 {
   http_t       *http;                  /* Connection to the server */
   const char   *op;                    /* Operation name */
@@ -110,6 +99,7 @@ main(int  argc,                              /* I - Number of command-line arguments */
   */
 
   cgiSetVariable("SECTION", "admin");
+  cgiSetVariable("REFRESH_PAGE", "");
 
  /*
   * See if we have form data...
@@ -133,24 +123,33 @@ main(int  argc,                           /* I - Number of command-line arguments */
 
     fprintf(stderr, "DEBUG: op=\"%s\"...\n", op);
 
-    if (!strcmp(op, "start-printer"))
-      do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer")));
-    else if (!strcmp(op, "stop-printer"))
-      do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Printer")));
-    else if (!strcmp(op, "start-class"))
-      do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Class")));
-    else if (!strcmp(op, "stop-class"))
-      do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Class")));
-    else if (!strcmp(op, "accept-jobs"))
-      do_printer_op(http, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs")));
-    else if (!strcmp(op, "reject-jobs"))
-      do_printer_op(http, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs")));
-    else if (!strcmp(op, "purge-jobs"))
-      do_printer_op(http, IPP_PURGE_JOBS, cgiText(_("Purge Jobs")));
+    if (!*op)
+    {
+      const char *printer = getenv("PRINTER_NAME"),
+                                       /* Printer or class name */
+               *server_port = getenv("SERVER_PORT");
+                                       /* Port number string */
+      int      port = atoi(server_port ? server_port : "0");
+                                       /* Port number */
+      char     uri[1024];              /* URL */
+
+      if (printer)
+        httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri),
+                        getenv("HTTPS") ? "https" : "http", NULL,
+                        getenv("SERVER_NAME"), port, "/%s/%s",
+                        cgiGetVariable("IS_CLASS") ? "classes" : "printers",
+                        printer);
+      else
+        httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri),
+                       getenv("HTTPS") ? "https" : "http", NULL,
+                       getenv("SERVER_NAME"), port, "/admin");
+
+      printf("Location: %s\n\n", uri);
+    }
     else if (!strcmp(op, "set-allowed-users"))
       do_set_allowed_users(http);
     else if (!strcmp(op, "set-as-default"))
-      do_printer_op(http, CUPS_SET_DEFAULT, cgiText(_("Set As Default")));
+      do_set_default(http);
     else if (!strcmp(op, "set-sharing"))
       do_set_sharing(http);
     else if (!strcmp(op, "find-new-printers") ||
@@ -193,7 +192,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   }
   else if (op && !strcmp(op, "redirect"))
   {
-    const char *url;                   /* Redirection URL... */
+    const char *url;                   /* Redirection URL... */
     char       prefix[1024];           /* URL prefix */
 
 
@@ -207,7 +206,50 @@ main(int  argc,                            /* I - Number of command-line arguments */
     fprintf(stderr, "DEBUG: redirecting with prefix %s!\n", prefix);
 
     if ((url = cgiGetVariable("URL")) != NULL)
-      printf("Location: %s%s\n\n", prefix, url);
+    {
+      char     encoded[1024],          /* Encoded URL string */
+               *ptr;                   /* Pointer into encoded string */
+
+
+      ptr = encoded;
+      if (*url != '/')
+        *ptr++ = '/';
+
+      for (; *url && ptr < (encoded + sizeof(encoded) - 4); url ++)
+      {
+        if (strchr("%@&+ <>#=", *url) || *url < ' ' || *url & 128)
+       {
+        /*
+         * Percent-encode this character; safe because we have at least 4
+         * bytes left in the array...
+         */
+
+         sprintf(ptr, "%%%02X", *url & 255);
+         ptr += 3;
+       }
+       else
+         *ptr++ = *url;
+      }
+
+      *ptr = '\0';
+
+      if (*url)
+      {
+       /*
+        * URL was too long, just redirect to the admin page...
+       */
+
+       printf("Location: %s/admin\n\n", prefix);
+      }
+      else
+      {
+       /*
+        * URL is OK, redirect there...
+       */
+
+        printf("Location: %s%s\n\n", prefix, encoded);
+      }
+    }
     else
       printf("Location: %s/admin\n\n", prefix);
   }
@@ -236,6 +278,50 @@ main(int  argc,                            /* I - Number of command-line arguments */
 }
 
 
+/*
+ * 'choose_device_cb()' - Add a device to the device selection page.
+ */
+
+static void
+choose_device_cb(
+    const char *device_class,          /* I - Class */
+    const char *device_id,             /* I - 1284 device ID */
+    const char *device_info,           /* I - Description */
+    const char *device_make_and_model, /* I - Make and model */
+    const char *device_uri,            /* I - Device URI */
+    const char *device_location,       /* I - Location */
+    const char *title)                 /* I - Page title */
+{
+ /*
+  * For modern browsers, start a multi-part page so we can show that something
+  * is happening.  Non-modern browsers just get everything at the end...
+  */
+
+  if (current_device == 0 && cgiSupportsMultipart())
+  {
+    cgiStartMultipart();
+    cgiStartHTML(title);
+    cgiCopyTemplateLang("choose-device.tmpl");
+    cgiEndHTML();
+    fflush(stdout);
+  }
+
+
+ /*
+  * Add the device to the array...
+  */
+
+  cgiSetArray("device_class", current_device, device_class);
+  cgiSetArray("device_id", current_device, device_id);
+  cgiSetArray("device_info", current_device, device_info);
+  cgiSetArray("device_make_and_model", current_device, device_make_and_model);
+  cgiSetArray("device_uri", current_device, device_uri);
+  cgiSetArray("device_location", current_device, device_location);
+
+  current_device ++;
+}
+
+
 /*
  * 'do_add_rss_subscription()' - Add a RSS subscription.
  */
@@ -301,6 +387,31 @@ do_add_rss_subscription(http_t *http)      /* I - HTTP connection */
     * and classes and (re)show the add page...
     */
 
+    if (cgiGetVariable("EVENT_JOB_CREATED"))
+      cgiSetVariable("EVENT_JOB_CREATED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_COMPLETED"))
+      cgiSetVariable("EVENT_JOB_COMPLETED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_STOPPED"))
+      cgiSetVariable("EVENT_JOB_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_CONFIG_CHANGED"))
+      cgiSetVariable("EVENT_JOB_CONFIG_CHANGED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_STOPPED"))
+      cgiSetVariable("EVENT_PRINTER_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_ADDED"))
+      cgiSetVariable("EVENT_PRINTER_ADDED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_MODIFIED"))
+      cgiSetVariable("EVENT_PRINTER_MODIFIED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_DELETED"))
+      cgiSetVariable("EVENT_PRINTER_DELETED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_STARTED"))
+      cgiSetVariable("EVENT_SERVER_STARTED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_STOPPED"))
+      cgiSetVariable("EVENT_SERVER_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_RESTARTED"))
+      cgiSetVariable("EVENT_SERVER_RESTARTED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_AUDIT"))
+      cgiSetVariable("EVENT_SERVER_AUDIT", "CHECKED");
+
     request  = ippNewRequest(CUPS_GET_PRINTERS);
     response = cupsDoRequest(http, request, "/");
 
@@ -363,7 +474,7 @@ do_add_rss_subscription(http_t *http)       /* I - HTTP connection */
 
   request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION);
 
-  if (!strcasecmp(printer_uri, "#ALL#"))
+  if (!_cups_strcasecmp(printer_uri, "#ALL#"))
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                  NULL, "ipp://localhost/");
   else
@@ -390,7 +501,7 @@ do_add_rss_subscription(http_t *http)       /* I - HTTP connection */
   else if (cupsLastError() > IPP_OK_CONFLICT)
   {
     cgiStartHTML(_("Add RSS Subscription"));
-    cgiShowIPPError(_("Unable to add RSS subscription:"));
+    cgiShowIPPError(_("Unable to add RSS subscription"));
   }
   else
   {
@@ -423,6 +534,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
   ipp_attribute_t *attr;               /* member-uris attribute */
   char         uri[HTTP_MAX_URI];      /* Device or printer URI */
   const char   *name,                  /* Pointer to class name */
+               *op,                    /* Operation name */
                *ptr;                   /* Pointer to CGI variable */
   const char   *title;                 /* Title of page */
   static const char * const pattrs[] = /* Requested printer attributes */
@@ -434,6 +546,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
 
 
   title = cgiText(modify ? _("Modify Class") : _("Add Class"));
+  op    = cgiGetVariable("OP");
   name  = cgiGetVariable("PRINTER_NAME");
 
   if (cgiGetVariable("PRINTER_LOCATION") == NULL)
@@ -448,10 +561,21 @@ do_am_class(http_t *http,         /* I - HTTP connection */
 
     request = ippNewRequest(CUPS_GET_PRINTERS);
 
+    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+                 CUPS_PRINTER_LOCAL);
+    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+                 CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
+
    /*
     * Do the request and get back a response...
     */
 
+    cgiClearVariables();
+    if (op)
+      cgiSetVariable("OP", op);
+    if (name)
+      cgiSetVariable("PRINTER_NAME", name);
+
     if ((response = cupsDoRequest(http, request, "/")) != NULL)
     {
      /*
@@ -464,7 +588,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
        if (attr->name && !strcmp(attr->name, "printer-uri-supported"))
        {
          if ((ptr = strrchr(attr->values[0].string.text, '/')) != NULL &&
-             (!name || strcasecmp(name, ptr + 1)))
+             (!name || _cups_strcasecmp(name, ptr + 1)))
          {
           /*
            * Don't show the current class...
@@ -480,7 +604,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
           attr = attr->next)
        if (attr->name && !strcmp(attr->name, "printer-name"))
        {
-         if (!name || strcasecmp(name, attr->values[0].string.text))
+         if (!name || _cups_strcasecmp(name, attr->values[0].string.text))
          {
           /*
            * Don't show the current class...
@@ -541,7 +665,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
          {
            for (j = 0; j < num_printers; j ++)
            {
-             if (!strcasecmp(attr->values[i].string.text,
+             if (!_cups_strcasecmp(attr->values[i].string.text,
                              cgiGetArray("MEMBER_NAMES", j)))
              {
                cgiSetArray("MEMBER_SELECTED", j, "SELECTED");
@@ -584,6 +708,15 @@ do_am_class(http_t *http,          /* I - HTTP connection */
     return;
   }
 
+  if (!name)
+  {
+    cgiStartHTML(title);
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+    cgiCopyTemplateLang("error.tmpl");
+    cgiEndHTML();
+    return;
+  }
+
   for (ptr = name; *ptr; ptr ++)
     if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
       break;
@@ -618,8 +751,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
   request = ippNewRequest(CUPS_ADD_CLASS);
 
   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                   "localhost", 0, "/classes/%s",
-                  cgiGetVariable("PRINTER_NAME"));
+                   "localhost", 0, "/classes/%s", name);
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                NULL, uri);
 
@@ -639,7 +771,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
     attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
                          num_printers, NULL, NULL);
     for (i = 0; i < num_printers; i ++)
-      attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i));
+      attr->values[i].string.text = _cupsStrAlloc(cgiGetArray("MEMBER_URIS", i));
   }
 
  /*
@@ -656,8 +788,8 @@ do_am_class(http_t *http,           /* I - HTTP connection */
   else if (cupsLastError() > IPP_OK_CONFLICT)
   {
     cgiStartHTML(title);
-    cgiShowIPPError(modify ? _("Unable to modify class:") :
-                             _("Unable to add class:"));
+    cgiShowIPPError(modify ? _("Unable to modify class") :
+                             _("Unable to add class"));
   }
   else
   {
@@ -805,22 +937,20 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
         *makeptr = '\0';
       else if ((makeptr = strchr(make, '-')) != NULL)
         *makeptr = '\0';
-      else if (!strncasecmp(make, "laserjet", 8) ||
-               !strncasecmp(make, "deskjet", 7) ||
-               !strncasecmp(make, "designjet", 9))
-        strcpy(make, "HP");
-      else if (!strncasecmp(make, "phaser", 6))
-        strcpy(make, "Xerox");
-      else if (!strncasecmp(make, "stylus", 6))
-        strcpy(make, "Epson");
+      else if (!_cups_strncasecmp(make, "laserjet", 8) ||
+               !_cups_strncasecmp(make, "deskjet", 7) ||
+               !_cups_strncasecmp(make, "designjet", 9))
+        strlcpy(make, "HP", sizeof(make));
+      else if (!_cups_strncasecmp(make, "phaser", 6))
+        strlcpy(make, "Xerox", sizeof(make));
+      else if (!_cups_strncasecmp(make, "stylus", 6))
+        strlcpy(make, "Epson", sizeof(make));
       else
-        strcpy(make, "Generic");
+        strlcpy(make, "Generic", sizeof(make));
 
       if (!cgiGetVariable("CURRENT_MAKE"))
         cgiSetVariable("CURRENT_MAKE", make);
 
-      cgiSetVariable("PPD_MAKE", make);
-
       if (!cgiGetVariable("CURRENT_MAKE_AND_MODEL"))
         cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr);
 
@@ -837,7 +967,8 @@ do_am_printer(http_t *http,         /* I - HTTP connection */
          if (isalnum(*uriptr & 255) || *uriptr == '_' || *uriptr == '-' ||
              *uriptr == '.')
            *tptr++ = *uriptr;
-         else if ((*uriptr == ' ' || *uriptr == '/') && tptr[-1] != '_')
+         else if ((*uriptr == ' ' || *uriptr == '/') && tptr > template &&
+                  tptr[-1] != '_')
            *tptr++ = '_';
          else if (*uriptr == '?' || *uriptr == '(')
            break;
@@ -852,56 +983,65 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
   if (!var)
   {
    /*
-    * Build a CUPS_GET_DEVICES request, which requires the following
-    * attributes:
-    *
-    *    attributes-charset
-    *    attributes-natural-language
-    *    printer-uri
+    * Look for devices so the user can pick something...
     */
 
-    fputs("DEBUG: Getting list of devices...\n", stderr);
-
-    request = ippNewRequest(CUPS_GET_DEVICES);
+    if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
+    {
+      strlcpy(uri, attr->values[0].string.text, sizeof(uri));
+      if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0)
+        *uriptr = '\0';
 
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-                 NULL, "ipp://localhost/printers/");
+      cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text);
+      cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
+    }
 
    /*
-    * Do the request and get back a response...
+    * Scan for devices for up to 30 seconds...
     */
 
-    if ((response = cupsDoRequest(http, request, "/")) != NULL)
+    fputs("DEBUG: Getting list of devices...\n", stderr);
+
+    current_device = 0;
+    if (cupsGetDevices(http, 5, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
+                       (cups_device_cb_t)choose_device_cb,
+                      (void *)title) == IPP_OK)
     {
       fputs("DEBUG: Got device list!\n", stderr);
 
-      cgiSetIPPVars(response, NULL, NULL, NULL, 0);
-      ippDelete(response);
+      if (cgiSupportsMultipart())
+        cgiStartMultipart();
+
+      cgiSetVariable("CUPS_GET_DEVICES_DONE", "1");
+      cgiStartHTML(title);
+      cgiCopyTemplateLang("choose-device.tmpl");
+      cgiEndHTML();
+
+      if (cgiSupportsMultipart())
+        cgiEndMultipart();
     }
     else
+    {
       fprintf(stderr,
               "ERROR: CUPS-Get-Devices request failed with status %x: %s\n",
              cupsLastError(), cupsLastErrorString());
-
-   /*
-    * Let the user choose...
-    */
-
-    if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
-    {
-      strlcpy(uri, attr->values[0].string.text, sizeof(uri));
-      if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0)
-        *uriptr = '\0';
-
-      cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text);
-      cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
+      if (cupsLastError() == IPP_NOT_AUTHORIZED)
+      {
+       puts("Status: 401\n");
+       exit(0);
+      }
+      else
+      {
+       cgiStartHTML(title);
+       cgiShowIPPError(modify ? _("Unable to modify printer") :
+                                _("Unable to add printer"));
+       cgiEndHTML();
+        return;
+      }
     }
-
-    cgiStartHTML(title);
-    cgiCopyTemplateLang("choose-device.tmpl");
-    cgiEndHTML();
   }
-  else if (strchr(var, '/') == NULL)
+  else if (!strchr(var, '/') ||
+           (!strncmp(var, "lpd://", 6) && !strchr(var + 6, '/')))
   {
     if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
     {
@@ -965,6 +1105,11 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
         if ((attr = ippFindAttribute(oldinfo, "printer-location",
                                     IPP_TAG_TEXT)) != NULL)
           cgiSetVariable("PRINTER_LOCATION", attr->values[0].string.text);
+
+       if ((attr = ippFindAttribute(oldinfo, "printer-is-shared",
+                                    IPP_TAG_BOOLEAN)) != NULL)
+         cgiSetVariable("PRINTER_IS_SHARED",
+                        attr->values[0].boolean ? "1" : "0");
       }
 
       cgiCopyTemplateLang("modify-printer.tmpl");
@@ -992,9 +1137,10 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
 
     return;
   }
-  else if (!file && !cgiGetVariable("PPD_NAME"))
+  else if (!file &&
+           (!cgiGetVariable("PPD_NAME") || cgiGetVariable("SELECT_MAKE")))
   {
-    if (modify)
+    if (modify && !cgiGetVariable("SELECT_MAKE"))
     {
      /*
       * Get the PPD file...
@@ -1004,7 +1150,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
       char             filename[1024]; /* PPD filename */
       ppd_file_t       *ppd;           /* PPD information */
       char             buffer[1024];   /* Buffer */
-      int              bytes;          /* Number of bytes */
+      ssize_t          bytes;          /* Number of bytes */
       http_status_t    get_status;     /* Status of GET */
 
 
@@ -1018,13 +1164,15 @@ do_am_printer(http_t *http,             /* I - HTTP connection */
 
       if (get_status != HTTP_OK)
       {
+        httpFlush(http);
+
         fprintf(stderr, "ERROR: Unable to get PPD file %s: %d - %s\n",
                uri, get_status, httpStatus(get_status));
       }
       else if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0)
       {
        while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
-          write(fd, buffer, bytes);
+          write(fd, buffer, (size_t)bytes);
 
        close(fd);
 
@@ -1041,8 +1189,10 @@ do_am_printer(http_t *http,              /* I - HTTP connection */
        }
        else
        {
+         int linenum;                  /* Line number */
+
          fprintf(stderr, "ERROR: Unable to open PPD file %s: %s\n",
-                 filename, ppdErrorString(ppdLastError(&bytes)));
+                 filename, ppdErrorString(ppdLastError(&linenum)));
        }
       }
       else
@@ -1069,11 +1219,20 @@ do_am_printer(http_t *http,             /* I - HTTP connection */
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                  NULL, "ipp://localhost/printers/");
 
-    if ((var = cgiGetVariable("CURRENT_MAKE")) == NULL)
-      var = cgiGetVariable("PPD_MAKE");
-    if (var)
+    if ((var = cgiGetVariable("PPD_MAKE")) == NULL)
+      var = cgiGetVariable("CURRENT_MAKE");
+    if (var && !cgiGetVariable("SELECT_MAKE"))
+    {
+      const char *make_model;          /* Make and model */
+
+
       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
                    "ppd-make", NULL, var);
+
+      if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
+       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+                    "ppd-make-and-model", NULL, make_model);
+    }
     else
       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                    "requested-attributes", NULL, "ppd-make");
@@ -1088,7 +1247,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
       * Got the list of PPDs, see if the user has selected a make...
       */
 
-      if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0)
+      if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0 && !modify)
       {
        /*
         * No PPD files with this make, try again with all makes...
@@ -1123,47 +1282,12 @@ do_am_printer(http_t *http,             /* I - HTTP connection */
        * Let the user choose a model...
        */
 
-        const char     *make_model;    /* Current make/model string */
-
-
-        if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
-       {
-        /*
-         * Scan for "close" matches...
-         */
-
-          int          match,          /* Current match */
-                       best_match,     /* Best match so far */
-                       count;          /* Number of drivers */
-         const char    *best,          /* Best matching string */
-                       *current;       /* Current string */
-
-
-          count = cgiGetSize("PPD_MAKE_AND_MODEL");
-
-         for (i = 0, best_match = 0, best = NULL; i < count; i ++)
-         {
-           current = cgiGetArray("PPD_MAKE_AND_MODEL", i);
-           match   = match_string(make_model, current);
-
-           if (match > best_match)
-           {
-             best_match = match;
-             best       = current;
-           }
-         }
-
-          if (best_match > strlen(var))
-         {
-          /*
-           * Found a match longer than the make...
-           */
-
-            cgiSetVariable("CURRENT_MAKE_AND_MODEL", best);
-         }
-       }
-
         cgiStartHTML(title);
+       if (!cgiGetVariable("PPD_MAKE"))
+         cgiSetVariable("PPD_MAKE", cgiGetVariable("CURRENT_MAKE"));
+       if (!modify)
+         cgiSetVariable("CURRENT_MAKE_AND_MODEL",
+                        cgiGetArray("PPD_MAKE_AND_MODEL", 0));
        cgiCopyTemplateLang("choose-model.tmpl");
         cgiEndHTML();
       }
@@ -1173,7 +1297,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
     else
     {
       cgiStartHTML(title);
-      cgiShowIPPError(_("Unable to get list of printer drivers:"));
+      cgiShowIPPError(_("Unable to get list of printer drivers"));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
     }
@@ -1204,20 +1328,20 @@ do_am_printer(http_t *http,             /* I - HTTP connection */
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                  NULL, uri);
 
-    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
-                 NULL, cgiGetVariable("PRINTER_LOCATION"));
-
-    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
-                 NULL, cgiGetVariable("PRINTER_INFO"));
-
     if (!file)
     {
       var = cgiGetVariable("PPD_NAME");
       if (strcmp(var, "__no_change__"))
-       ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
+       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name",
                     NULL, var);
     }
 
+    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
+                 NULL, cgiGetVariable("PRINTER_LOCATION"));
+
+    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
+                 NULL, cgiGetVariable("PRINTER_INFO"));
+
     strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri));
 
    /*
@@ -1236,7 +1360,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
       if ((uriptr = strchr(uri, '?')) == NULL)
         uriptr = uri + strlen(uri);
 
-      snprintf(uriptr, sizeof(uri) - (uriptr - uri),
+      snprintf(uriptr, sizeof(uri) - (size_t)(uriptr - uri),
                "?baud=%s+bits=%s+parity=%s+flow=%s",
                cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"),
               cgiGetVariable("PARITY"), cgiGetVariable("FLOW"));
@@ -1271,8 +1395,8 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
     else if (cupsLastError() > IPP_OK_CONFLICT)
     {
       cgiStartHTML(title);
-      cgiShowIPPError(modify ? _("Unable to modify printer:") :
-                               _("Unable to add printer:"));
+      cgiShowIPPError(modify ? _("Unable to modify printer") :
+                               _("Unable to add printer"));
     }
     else if (modify)
     {
@@ -1337,7 +1461,7 @@ do_cancel_subscription(http_t *http)/* I - HTTP connection */
 
   if (id <= 0)
   {
-    cgiSetVariable("ERROR", cgiText(_("Bad subscription ID!")));
+    cgiSetVariable("ERROR", cgiText(_("Bad subscription ID")));
     cgiStartHTML(_("Cancel RSS Subscription"));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -1378,7 +1502,7 @@ do_cancel_subscription(http_t *http)/* I - HTTP connection */
   else if (cupsLastError() > IPP_OK_CONFLICT)
   {
     cgiStartHTML(_("Cancel RSS Subscription"));
-    cgiShowIPPError(_("Unable to cancel RSS subscription:"));
+    cgiShowIPPError(_("Unable to cancel RSS subscription"));
   }
   else
   {
@@ -1413,29 +1537,41 @@ do_config_server(http_t *http)          /* I - HTTP connection */
     int                        advanced,       /* Advanced settings shown? */
                        changed;        /* Have settings changed? */
     const char         *debug_logging, /* DEBUG_LOGGING value */
+                       *preserve_jobs = NULL,
+                                       /* PRESERVE_JOBS value */
                        *remote_admin,  /* REMOTE_ADMIN value */
                        *remote_any,    /* REMOTE_ANY value */
-                       *remote_printers,
-                                       /* REMOTE_PRINTERS value */
                        *share_printers,/* SHARE_PRINTERS value */
                        *user_cancel_any,
                                        /* USER_CANCEL_ANY value */
-                       *browse_web_if, /* BrowseWebIF value */
-                       *preserve_job_history,
+                       *browse_web_if = NULL,
+                                       /* BrowseWebIF value */
+                       *preserve_job_history = NULL,
+                                       /* PreserveJobHistory value */
+                       *preserve_job_files = NULL,
+                                       /* PreserveJobFiles value */
+                       *max_clients = NULL,
+                                       /* MaxClients value */
+                       *max_jobs = NULL,
+                                       /* MaxJobs value */
+                       *max_log_size = NULL;
+                                       /* MaxLogSize value */
+    const char         *current_browse_web_if,
+                                       /* BrowseWebIF value */
+                       *current_preserve_job_history,
                                        /* PreserveJobHistory value */
-                       *preserve_job_files,
+                       *current_preserve_job_files,
                                        /* PreserveJobFiles value */
-                       *max_clients,   /* MaxClients value */
-                       *max_jobs,      /* MaxJobs value */
-                       *max_log_size;  /* MaxLogSize value */
-    char               local_protocols[255],
-                                       /* BrowseLocalProtocols */
-                       remote_protocols[255];
-                                       /* BrowseRemoteProtocols */
+                       *current_max_clients,
+                                       /* MaxClients value */
+                       *current_max_jobs,
+                                       /* MaxJobs value */
+                       *current_max_log_size;
+                                       /* MaxLogSize value */
 #ifdef HAVE_GSSAPI
     char               default_auth_type[255];
                                        /* DefaultAuthType value */
-    const char         *val;           /* Setting value */ 
+    const char         *val;           /* Setting value */
 #endif /* HAVE_GSSAPI */
 
 
@@ -1446,7 +1582,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     debug_logging        = cgiGetVariable("DEBUG_LOGGING") ? "1" : "0";
     remote_admin         = cgiGetVariable("REMOTE_ADMIN") ? "1" : "0";
     remote_any           = cgiGetVariable("REMOTE_ANY") ? "1" : "0";
-    remote_printers      = cgiGetVariable("REMOTE_PRINTERS") ? "1" : "0";
     share_printers       = cgiGetVariable("SHARE_PRINTERS") ? "1" : "0";
     user_cancel_any      = cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0";
 
@@ -1458,80 +1593,37 @@ do_config_server(http_t *http)          /* I - HTTP connection */
       */
 
       browse_web_if        = cgiGetVariable("BROWSE_WEB_IF") ? "Yes" : "No";
-      preserve_job_history = cgiGetVariable("PRESERVE_JOB_HISTORY") ? "Yes" : "No";
-      preserve_job_files   = cgiGetVariable("PRESERVE_JOB_FILES") ? "Yes" : "No";
       max_clients          = cgiGetVariable("MAX_CLIENTS");
-      max_jobs             = cgiGetVariable("MAX_JOBS");
       max_log_size         = cgiGetVariable("MAX_LOG_SIZE");
+      preserve_jobs        = cgiGetVariable("PRESERVE_JOBS");
 
-      if (!max_clients || atoi(max_clients) <= 0)
-       max_clients = "100";
-
-      if (!max_jobs || atoi(max_jobs) <= 0)
-       max_jobs = "500";
-
-      if (!max_log_size || atof(max_log_size) <= 0.0)
-       max_log_size = "1m";
-
-      if (cgiGetVariable("BROWSE_LOCAL_CUPS"))
-       strcpy(local_protocols, "cups");
-      else
-       local_protocols[0] = '\0';
-
-#ifdef HAVE_DNSSD
-      if (cgiGetVariable("BROWSE_LOCAL_DNSSD"))
+      if (preserve_jobs)
       {
-       if (local_protocols[0])
-         strcat(local_protocols, " dnssd");
-       else
-         strcat(local_protocols, "dnssd");
-      }
-#endif /* HAVE_DNSSD */
+        max_jobs             = cgiGetVariable("MAX_JOBS");
+       preserve_job_history = cgiGetVariable("PRESERVE_JOB_HISTORY");
+       preserve_job_files   = cgiGetVariable("PRESERVE_JOB_FILES");
 
-#ifdef HAVE_LDAP
-      if (cgiGetVariable("BROWSE_LOCAL_LDAP"))
-      {
-       if (local_protocols[0])
-         strcat(local_protocols, " ldap");
-       else
-         strcat(local_protocols, "ldap");
-      }
-#endif /* HAVE_LDAP */
+       if (!max_jobs || atoi(max_jobs) < 0)
+         max_jobs = "500";
 
-#ifdef HAVE_LIBSLP
-      if (cgiGetVariable("BROWSE_LOCAL_SLP"))
-      {
-       if (local_protocols[0])
-         strcat(local_protocols, " slp");
-       else
-         strcat(local_protocols, "slp");
+       if (!preserve_job_history)
+         preserve_job_history = "On";
+
+       if (!preserve_job_files)
+         preserve_job_files = "1d";
       }
-#endif /* HAVE_SLP */
-      
-      if (cgiGetVariable("BROWSE_REMOTE_CUPS"))
-       strcpy(remote_protocols, "cups");
       else
-       remote_protocols[0] = '\0';
-
-#ifdef HAVE_LDAP
-      if (cgiGetVariable("BROWSE_REMOTE_LDAP"))
       {
-       if (remote_protocols[0])
-         strcat(remote_protocols, " ldap");
-       else
-         strcat(remote_protocols, "ldap");
+        max_jobs             = "0";
+        preserve_job_history = "No";
+        preserve_job_files   = "No";
       }
-#endif /* HAVE_LDAP */
 
-#ifdef HAVE_LIBSLP
-      if (cgiGetVariable("BROWSE_REMOTE_SLP"))
-      {
-       if (remote_protocols[0])
-         strcat(remote_protocols, " slp");
-       else
-         strcat(remote_protocols, "slp");
-      }
-#endif /* HAVE_SLP */
+      if (!max_clients || atoi(max_clients) <= 0)
+       max_clients = "100";
+
+      if (!max_log_size || atoi(max_log_size) <= 0.0)
+       max_log_size = "1m";
     }
 
    /*
@@ -1542,7 +1634,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     {
       cgiStartHTML(cgiText(_("Change Settings")));
       cgiSetVariable("MESSAGE",
-                     cgiText(_("Unable to change server settings:")));
+                     cgiText(_("Unable to change server settings")));
       cgiSetVariable("ERROR", cupsLastErrorString());
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
@@ -1560,7 +1652,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     {
       val = cupsGetOption("DefaultAuthType", num_settings, settings);
 
-      if (!val || !strcasecmp(val, "Negotiate"))
+      if (!val || !_cups_strcasecmp(val, "Negotiate"))
         strlcpy(default_auth_type, "Basic", sizeof(default_auth_type));
       else
         strlcpy(default_auth_type, val, sizeof(default_auth_type));
@@ -1569,6 +1661,32 @@ do_config_server(http_t *http)           /* I - HTTP connection */
     fprintf(stderr, "DEBUG: DefaultAuthType %s\n", default_auth_type);
 #endif /* HAVE_GSSAPI */
 
+    if ((current_browse_web_if = cupsGetOption("BrowseWebIF", num_settings,
+                                               settings)) == NULL)
+      current_browse_web_if = "No";
+
+    if ((current_preserve_job_history = cupsGetOption("PreserveJobHistory",
+                                                      num_settings,
+                                                     settings)) == NULL)
+      current_preserve_job_history = "Yes";
+
+    if ((current_preserve_job_files = cupsGetOption("PreserveJobFiles",
+                                                    num_settings,
+                                                   settings)) == NULL)
+      current_preserve_job_files = "1d";
+
+    if ((current_max_clients = cupsGetOption("MaxClients", num_settings,
+                                             settings)) == NULL)
+      current_max_clients = "100";
+
+    if ((current_max_jobs = cupsGetOption("MaxJobs", num_settings,
+                                          settings)) == NULL)
+      current_max_jobs = "500";
+
+    if ((current_max_log_size = cupsGetOption("MaxLogSize", num_settings,
+                                              settings)) == NULL)
+      current_max_log_size = "1m";
+
    /*
     * See if the settings have changed...
     */
@@ -1579,8 +1697,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                                                 num_settings, settings)) ||
              strcmp(remote_any, cupsGetOption(CUPS_SERVER_REMOTE_ANY,
                                               num_settings, settings)) ||
-             strcmp(remote_printers, cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                                   num_settings, settings)) ||
              strcmp(share_printers, cupsGetOption(CUPS_SERVER_SHARE_PRINTERS,
                                                   num_settings, settings)) ||
 #ifdef HAVE_GSSAPI
@@ -1592,25 +1708,12 @@ do_config_server(http_t *http)          /* I - HTTP connection */
                                                    num_settings, settings));
 
     if (advanced && !changed)
-      changed = cupsGetOption("BrowseLocalProtocols", num_settings, settings) ||
-               strcasecmp(local_protocols,
-                          CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS) ||
-               cupsGetOption("BrowseRemoteProtocols", num_settings,
-                             settings) ||
-               strcasecmp(remote_protocols,
-                          CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS) ||
-               cupsGetOption("BrowseWebIF", num_settings, settings) ||
-               strcasecmp(browse_web_if, "No") ||
-               cupsGetOption("PreserveJobHistory", num_settings, settings) ||
-               strcasecmp(preserve_job_history, "Yes") ||
-               cupsGetOption("PreserveJobFiles", num_settings, settings) ||
-               strcasecmp(preserve_job_files, "No") ||
-               cupsGetOption("MaxClients", num_settings, settings) ||
-               strcasecmp(max_clients, "100") ||
-               cupsGetOption("MaxJobs", num_settings, settings) ||
-               strcasecmp(max_jobs, "500") ||
-               cupsGetOption("MaxLogSize", num_settings, settings) ||
-               strcasecmp(max_log_size, "1m");
+      changed = _cups_strcasecmp(browse_web_if, current_browse_web_if) ||
+               _cups_strcasecmp(preserve_job_history, current_preserve_job_history) ||
+               _cups_strcasecmp(preserve_job_files, current_preserve_job_files) ||
+               _cups_strcasecmp(max_clients, current_max_clients) ||
+               _cups_strcasecmp(max_jobs, current_max_jobs) ||
+               _cups_strcasecmp(max_log_size, current_max_log_size);
 
     if (changed)
     {
@@ -1627,8 +1730,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                                    remote_admin, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
                                    remote_any, num_settings, &settings);
-      num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                   remote_printers, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                    share_printers, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
@@ -1644,37 +1745,23 @@ do_config_server(http_t *http)          /* I - HTTP connection */
         * Add advanced settings...
        */
 
-       if (cupsGetOption("BrowseLocalProtocols", num_settings, settings) ||
-           strcasecmp(local_protocols, CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS))
-         num_settings = cupsAddOption("BrowseLocalProtocols", local_protocols,
-                                      num_settings, &settings);
-       if (cupsGetOption("BrowseRemoteProtocols", num_settings, settings) ||
-           strcasecmp(remote_protocols, CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS))
-         num_settings = cupsAddOption("BrowseRemoteProtocols", remote_protocols,
-                                      num_settings, &settings);
-       if (cupsGetOption("BrowseWebIF", num_settings, settings) ||
-           strcasecmp(browse_web_if, "No"))
+       if (_cups_strcasecmp(browse_web_if, current_browse_web_if))
          num_settings = cupsAddOption("BrowseWebIF", browse_web_if,
                                       num_settings, &settings);
-       if (cupsGetOption("PreserveJobHistory", num_settings, settings) ||
-           strcasecmp(preserve_job_history, "Yes"))
+       if (_cups_strcasecmp(preserve_job_history, current_preserve_job_history))
          num_settings = cupsAddOption("PreserveJobHistory",
                                       preserve_job_history, num_settings,
                                       &settings);
-       if (cupsGetOption("PreserveJobFiles", num_settings, settings) ||
-           strcasecmp(preserve_job_files, "No"))
+       if (_cups_strcasecmp(preserve_job_files, current_preserve_job_files))
          num_settings = cupsAddOption("PreserveJobFiles", preserve_job_files,
                                       num_settings, &settings);
-        if (cupsGetOption("MaxClients", num_settings, settings) ||
-           strcasecmp(max_clients, "100"))
+        if (_cups_strcasecmp(max_clients, current_max_clients))
          num_settings = cupsAddOption("MaxClients", max_clients, num_settings,
                                       &settings);
-        if (cupsGetOption("MaxJobs", num_settings, settings) ||
-           strcasecmp(max_jobs, "500"))
+        if (_cups_strcasecmp(max_jobs, current_max_jobs))
          num_settings = cupsAddOption("MaxJobs", max_jobs, num_settings,
                                       &settings);
-        if (cupsGetOption("MaxLogSize", num_settings, settings) ||
-           strcasecmp(max_log_size, "1m"))
+        if (_cups_strcasecmp(max_log_size, current_max_log_size))
          num_settings = cupsAddOption("MaxLogSize", max_log_size, num_settings,
                                       &settings);
       }
@@ -1689,13 +1776,17 @@ do_config_server(http_t *http)          /* I - HTTP connection */
 
        cgiStartHTML(cgiText(_("Change Settings")));
        cgiSetVariable("MESSAGE",
-                       cgiText(_("Unable to change server settings:")));
+                       cgiText(_("Unable to change server settings")));
        cgiSetVariable("ERROR", cupsLastErrorString());
        cgiCopyTemplateLang("error.tmpl");
       }
       else
       {
-       cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
+        if (advanced)
+         cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&"
+                                        "URL=/admin/?ADVANCEDSETTINGS=YES");
+        else
+         cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
        cgiStartHTML(cgiText(_("Change Settings")));
        cgiCopyTemplateLang("restart.tmpl");
       }
@@ -1736,11 +1827,11 @@ do_config_server(http_t *http)          /* I - HTTP connection */
     if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
     {
       cgiStartHTML(cgiText(_("Edit Configuration File")));
-      cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
+      cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file")));
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
-      
+
       perror(tempfile);
       return;
     }
@@ -1748,11 +1839,11 @@ do_config_server(http_t *http)          /* I - HTTP connection */
     if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
     {
       cgiStartHTML(cgiText(_("Edit Configuration File")));
-      cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
+      cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file")));
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
-      
+
       perror(tempfile);
       close(tempfd);
       unlink(tempfile);
@@ -1770,7 +1861,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
         if ((end = strstr(start, "\n")) == NULL)
          end = start + strlen(start);
 
-      cupsFileWrite(temp, start, end - start);
+      cupsFileWrite(temp, start, (size_t)(end - start));
       cupsFilePutChar(temp, '\n');
 
       if (*end == '\r')
@@ -1798,7 +1889,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     else if (status != HTTP_CREATED)
     {
       cgiSetVariable("MESSAGE",
-                     cgiText(_("Unable to upload cupsd.conf file:")));
+                     cgiText(_("Unable to upload cupsd.conf file")));
       cgiSetVariable("ERROR", httpStatus(status));
 
       cgiStartHTML(cgiText(_("Edit Configuration File")));
@@ -1845,7 +1936,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     {
       cgiStartHTML(cgiText(_("Edit Configuration File")));
       cgiSetVariable("MESSAGE",
-                     cgiText(_("Unable to access cupsd.conf file:")));
+                     cgiText(_("Unable to access cupsd.conf file")));
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
@@ -1858,10 +1949,10 @@ do_config_server(http_t *http)          /* I - HTTP connection */
     {
       cgiStartHTML(cgiText(_("Edit Configuration File")));
       cgiSetVariable("MESSAGE",
-                     cgiText(_("Unable to access cupsd.conf file:")));
+                     cgiText(_("Unable to access cupsd.conf file")));
       cgiSetVariable("ERROR",
                      cgiText(_("Unable to edit cupsd.conf files larger than "
-                              "1MB!")));
+                              "1MB")));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
 
@@ -1882,7 +1973,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
 
       cgiStartHTML(cgiText(_("Edit Configuration File")));
       cgiSetVariable("MESSAGE",
-                     cgiText(_("Unable to access cupsd.conf file:")));
+                     cgiText(_("Unable to access cupsd.conf file")));
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
@@ -1895,9 +1986,9 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     * Allocate memory and load the file into a string buffer...
     */
 
-    if ((buffer = calloc(1, info.st_size + 1)) != NULL)
+    if ((buffer = calloc(1, (size_t)info.st_size + 1)) != NULL)
     {
-      cupsFileRead(cupsd, buffer, info.st_size);
+      cupsFileRead(cupsd, buffer, (size_t)info.st_size);
       cgiSetVariable("CUPSDCONF", buffer);
       free(buffer);
     }
@@ -1914,7 +2005,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     if (!stat(filename, &info) && info.st_size < (1024 * 1024) &&
         (cupsd = cupsFileOpen(filename, "r")) != NULL)
     {
-      if ((buffer = calloc(1, 2 * info.st_size + 1)) != NULL)
+      if ((buffer = calloc(1, 2 * (size_t)info.st_size + 1)) != NULL)
       {
        bufend = buffer + 2 * info.st_size - 1;
 
@@ -1924,7 +2015,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
          if (ch == '\\' || ch == '\"')
          {
            *bufptr++ = '\\';
-           *bufptr++ = ch;
+           *bufptr++ = (char)ch;
          }
          else if (ch == '\n')
          {
@@ -1937,7 +2028,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
            *bufptr++ = 't';
          }
          else if (ch >= ' ')
-           *bufptr++ = ch;
+           *bufptr++ = (char)ch;
        }
 
        *bufptr = '\0';
@@ -1992,7 +2083,7 @@ do_delete_class(http_t *http)             /* I - HTTP connection */
   else
   {
     cgiStartHTML(cgiText(_("Delete Class")));
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
     return;
@@ -2039,7 +2130,7 @@ do_delete_class(http_t *http)             /* I - HTTP connection */
   cgiStartHTML(cgiText(_("Delete Class")));
 
   if (cupsLastError() > IPP_OK_CONFLICT)
-    cgiShowIPPError(_("Unable to delete class:"));
+    cgiShowIPPError(_("Unable to delete class"));
   else
     cgiCopyTemplateLang("class-deleted.tmpl");
 
@@ -2077,7 +2168,7 @@ do_delete_printer(http_t *http)           /* I - HTTP connection */
   else
   {
     cgiStartHTML(cgiText(_("Delete Printer")));
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
     return;
@@ -2124,7 +2215,7 @@ do_delete_printer(http_t *http)           /* I - HTTP connection */
   cgiStartHTML(cgiText(_("Delete Printer")));
 
   if (cupsLastError() > IPP_OK_CONFLICT)
-    cgiShowIPPError(_("Unable to delete printer:"));
+    cgiShowIPPError(_("Unable to delete printer"));
   else
     cgiCopyTemplateLang("printer-deleted.tmpl");
 
@@ -2174,8 +2265,7 @@ do_export(http_t *http)                   /* I - HTTP connection */
                 "printer-type", 0);
 
   ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
-                "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
-                                    CUPS_PRINTER_IMPLICIT);
+                "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes", NULL, "printer-name");
@@ -2194,7 +2284,7 @@ do_export(http_t *http)                   /* I - HTTP connection */
         dest = cgiGetArray("PRINTER_NAME", i);
 
         for (j = 0; j < export_count; j ++)
-         if (!strcasecmp(dest, cgiGetArray("EXPORT_NAME", j)))
+         if (!_cups_strcasecmp(dest, cgiGetArray("EXPORT_NAME", j)))
             break;
 
         cgiSetArray("PRINTER_EXPORT", i, j < export_count ? "Y" : "");
@@ -2252,11 +2342,11 @@ do_export(http_t *http)                 /* I - HTTP connection */
   else if (username && !*username)
     cgiSetVariable("ERROR",
                    cgiText(_("A Samba username is required to export "
-                            "printer drivers!")));
+                            "printer drivers")));
   else if (username && (!password || !*password))
     cgiSetVariable("ERROR",
                    cgiText(_("A Samba password is required to export "
-                            "printer drivers!")));
+                            "printer drivers")));
 
  /*
   * Show form...
@@ -2318,7 +2408,7 @@ do_list_printers(http_t *http)            /* I - HTTP connection */
          attr;
         attr = ippFindNextAttribute(response, "device-uri", IPP_TAG_URI))
     {
-      cupsArrayAdd(printer_devices, strdup(attr->values[0].string.text));
+      cupsArrayAdd(printer_devices, _cupsStrAlloc(attr->values[0].string.text));
     }
 
    /*
@@ -2382,7 +2472,7 @@ do_list_printers(http_t *http)            /* I - HTTP connection */
        */
 
        if (device_info && device_make_and_model && device_uri &&
-           strcasecmp(device_make_and_model, "unknown") &&
+           _cups_strcasecmp(device_make_and_model, "unknown") &&
            strchr(device_uri, ':'))
        {
         /*
@@ -2409,7 +2499,7 @@ do_list_printers(http_t *http)            /* I - HTTP connection */
            * suitable name.
            */
 
-            if (strncasecmp(device_info, "unknown", 7))
+            if (_cups_strncasecmp(device_info, "unknown", 7))
              ptr = device_info;
             else if ((ptr = strstr(device_uri, "://")) != NULL)
              ptr += 3;
@@ -2422,7 +2512,8 @@ do_list_printers(http_t *http)            /* I - HTTP connection */
              if (isalnum(*ptr & 255) || *ptr == '_' || *ptr == '-' ||
                  *ptr == '.')
                *option_ptr++ = *ptr;
-             else if ((*ptr == ' ' || *ptr == '/') && option_ptr[-1] != '_')
+             else if ((*ptr == ' ' || *ptr == '/') && option_ptr > option &&
+                      option_ptr[-1] != '_')
                *option_ptr++ = '_';
              else if (*ptr == '?' || *ptr == '(')
                break;
@@ -2455,7 +2546,7 @@ do_list_printers(http_t *http)            /* I - HTTP connection */
       for (printer_device = (char *)cupsArrayFirst(printer_devices);
            printer_device;
           printer_device = (char *)cupsArrayNext(printer_devices))
-        free(printer_device);
+        _cupsStrFree(printer_device);
 
       cupsArrayDelete(printer_devices);
     }
@@ -2510,10 +2601,6 @@ do_menu(http_t *http)                    /* I - HTTP connection */
                            settings)) != NULL && atoi(val))
     cgiSetVariable("REMOTE_ANY", "CHECKED");
 
-  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings,
-                           settings)) != NULL && atoi(val))
-    cgiSetVariable("REMOTE_PRINTERS", "CHECKED");
-
   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
                            settings)) != NULL && atoi(val))
     cgiSetVariable("SHARE_PRINTERS", "CHECKED");
@@ -2526,81 +2613,43 @@ do_menu(http_t *http)                   /* I - HTTP connection */
   cgiSetVariable("HAVE_GSSAPI", "1");
 
   if ((val = cupsGetOption("DefaultAuthType", num_settings,
-                           settings)) != NULL && !strcasecmp(val, "Negotiate"))
+                           settings)) != NULL && !_cups_strcasecmp(val, "Negotiate"))
     cgiSetVariable("KERBEROS", "CHECKED");
+  else
 #endif /* HAVE_GSSAPI */
-
-#ifdef HAVE_DNSSD
-  cgiSetVariable("HAVE_DNSSD", "1");
-#endif /* HAVE_DNSSD */
-
-#ifdef HAVE_LDAP
-  cgiSetVariable("HAVE_LDAP", "1");
-#endif /* HAVE_LDAP */
-
-#ifdef HAVE_LIBSLP
-  cgiSetVariable("HAVE_LIBSLP", "1");
-#endif /* HAVE_LIBSLP */
-
-  if ((val = cupsGetOption("BrowseRemoteProtocols", num_settings,
-                           settings)) == NULL)
-    if ((val = cupsGetOption("BrowseProtocols", num_settings,
-                           settings)) == NULL)
-      val = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS;
-
-  if (strstr(val, "cups") || strstr(val, "CUPS"))
-    cgiSetVariable("BROWSE_REMOTE_CUPS", "CHECKED");
-
-  if (strstr(val, "ldap") || strstr(val, "LDAP"))
-    cgiSetVariable("BROWSE_REMOTE_LDAP", "CHECKED");
-
-  if (strstr(val, "slp") || strstr(val, "SLP"))
-    cgiSetVariable("BROWSE_REMOTE_SLP", "CHECKED");
-
-  if ((val = cupsGetOption("BrowseLocalProtocols", num_settings,
-                           settings)) == NULL)
-    if ((val = cupsGetOption("BrowseProtocols", num_settings,
-                           settings)) == NULL)
-      val = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
-
-  if (strstr(val, "cups") || strstr(val, "CUPS"))
-    cgiSetVariable("BROWSE_LOCAL_CUPS", "CHECKED");
-
-  if (strstr(val, "dnssd") || strstr(val, "DNSSD") ||
-      strstr(val, "dns-sd") || strstr(val, "DNS-SD") ||
-      strstr(val, "bonjour") || strstr(val, "BONJOUR"))
-    cgiSetVariable("BROWSE_LOCAL_DNSSD", "CHECKED");
-
-  if (strstr(val, "ldap") || strstr(val, "LDAP"))
-    cgiSetVariable("BROWSE_LOCAL_LDAP", "CHECKED");
-
-  if (strstr(val, "slp") || strstr(val, "SLP"))
-    cgiSetVariable("BROWSE_LOCAL_SLP", "CHECKED");
+  cgiSetVariable("KERBEROS", "");
 
   if ((val = cupsGetOption("BrowseWebIF", num_settings,
                            settings)) == NULL)
     val = "No";
 
-  if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
-      !strcasecmp(val, "true"))
+  if (!_cups_strcasecmp(val, "yes") || !_cups_strcasecmp(val, "on") ||
+      !_cups_strcasecmp(val, "true"))
     cgiSetVariable("BROWSE_WEB_IF", "CHECKED");
 
   if ((val = cupsGetOption("PreserveJobHistory", num_settings,
                            settings)) == NULL)
     val = "Yes";
 
-  if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
-      !strcasecmp(val, "true"))
+  if (val &&
+      (!_cups_strcasecmp(val, "0") || !_cups_strcasecmp(val, "no") ||
+       !_cups_strcasecmp(val, "off") || !_cups_strcasecmp(val, "false") ||
+       !_cups_strcasecmp(val, "disabled")))
+  {
+    cgiSetVariable("PRESERVE_JOB_HISTORY", "0");
+    cgiSetVariable("PRESERVE_JOB_FILES", "0");
+  }
+  else
   {
-    cgiSetVariable("PRESERVE_JOB_HISTORY", "CHECKED");
+    cgiSetVariable("PRESERVE_JOBS", "CHECKED");
+    cgiSetVariable("PRESERVE_JOB_HISTORY", val);
 
     if ((val = cupsGetOption("PreserveJobFiles", num_settings,
                             settings)) == NULL)
-      val = "No";
+      val = "1d";
+
+    cgiSetVariable("PRESERVE_JOB_FILES", val);
 
-    if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
-       !strcasecmp(val, "true"))
-      cgiSetVariable("PRESERVE_JOB_FILES", "CHECKED");
   }
 
   if ((val = cupsGetOption("MaxClients", num_settings, settings)) == NULL)
@@ -2682,18 +2731,30 @@ do_menu(http_t *http)                   /* I - HTTP connection */
 
 
 /*
- * 'do_printer_op()' - Do a printer operation.
+ * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
  */
 
 static void
-do_printer_op(http_t      *http,       /* I - HTTP connection */
-             ipp_op_t    op,           /* I - Operation to perform */
-             const char  *title)       /* I - Title of page */
+do_set_allowed_users(http_t *http)     /* I - HTTP connection */
 {
-  ipp_t                *request;               /* IPP request */
+  int          i;                      /* Looping var */
+  ipp_t                *request,               /* IPP request */
+               *response;              /* IPP response */
   char         uri[HTTP_MAX_URI];      /* Printer URI */
   const char   *printer,               /* Printer name (purge-jobs) */
-               *is_class;              /* Is a class? */
+               *is_class,              /* Is a class? */
+               *users,                 /* List of users or groups */
+               *type;                  /* Allow/deny type */
+  int          num_users;              /* Number of users */
+  char         *ptr,                   /* Pointer into users string */
+               *end,                   /* Pointer to end of users string */
+               quote;                  /* Quote character */
+  ipp_attribute_t *attr;               /* Attribute */
+  static const char * const attrs[] =  /* Requested attributes */
+               {
+                 "requesting-user-name-allowed",
+                 "requesting-user-name-denied"
+               };
 
 
   is_class = cgiGetVariable("IS_CLASS");
@@ -2701,115 +2762,8 @@ do_printer_op(http_t      *http,        /* I - HTTP connection */
 
   if (!printer)
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
-    cgiStartHTML(title);
-    cgiCopyTemplateLang("error.tmpl");
-    cgiEndHTML();
-    return;
-  }
-
- /*
-  * Build a printer request, which requires the following
-  * attributes:
-  *
-  *    attributes-charset
-  *    attributes-natural-language
-  *    printer-uri
-  */
-
-  request = ippNewRequest(op);
-
-  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                   "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
-                  printer);
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-               NULL, uri);
-
- /*
-  * Do the request and get back a response...
-  */
-
-  ippDelete(cupsDoRequest(http, request, "/admin/"));
-
-  if (cupsLastError() == IPP_NOT_AUTHORIZED)
-  {
-    puts("Status: 401\n");
-    exit(0);
-  }
-  else if (cupsLastError() > IPP_OK_CONFLICT)
-  {
-    cgiStartHTML(title);
-    cgiShowIPPError(_("Unable to change printer:"));
-  }
-  else
-  {
-   /*
-    * Redirect successful updates back to the printer page...
-    */
-
-    char       url[1024],              /* Printer/class URL */
-               refresh[1024];          /* Refresh URL */
-
-
-    cgiRewriteURL(uri, url, sizeof(url), NULL);
-    cgiFormEncode(uri, url, sizeof(uri));
-    snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
-    cgiSetVariable("refresh_page", refresh);
-
-    cgiStartHTML(title);
-
-    if (op == IPP_PAUSE_PRINTER)
-      cgiCopyTemplateLang("printer-stop.tmpl");
-    else if (op == IPP_RESUME_PRINTER)
-      cgiCopyTemplateLang("printer-start.tmpl");
-    else if (op == CUPS_ACCEPT_JOBS)
-      cgiCopyTemplateLang("printer-accept.tmpl");
-    else if (op == CUPS_REJECT_JOBS)
-      cgiCopyTemplateLang("printer-reject.tmpl");
-    else if (op == IPP_PURGE_JOBS)
-      cgiCopyTemplateLang("printer-purge.tmpl");
-    else if (op == CUPS_SET_DEFAULT)
-      cgiCopyTemplateLang("printer-default.tmpl");
-  }
-
-  cgiEndHTML();
-}
-
-
-/*
- * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
- */
-
-static void
-do_set_allowed_users(http_t *http)     /* I - HTTP connection */
-{
-  int          i;                      /* Looping var */
-  ipp_t                *request,               /* IPP request */
-               *response;              /* IPP response */
-  char         uri[HTTP_MAX_URI];      /* Printer URI */
-  const char   *printer,               /* Printer name (purge-jobs) */
-               *is_class,              /* Is a class? */
-               *users,                 /* List of users or groups */
-               *type;                  /* Allow/deny type */
-  int          num_users;              /* Number of users */
-  char         *ptr,                   /* Pointer into users string */
-               *end,                   /* Pointer to end of users string */
-               quote;                  /* Quote character */
-  ipp_attribute_t *attr;               /* Attribute */
-  static const char * const attrs[] =  /* Requested attributes */
-               {
-                 "requesting-user-name-allowed",
-                 "requesting-user-name-denied"
-               };
-
-
-  is_class = cgiGetVariable("IS_CLASS");
-  printer  = cgiGetVariable("PRINTER_NAME");
-
-  if (!printer)
-  {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
-    cgiStartHTML(cgiText(_("Set Allowed Users")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+    cgiStartHTML(cgiText(_("Set Allowed Users")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
     return;
@@ -2863,7 +2817,7 @@ do_set_allowed_users(http_t *http)        /* I - HTTP connection */
       exit(0);
     }
     else if (cupsLastError() > IPP_OK_CONFLICT)
-      cgiShowIPPError(_("Unable to get printer attributes:"));
+      cgiShowIPPError(_("Unable to get printer attributes"));
     else
       cgiCopyTemplateLang("users.tmpl");
 
@@ -2989,7 +2943,7 @@ do_set_allowed_users(http_t *http)        /* I - HTTP connection */
         * Add the name...
        */
 
-        attr->values[i].string.text = strdup(ptr);
+        attr->values[i].string.text = _cupsStrAlloc(ptr);
 
        /*
         * Advance to the next name...
@@ -3013,7 +2967,7 @@ do_set_allowed_users(http_t *http)        /* I - HTTP connection */
     else if (cupsLastError() > IPP_OK_CONFLICT)
     {
       cgiStartHTML(cgiText(_("Set Allowed Users")));
-      cgiShowIPPError(_("Unable to change printer:"));
+      cgiShowIPPError(_("Unable to change printer"));
     }
     else
     {
@@ -3042,6 +2996,89 @@ do_set_allowed_users(http_t *http)       /* I - HTTP connection */
 }
 
 
+/*
+ * 'do_set_default()' - Set the server default printer/class.
+ */
+
+static void
+do_set_default(http_t *http)           /* I - HTTP connection */
+{
+  const char   *title;                 /* Page title */
+  ipp_t                *request;               /* IPP request */
+  char         uri[HTTP_MAX_URI];      /* Printer URI */
+  const char   *printer,               /* Printer name (purge-jobs) */
+               *is_class;              /* Is a class? */
+
+
+  is_class = cgiGetVariable("IS_CLASS");
+  printer  = cgiGetVariable("PRINTER_NAME");
+  title    = cgiText(_("Set As Server Default"));
+
+  if (!printer)
+  {
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+    cgiStartHTML(title);
+    cgiCopyTemplateLang("error.tmpl");
+    cgiEndHTML();
+    return;
+  }
+
+ /*
+  * Build a printer request, which requires the following
+  * attributes:
+  *
+  *    attributes-charset
+  *    attributes-natural-language
+  *    printer-uri
+  */
+
+  request = ippNewRequest(CUPS_SET_DEFAULT);
+
+  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                   "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+                  printer);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, uri);
+
+ /*
+  * Do the request and get back a response...
+  */
+
+  ippDelete(cupsDoRequest(http, request, "/admin/"));
+
+  if (cupsLastError() == IPP_NOT_AUTHORIZED)
+  {
+    puts("Status: 401\n");
+    exit(0);
+  }
+  else if (cupsLastError() > IPP_OK_CONFLICT)
+  {
+    cgiStartHTML(title);
+    cgiShowIPPError(_("Unable to set server default"));
+  }
+  else
+  {
+   /*
+    * Redirect successful updates back to the printer page...
+    */
+
+    char       url[1024],              /* Printer/class URL */
+               refresh[1024];          /* Refresh URL */
+
+
+    cgiRewriteURL(uri, url, sizeof(url), NULL);
+    cgiFormEncode(uri, url, sizeof(uri));
+    snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
+    cgiSetVariable("refresh_page", refresh);
+
+    cgiStartHTML(title);
+    cgiCopyTemplateLang("printer-default.tmpl");
+  }
+
+  cgiEndHTML();
+}
+
+
 /*
  * 'do_set_options()' - Configure the default options for a queue.
  */
@@ -3090,7 +3127,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
                     printer);
   else
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(title);
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3106,57 +3143,7 @@ do_set_options(http_t *http,             /* I - HTTP connection */
 
   if (cgiGetVariable("AUTOCONFIGURE"))
   {
-    int                        job_id;         /* Command file job */
-    char               refresh[1024];  /* Refresh URL */
-    http_status_t      status;         /* Document status */
-    static const char  *autoconfigure =/* Command file */
-                       "#CUPS-COMMAND\n"
-                       "AutoConfigure\n";
-
-
-    if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, "Auto-Configure",
-                                0, NULL)) < 1)
-    {
-      cgiSetVariable("ERROR", cgiText(_("Unable to send auto-configure command "
-                                        "to printer driver!")));
-      cgiStartHTML(title);
-      cgiCopyTemplateLang("error.tmpl");
-      cgiEndHTML();
-      return;
-    }
-
-    status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id,
-                               "AutoConfigure.command", CUPS_FORMAT_COMMAND, 1);
-    if (status == HTTP_CONTINUE)
-      status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, autoconfigure,
-                                    strlen(autoconfigure));
-    if (status == HTTP_CONTINUE)
-      cupsFinishDocument(CUPS_HTTP_DEFAULT, printer);
-
-    if (cupsLastError() >= IPP_REDIRECTION_OTHER_SITE)
-    {
-      cgiSetVariable("ERROR", cupsLastErrorString());
-      cgiStartHTML(title);
-      cgiCopyTemplateLang("error.tmpl");
-      cgiEndHTML();
-
-      cupsCancelJob(printer, job_id);
-      return;
-    }
-
-   /*
-    * Redirect successful updates back to the printer page...
-    */
-
-    cgiFormEncode(uri, printer, sizeof(uri));
-    snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/%s/%s",
-            is_class ? "classes" : "printers", uri);
-    cgiSetVariable("refresh_page", refresh);
-
-    cgiStartHTML(title);
-
-    cgiCopyTemplateLang("printer-configured.tmpl");
-    cgiEndHTML();
+    cgiPrintCommand(http, printer, "AutoConfigure", "Set Default Options");
     return;
   }
 
@@ -3176,7 +3163,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
     if ((ppd = ppdOpenFile(filename)) == NULL)
     {
       cgiSetVariable("ERROR", ppdErrorString(ppdLastError(&i)));
-      cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file:")));
+      cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file")));
       cgiStartHTML(title);
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
@@ -3202,11 +3189,16 @@ do_set_options(http_t *http,            /* I - HTTP connection */
     for (option = ppdFirstOption(ppd);
          option;
         option = ppdNextOption(ppd))
+    {
       if ((var = cgiGetVariable(option->keyword)) != NULL)
       {
        have_options = 1;
        ppdMarkOption(ppd, option->keyword, var);
+       fprintf(stderr, "DEBUG: Set %s to %s...\n", option->keyword, var);
       }
+      else
+        fprintf(stderr, "DEBUG: Didn't find %s...\n", option->keyword);
+    }
   }
 
   if (!have_options || ppdConflicts(ppd))
@@ -3217,13 +3209,17 @@ do_set_options(http_t *http,            /* I - HTTP connection */
 
     fputs("DEBUG: Showing options...\n", stderr);
 
+   /*
+    * Show auto-configure button if supported...
+    */
+
     if (ppd)
     {
       if (ppd->num_filters == 0 ||
           ((ppdattr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL &&
            ppdattr->value && strstr(ppdattr->value, "AutoConfigure")))
         cgiSetVariable("HAVE_AUTOCONFIGURE", "YES");
-      else 
+      else
       {
         for (i = 0; i < ppd->num_filters; i ++)
          if (!strncmp(ppd->filters[i], "application/vnd.cups-postscript", 31))
@@ -3234,6 +3230,62 @@ do_set_options(http_t *http,             /* I - HTTP connection */
       }
     }
 
+   /*
+    * Get the printer attributes...
+    */
+
+    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+
+    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                     "localhost", 0, "/printers/%s", printer);
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+                 NULL, uri);
+
+    response = cupsDoRequest(http, request, "/");
+
+   /*
+    * List the groups used as "tabs"...
+    */
+
+    i = 0;
+
+    if (ppd)
+    {
+      for (group = ppd->groups;
+          i < ppd->num_groups;
+          i ++, group ++)
+      {
+        cgiSetArray("GROUP_ID", i, group->name);
+
+       if (!strcmp(group->name, "InstallableOptions"))
+         cgiSetArray("GROUP", i, cgiText(_("Options Installed")));
+       else
+         cgiSetArray("GROUP", i, group->text);
+      }
+    }
+
+    if (ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO))
+    {
+      cgiSetArray("GROUP_ID", i, "CUPS_BANNERS");
+      cgiSetArray("GROUP", i ++, cgiText(_("Banners")));
+    }
+
+    if (ippFindAttribute(response, "printer-error-policy-supported",
+                        IPP_TAG_ZERO) ||
+       ippFindAttribute(response, "printer-op-policy-supported",
+                        IPP_TAG_ZERO))
+    {
+      cgiSetArray("GROUP_ID", i, "CUPS_POLICIES");
+      cgiSetArray("GROUP", i ++, cgiText(_("Policies")));
+    }
+
+    if ((attr = ippFindAttribute(response, "port-monitor-supported",
+                                 IPP_TAG_NAME)) != NULL && attr->num_values > 1)
+    {
+      cgiSetArray("GROUP_ID", i, "CUPS_PORT_MONITOR");
+      cgiSetArray("GROUP", i, cgiText(_("Port Monitor")));
+    }
+
     cgiStartHTML(cgiText(_("Set Printer Options")));
     cgiCopyTemplateLang("set-printer-options-header.tmpl");
 
@@ -3253,6 +3305,16 @@ do_set_options(http_t *http,             /* I - HTTP connection */
            {
              cgiSetArray("ckeyword", k, option->keyword);
              cgiSetArray("ckeytext", k, option->text);
+
+             for (m = 0; m < option->num_choices; m ++)
+             {
+               if (option->choices[m].marked)
+               {
+                 cgiSetArray("cchoice", k, option->choices[m].text);
+                 break;
+               }
+              }
+
              k ++;
            }
 
@@ -3263,18 +3325,34 @@ do_set_options(http_t *http,            /* I - HTTP connection */
           i > 0;
           i --, group ++)
       {
+       for (j = group->num_options, option = group->options;
+            j > 0;
+            j --, option ++)
+       {
+         if (!strcmp(option->keyword, "PageRegion"))
+           continue;
+
+         if (option->num_choices > 1)
+           break;
+       }
+
+        if (j == 0)
+         continue;
+
+        cgiSetVariable("GROUP_ID", group->name);
+
        if (!strcmp(group->name, "InstallableOptions"))
          cgiSetVariable("GROUP", cgiText(_("Options Installed")));
        else
          cgiSetVariable("GROUP", group->text);
 
        cgiCopyTemplateLang("option-header.tmpl");
-       
+
        for (j = group->num_options, option = group->options;
             j > 0;
             j --, option ++)
        {
-         if (!strcmp(option->keyword, "PageRegion"))
+         if (!strcmp(option->keyword, "PageRegion") || option->num_choices < 2)
            continue;
 
          cgiSetVariable("KEYWORD", option->keyword);
@@ -3307,16 +3385,15 @@ do_set_options(http_t *http,            /* I - HTTP connection */
          {
             const char *units = NULL;  /* Units value, if any */
 
-
            cgiSetVariable("ISCUSTOM", "1");
 
            for (cparam = ppdFirstCustomParam(coption), m = 0;
                 cparam;
                 cparam = ppdNextCustomParam(coption), m ++)
            {
-             if (!strcasecmp(option->keyword, "PageSize") &&
-                 strcasecmp(cparam->name, "Width") &&
-                 strcasecmp(cparam->name, "Height"))
+             if (!_cups_strcasecmp(option->keyword, "PageSize") &&
+                 _cups_strcasecmp(cparam->name, "Width") &&
+                 _cups_strcasecmp(cparam->name, "Height"))
               {
                m --;
                continue;
@@ -3329,7 +3406,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
              switch (cparam->type)
              {
                case PPD_CUSTOM_POINTS :
-                   if (!strncasecmp(option->defchoice, "Custom.", 7))
+                   if (!_cups_strncasecmp(option->defchoice, "Custom.", 7))
                    {
                      units = option->defchoice + strlen(option->defchoice) - 2;
 
@@ -3428,38 +3505,70 @@ do_set_options(http_t *http,            /* I - HTTP connection */
       }
     }
 
-   /*
-    * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
-    * following attributes:
-    *
-    *    attributes-charset
-    *    attributes-natural-language
-    *    printer-uri
-    */
+    if ((attr = ippFindAttribute(response, "job-sheets-supported",
+                                IPP_TAG_ZERO)) != NULL)
+    {
+     /*
+      * Add the job sheets options...
+      */
 
-    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+      cgiSetVariable("GROUP_ID", "CUPS_BANNERS");
+      cgiSetVariable("GROUP", cgiText(_("Banners")));
+      cgiCopyTemplateLang("option-header.tmpl");
 
-    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                     "localhost", 0, "/printers/%s", printer);
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-                 NULL, uri);
+      cgiSetSize("CHOICES", attr->num_values);
+      cgiSetSize("TEXT", attr->num_values);
+      for (k = 0; k < attr->num_values; k ++)
+      {
+       cgiSetArray("CHOICES", k, attr->values[k].string.text);
+       cgiSetArray("TEXT", k, attr->values[k].string.text);
+      }
 
-   /*
-    * Do the request and get back a response...
-    */
+      attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
 
-    if ((response = cupsDoRequest(http, request, "/")) != NULL)
+      cgiSetVariable("KEYWORD", "job_sheets_start");
+      cgiSetVariable("KEYTEXT",
+                     /* TRANSLATORS: Banner/cover sheet before the print job. */
+                     cgiText(_("Starting Banner")));
+      cgiSetVariable("DEFCHOICE", attr != NULL ?
+                                 attr->values[0].string.text : "");
+
+      cgiCopyTemplateLang("option-pickone.tmpl");
+
+      cgiSetVariable("KEYWORD", "job_sheets_end");
+      cgiSetVariable("KEYTEXT",
+                     /* TRANSLATORS: Banner/cover sheet after the print job. */
+                     cgiText(_("Ending Banner")));
+      cgiSetVariable("DEFCHOICE", attr != NULL && attr->num_values > 1 ?
+                                 attr->values[1].string.text : "");
+
+      cgiCopyTemplateLang("option-pickone.tmpl");
+
+      cgiCopyTemplateLang("option-trailer.tmpl");
+    }
+
+    if (ippFindAttribute(response, "printer-error-policy-supported",
+                        IPP_TAG_ZERO) ||
+       ippFindAttribute(response, "printer-op-policy-supported",
+                        IPP_TAG_ZERO))
     {
-      if ((attr = ippFindAttribute(response, "job-sheets-supported",
-                                   IPP_TAG_ZERO)) != NULL)
-      {
-       /*
-       * Add the job sheets options...
-       */
+     /*
+      * Add the error and operation policy options...
+      */
 
-       cgiSetVariable("GROUP", cgiText(_("Banners")));
-       cgiCopyTemplateLang("option-header.tmpl");
+      cgiSetVariable("GROUP_ID", "CUPS_POLICIES");
+      cgiSetVariable("GROUP", cgiText(_("Policies")));
+      cgiCopyTemplateLang("option-header.tmpl");
+
+     /*
+      * Error policy...
+      */
+
+      attr = ippFindAttribute(response, "printer-error-policy-supported",
+                             IPP_TAG_ZERO);
 
+      if (attr)
+      {
        cgiSetSize("CHOICES", attr->num_values);
        cgiSetSize("TEXT", attr->num_values);
        for (k = 0; k < attr->num_values; k ++)
@@ -3468,136 +3577,80 @@ do_set_options(http_t *http,           /* I - HTTP connection */
          cgiSetArray("TEXT", k, attr->values[k].string.text);
        }
 
-        attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
-
-        cgiSetVariable("KEYWORD", "job_sheets_start");
-       cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner")));
-        cgiSetVariable("DEFCHOICE", attr != NULL ?
-                                   attr->values[0].string.text : "");
-
-       cgiCopyTemplateLang("option-pickone.tmpl");
-
-        cgiSetVariable("KEYWORD", "job_sheets_end");
-       cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner")));
-        cgiSetVariable("DEFCHOICE", attr != NULL && attr->num_values > 1 ?
-                                   attr->values[1].string.text : "");
-
-       cgiCopyTemplateLang("option-pickone.tmpl");
+       attr = ippFindAttribute(response, "printer-error-policy",
+                               IPP_TAG_ZERO);
 
-       cgiCopyTemplateLang("option-trailer.tmpl");
+       cgiSetVariable("KEYWORD", "printer_error_policy");
+       cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
+       cgiSetVariable("DEFCHOICE", attr == NULL ?
+                                   "" : attr->values[0].string.text);
       }
 
-      if (ippFindAttribute(response, "printer-error-policy-supported",
-                           IPP_TAG_ZERO) ||
-          ippFindAttribute(response, "printer-op-policy-supported",
-                          IPP_TAG_ZERO))
-      {
-       /*
-       * Add the error and operation policy options...
-       */
-
-       cgiSetVariable("GROUP", cgiText(_("Policies")));
-       cgiCopyTemplateLang("option-header.tmpl");
+      cgiCopyTemplateLang("option-pickone.tmpl");
 
-       /*
-        * Error policy...
-       */
+     /*
+      * Operation policy...
+      */
 
-        attr = ippFindAttribute(response, "printer-error-policy-supported",
-                               IPP_TAG_ZERO);
+      attr = ippFindAttribute(response, "printer-op-policy-supported",
+                             IPP_TAG_ZERO);
 
-        if (attr)
+      if (attr)
+      {
+       cgiSetSize("CHOICES", attr->num_values);
+       cgiSetSize("TEXT", attr->num_values);
+       for (k = 0; k < attr->num_values; k ++)
        {
-         cgiSetSize("CHOICES", attr->num_values);
-         cgiSetSize("TEXT", attr->num_values);
-         for (k = 0; k < attr->num_values; k ++)
-         {
-           cgiSetArray("CHOICES", k, attr->values[k].string.text);
-           cgiSetArray("TEXT", k, attr->values[k].string.text);
-         }
+         cgiSetArray("CHOICES", k, attr->values[k].string.text);
+         cgiSetArray("TEXT", k, attr->values[k].string.text);
+       }
 
-          attr = ippFindAttribute(response, "printer-error-policy",
-                                 IPP_TAG_ZERO);
+       attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
 
-          cgiSetVariable("KEYWORD", "printer_error_policy");
-         cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
-          cgiSetVariable("DEFCHOICE", attr == NULL ?
-                                     "" : attr->values[0].string.text);
-        }
+       cgiSetVariable("KEYWORD", "printer_op_policy");
+       cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
+       cgiSetVariable("DEFCHOICE", attr == NULL ?
+                                   "" : attr->values[0].string.text);
 
        cgiCopyTemplateLang("option-pickone.tmpl");
-
-       /*
-        * Operation policy...
-       */
-
-        attr = ippFindAttribute(response, "printer-op-policy-supported",
-                               IPP_TAG_ZERO);
-
-        if (attr)
-       {
-         cgiSetSize("CHOICES", attr->num_values);
-         cgiSetSize("TEXT", attr->num_values);
-         for (k = 0; k < attr->num_values; k ++)
-         {
-           cgiSetArray("CHOICES", k, attr->values[k].string.text);
-           cgiSetArray("TEXT", k, attr->values[k].string.text);
-         }
-
-          attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
-
-          cgiSetVariable("KEYWORD", "printer_op_policy");
-         cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
-          cgiSetVariable("DEFCHOICE", attr == NULL ?
-                                     "" : attr->values[0].string.text);
-
-         cgiCopyTemplateLang("option-pickone.tmpl");
-        }
-
-       cgiCopyTemplateLang("option-trailer.tmpl");
       }
 
-      ippDelete(response);
+      cgiCopyTemplateLang("option-trailer.tmpl");
     }
 
    /*
     * Binary protocol support...
     */
 
-    if (ppd && ppd->protocols && strstr(ppd->protocols, "BCP"))
+    if ((attr = ippFindAttribute(response, "port-monitor-supported",
+                                 IPP_TAG_NAME)) != NULL && attr->num_values > 1)
     {
-      ppdattr = ppdFindAttr(ppd, "cupsProtocol", NULL);
-
-      cgiSetVariable("GROUP", cgiText(_("PS Binary Protocol")));
-      cgiCopyTemplateLang("option-header.tmpl");
+      cgiSetVariable("GROUP_ID", "CUPS_PORT_MONITOR");
+      cgiSetVariable("GROUP", cgiText(_("Port Monitor")));
 
-      cgiSetSize("CHOICES", 2);
-      cgiSetSize("TEXT", 2);
-      cgiSetArray("CHOICES", 0, "None");
-      cgiSetArray("TEXT", 0, cgiText(_("None")));
+      cgiSetSize("CHOICES", attr->num_values);
+      cgiSetSize("TEXT", attr->num_values);
 
-      if (strstr(ppd->protocols, "TBCP"))
+      for (i = 0; i < attr->num_values; i ++)
       {
-       cgiSetArray("CHOICES", 1, "TBCP");
-       cgiSetArray("TEXT", 1, "TBCP");
-      }
-      else
-      {
-       cgiSetArray("CHOICES", 1, "BCP");
-       cgiSetArray("TEXT", 1, "BCP");
+        cgiSetArray("CHOICES", i, attr->values[i].string.text);
+        cgiSetArray("TEXT", i, attr->values[i].string.text);
       }
 
-      cgiSetVariable("KEYWORD", "protocol");
-      cgiSetVariable("KEYTEXT", cgiText(_("PS Binary Protocol")));
-      cgiSetVariable("DEFCHOICE", ppdattr ? ppdattr->value : "None");
+      attr = ippFindAttribute(response, "port-monitor", IPP_TAG_NAME);
+      cgiSetVariable("KEYWORD", "port_monitor");
+      cgiSetVariable("KEYTEXT", cgiText(_("Port Monitor")));
+      cgiSetVariable("DEFCHOICE", attr ? attr->values[0].string.text : "none");
 
+      cgiCopyTemplateLang("option-header.tmpl");
       cgiCopyTemplateLang("option-pickone.tmpl");
-
       cgiCopyTemplateLang("option-trailer.tmpl");
     }
 
     cgiCopyTemplateLang("set-printer-options-trailer.tmpl");
     cgiEndHTML();
+
+    ippDelete(response);
   }
   else
   {
@@ -3634,7 +3687,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
 
       while (cupsFileGets(in, line, sizeof(line)))
       {
-       if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol"))
+       if (!strncmp(line, "*cupsProtocol:", 14))
          continue;
        else if (strncmp(line, "*Default", 8))
          cupsFilePrintf(out, "%s\n", line);
@@ -3666,13 +3719,6 @@ do_set_options(http_t *http,             /* I - HTTP connection */
        }
       }
 
-     /*
-      * TODO: We need to set the port-monitor attribute!
-      */
-
-      if ((var = cgiGetVariable("protocol")) != NULL)
-       cupsFilePrintf(out, "*cupsProtocol: %s\n", var);
-
       cupsFileClose(in);
       cupsFileClose(out);
     }
@@ -3717,6 +3763,10 @@ do_set_options(http_t *http,             /* I - HTTP connection */
       ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
                   "printer-op-policy", NULL, var);
 
+    if ((var = cgiGetVariable("port_monitor")) != NULL)
+      ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+                  "port-monitor", NULL, var);
+
    /*
     * Do the request and get back a response...
     */
@@ -3734,7 +3784,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
     else if (cupsLastError() > IPP_OK_CONFLICT)
     {
       cgiStartHTML(title);
-      cgiShowIPPError(_("Unable to set options:"));
+      cgiShowIPPError(_("Unable to set options"));
     }
     else
     {
@@ -3787,7 +3837,7 @@ do_set_sharing(http_t *http)              /* I - HTTP connection */
 
   if (!printer || !shared)
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(cgiText(_("Set Publishing")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3812,7 +3862,7 @@ do_set_sharing(http_t *http)              /* I - HTTP connection */
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                NULL, uri);
 
-  ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", atoi(shared));
+  ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", (char)atoi(shared));
 
  /*
   * Do the request and get back a response...
@@ -3833,7 +3883,7 @@ do_set_sharing(http_t *http)              /* I - HTTP connection */
   else if (cupsLastError() > IPP_OK_CONFLICT)
   {
     cgiStartHTML(cgiText(_("Set Publishing")));
-    cgiShowIPPError(_("Unable to change printer-is-shared attribute:"));
+    cgiShowIPPError(_("Unable to change printer-is-shared attribute"));
   }
   else
   {
@@ -3896,7 +3946,7 @@ get_option_value(
 
     return (NULL);
   }
-  else if (strcasecmp(val, "Custom") ||
+  else if (_cups_strcasecmp(val, "Custom") ||
            (coption = ppdFindCustomOption(ppd, name)) == NULL)
   {
    /*
@@ -3944,7 +3994,7 @@ get_option_value(
 
     snprintf(buffer, bufsize, "Custom.%gx%g%s", width, length, uval);
   }
-  else if (cupsArrayCount(coption->params) == 1) 
+  else if (cupsArrayCount(coption->params) == 1)
   {
     cparam = ppdFirstCustomParam(coption);
     snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword, cparam->name);
@@ -4026,7 +4076,7 @@ get_option_value(
       if ((val = cgiGetVariable(keyword)) == NULL)
        return (NULL);
 
-      snprintf(bufptr, bufend - bufptr, "%s%s=", prefix, cparam->name);
+      snprintf(bufptr, (size_t)(bufend - bufptr), "%s%s=", prefix, cparam->name);
       bufptr += strlen(bufptr);
       prefix = " ";
 
@@ -4040,7 +4090,7 @@ get_option_value(
                number > cparam->maximum.custom_real)
              return (NULL);
 
-           snprintf(bufptr, bufend - bufptr, "%g", number);
+           snprintf(bufptr, (size_t)(bufend - bufptr), "%g", number);
            break;
 
        case PPD_CUSTOM_INT :
@@ -4050,7 +4100,7 @@ get_option_value(
                integer > cparam->maximum.custom_int)
              return (NULL);
 
-           snprintf(bufptr, bufend - bufptr, "%ld", integer);
+           snprintf(bufptr, (size_t)(bufend - bufptr), "%ld", integer);
            break;
 
        case PPD_CUSTOM_POINTS :
@@ -4068,7 +4118,7 @@ get_option_value(
                number_points > cparam->maximum.custom_points)
              return (NULL);
 
-           snprintf(bufptr, bufend - bufptr, "%g%s", number, uval);
+           snprintf(bufptr, (size_t)(bufend - bufptr), "%g%s", number, uval);
            break;
 
        case PPD_CUSTOM_PASSCODE :
@@ -4117,7 +4167,7 @@ get_option_value(
     if (bufptr == buffer || (bufend - bufptr) < 2)
       return (NULL);
 
-    strcpy(bufptr, "}");
+    memcpy(bufptr, "}", 2);
   }
 
   return (buffer);
@@ -4148,54 +4198,5 @@ get_points(double     number,            /* I - Original number */
 
 
 /*
- * 'match_string()' - Return the number of matching characters.
- */
-
-static int                             /* O - Number of matching characters */
-match_string(const char *a,            /* I - First string */
-             const char *b)            /* I - Second string */
-{
-  int  count;                          /* Number of matching characters */
-
-
- /*
-  * Loop through both strings until we hit the end of either or we find
-  * a non-matching character.  For the purposes of comparison, we ignore
-  * whitespace and do a case-insensitive comparison so that we have a
-  * better chance of finding a match...
-  */
-
-  for (count = 0; *a && *b; a++, b++, count ++)
-  {
-   /*
-    * Skip leading whitespace characters...
-    */
-
-    while (isspace(*a & 255))
-      a ++;
-
-    while (isspace(*b & 255))
-      b ++;
-
-   /*
-    * Break out if we run out of characters...
-    */
-
-    if (!*a || !*b)
-      break;
-
-   /*
-    * Do a case-insensitive comparison of the next two chars...
-    */
-
-    if (tolower(*a & 255) != tolower(*b & 255))
-      break;
-  }
-
-  return (count);
-}
-
-    
-/*
- * End of "$Id: admin.c 7888 2008-08-29 21:16:56Z mike $".
+ * End of "$Id$".
  */