]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/adminutil.c
Merge changes from CUPS 1.4svn-r8606.
[thirdparty/cups.git] / cups / adminutil.c
index 8b96fcb6c1de0bcf61911f5222684d7c3cfef868..e2c5ea827dbe49154805a3e5ea9003c194157386 100644 (file)
@@ -1,29 +1,17 @@
 /*
- * "$Id: adminutil.c 6270 2007-02-12 14:27:47Z mike $"
+ * "$Id: adminutil.c 7850 2008-08-20 00:07:25Z mike $"
  *
  *   Administration utility API definitions for the Common UNIX Printing
  *   System (CUPS).
  *
- *   MANY OF THE FUNCTIONS IN THIS HEADER ARE PRIVATE AND SUBJECT TO
- *   CHANGE AT ANY TIME.  USE AT YOUR OWN RISK.
- *
+ *   Copyright 2007-2009 by Apple Inc.
  *   Copyright 2001-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   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/".
  *
  *   This file is subject to the Apple OS-Developed Software exception.
  *
  *
  *   cupsAdminCreateWindowsPPD()   - Create the Windows PPD file for a printer.
  *   cupsAdminExportSamba()        - Export a printer to Samba.
- *   _cupsAdminGetServerSettings() - Get settings from the server.
- *   _cupsAdminSetServerSettings() - Set settings on the server.
+ *   cupsAdminGetServerSettings()  - Get settings from the server.
+ *   _cupsAdminGetServerSettings() - Get settings from the server (private).
+ *   cupsAdminSetServerSettings()  - Set settings on the server.
+ *   _cupsAdminSetServerSettings() - Set settings on the server (private).
  *   do_samba_command()            - Do a SAMBA command.
  *   get_cupsd_conf()              - Get the current cupsd.conf file.
  *   invalidate_cupsd_cache()      - Invalidate the cached cupsd.conf settings.
  * Local functions...
  */
 
+extern int             _cupsAdminGetServerSettings(http_t *http,
+                                                   int *num_settings,
+                                                   cups_option_t **settings);
+extern int             _cupsAdminSetServerSettings(http_t *http,
+                                                   int num_settings,
+                                                   cups_option_t *settings);
 static int             do_samba_command(const char *command,
                                         const char *address,
                                         const char *subcommand,
@@ -79,11 +75,13 @@ static void         write_option(cups_file_t *dstfp, int order,
 
 /*
  * 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
  */
 
 char *                                 /* O - PPD file or NULL */
 cupsAdminCreateWindowsPPD(
-    http_t     *http,                  /* I - Connection to server */
+    http_t     *http,                  /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
     const char *dest,                  /* I - Printer or class */
     char       *buffer,                        /* I - Filename buffer */
     int        bufsize)                        /* I - Size of filename buffer */
@@ -103,6 +101,7 @@ cupsAdminCreateWindowsPPD(
                        option[41],     /* Option */
                        choice[41];     /* Choice */
   int                  jcloption,      /* In a JCL option? */
+                       jclorder,       /* Next JCL order dependency */
                        linenum;        /* Current line number */
   time_t               curtime;        /* Current time */
   struct tm            *curdate;       /* Current date */
@@ -124,6 +123,9 @@ cupsAdminCreateWindowsPPD(
   if (buffer)
     *buffer = '\0';
 
+  if (!http)
+    http = _cupsConnect();
+
   if (!http || !dest || !buffer || bufsize < 2)
     return (NULL);
 
@@ -200,6 +202,7 @@ cupsAdminCreateWindowsPPD(
   */
 
   jcloption = 0;
+  jclorder  = 0;
   linenum   = 0;
   language  = cupsLangDefault();
 
@@ -238,17 +241,30 @@ cupsAdminCreateWindowsPPD(
       jcloption = 0;
       cupsFilePrintf(dstfp, "%s\n", line);
     }
+    else if (jcloption && !strncmp(line, "*OrderDependency:", 17))
+    {
+      for (ptr = line + 17; *ptr && isspace(*ptr & 255); ptr ++);
+
+      ptr = strchr(ptr, ' ');
+
+      if (ptr)
+      {
+       cupsFilePrintf(dstfp, "*OrderDependency: %d%s\n", jclorder, ptr);
+       jclorder ++;
+      }
+      else
+        cupsFilePrintf(dstfp, "%s\n", line);
+    }
     else if (jcloption &&
              strncmp(line, "*End", 4) &&
-             strncmp(line, "*Default", 8) &&
-             strncmp(line, "*OrderDependency", 16))
+             strncmp(line, "*Default", 8))
     {
       if ((ptr = strchr(line, ':')) == NULL)
       {
         snprintf(line, sizeof(line),
-                 _cupsLangString(language, _("Missing value on line %d!")),
-                 linenum);
-        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+                _cupsLangString(language, _("Missing value on line %d!")),
+                linenum);
+        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
 
         cupsFileClose(srcfp);
         cupsFileClose(dstfp);
@@ -267,7 +283,7 @@ cupsAdminCreateWindowsPPD(
                 _cupsLangString(language,
                                 _("Missing double quote on line %d!")),
                 linenum);
-        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
 
         cupsFileClose(srcfp);
         cupsFileClose(dstfp);
@@ -280,13 +296,13 @@ cupsAdminCreateWindowsPPD(
        return (NULL);
       }
 
-      if (sscanf(line, "*%40s%*[ \t]%40[^/]", option, choice) != 2)
+      if (sscanf(line, "*%40s%*[ \t]%40[^:/]", option, choice) != 2)
       {
         snprintf(line, sizeof(line),
                 _cupsLangString(language,
                                 _("Bad option + choice on line %d!")),
                 linenum);
-        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+        _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line, 0);
 
         cupsFileClose(srcfp);
         cupsFileClose(dstfp);
@@ -329,10 +345,7 @@ cupsAdminCreateWindowsPPD(
 
   if (linenum == 0)
   {
-    snprintf(line, sizeof(line),
-             _cupsLangString(language, _("Empty PPD file!")),
-             linenum);
-    _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, line);
+    _cupsSetError(IPP_DOCUMENT_FORMAT_ERROR, _("Empty PPD file!"), 1);
 
     cupsFileClose(dstfp);
     unlink(buffer);
@@ -358,24 +371,24 @@ cupsAdminCreateWindowsPPD(
                                   IPP_TAG_ZERO)) != NULL &&
       (suppattr = ippFindAttribute(response, "job-hold-until-supported",
                                    IPP_TAG_ZERO)) != NULL)
-    write_option(dstfp, 10, "cupsJobHoldUntil", "Hold Until", "job-hold-until",
-                 suppattr, defattr, 0, 1);
+    write_option(dstfp, jclorder ++, "cupsJobHoldUntil", "Hold Until",
+                 "job-hold-until", suppattr, defattr, 0, 1);
 
   if ((defattr = ippFindAttribute(response, "job-priority-default",
                                   IPP_TAG_INTEGER)) != NULL &&
       (suppattr = ippFindAttribute(response, "job-priority-supported",
                                    IPP_TAG_RANGE)) != NULL)
-    write_option(dstfp, 11, "cupsJobPriority", "Priority", "job-priority",
-                 suppattr, defattr, 0, 1);
+    write_option(dstfp, jclorder ++, "cupsJobPriority", "Priority",
+                 "job-priority", suppattr, defattr, 0, 1);
 
   if ((defattr = ippFindAttribute(response, "job-sheets-default",
                                   IPP_TAG_ZERO)) != NULL &&
       (suppattr = ippFindAttribute(response, "job-sheets-supported",
                                    IPP_TAG_ZERO)) != NULL)
   {
-    write_option(dstfp, 20, "cupsJobSheetsStart", "Start Banner",
+    write_option(dstfp, jclorder ++, "cupsJobSheetsStart", "Start Banner",
                  "job-sheets", suppattr, defattr, 0, 2);
-    write_option(dstfp, 21, "cupsJobSheetsEnd", "End Banner",
+    write_option(dstfp, jclorder, "cupsJobSheetsEnd", "End Banner",
                  "job-sheets", suppattr, defattr, 1, 2);
   }
 
@@ -390,6 +403,8 @@ cupsAdminCreateWindowsPPD(
 
 /*
  * 'cupsAdminExportSamba()' - Export a printer to Samba.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
  */
 
 int                                    /* O - 1 on success, 0 on failure */
@@ -420,7 +435,7 @@ cupsAdminExportSamba(
 
   if (!dest || !ppd || !samba_server || !samba_user || !samba_password)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
     return (0);
   }
 
@@ -430,7 +445,7 @@ cupsAdminExportSamba(
 
   if ((fp = cupsTempFile2(authfile, sizeof(authfile))) == NULL)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+    _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
     return (0);
   }
 
@@ -483,7 +498,7 @@ cupsAdminExportSamba(
                               _("Unable to copy Windows 2000 printer "
                                 "driver files (%d)!")), status);
 
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
       if (logfile)
        _cupsLangPrintf(logfile, "%s\n", message);
@@ -518,7 +533,7 @@ cupsAdminExportSamba(
                                 _("Unable to copy CUPS printer driver "
                                   "files (%d)!")), status);
 
-       _cupsSetError(IPP_INTERNAL_ERROR, message);
+       _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
        if (logfile)
          _cupsLangPrintf(logfile, "%s\n", message);
@@ -561,7 +576,7 @@ cupsAdminExportSamba(
                               _("Unable to install Windows 2000 printer "
                                 "driver files (%d)!")), status);
 
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
       if (logfile)
        _cupsLangPrintf(logfile, "%s\n", message);
@@ -572,6 +587,10 @@ cupsAdminExportSamba(
     }
   }
 
+ /*
+  * See if we have the Win9x PS driver...
+  */
+
   snprintf(file, sizeof(file), "%s/drivers/ADOBEPS4.DRV", cg->cups_datadir);
   if (!access(file, 0))
   {
@@ -602,7 +621,7 @@ cupsAdminExportSamba(
                               _("Unable to copy Windows 9x printer "
                                 "driver files (%d)!")), status);
 
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
       if (logfile)
        _cupsLangPrintf(logfile, "%s\n", message);
@@ -631,7 +650,137 @@ cupsAdminExportSamba(
                               _("Unable to install Windows 9x printer "
                                 "driver files (%d)!")), status);
 
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
+
+      if (logfile)
+       _cupsLangPrintf(logfile, "%s\n", message);
+
+      unlink(authfile);
+
+      return (0);
+    }
+  }
+
+ /*
+  * See if we have the 64-bit Windows PS driver...
+  *
+  * Files:
+  *
+  *     x64/ps5ui.dll
+  *     x64/pscript.hlp
+  *     x64/pscript.ntf
+  *     x64/pscript5.dll
+  */
+
+  snprintf(file, sizeof(file), "%s/drivers/x64/pscript5.dll", cg->cups_datadir);
+  if (!access(file, 0))
+  {
+    have_drivers |= 4;
+
+   /*
+    * 64-bit Windows driver is installed; do the smbclient commands needed
+    * to copy the Win64 drivers over...
+    */
+
+    snprintf(address, sizeof(address), "//%s/print$", samba_server);
+
+    snprintf(subcmd, sizeof(subcmd),
+             "mkdir x64;"
+            "put %s x64/%s.ppd;"
+            "put %s/drivers/x64/ps5ui.dll x64/ps5ui.dll;"
+            "put %s/drivers/x64/pscript.hlp x64/pscript.hlp;"
+            "put %s/drivers/x64/pscript.ntf x64/pscript.ntf;"
+            "put %s/drivers/x64/pscript5.dll x64/pscript5.dll",
+            ppd, dest, cg->cups_datadir, cg->cups_datadir,
+            cg->cups_datadir, cg->cups_datadir);
+
+    if ((status = do_samba_command("smbclient", address, subcmd,
+                                   authfile, logfile)) != 0)
+    {
+      snprintf(message, sizeof(message),
+               _cupsLangString(language,
+                              _("Unable to copy 64-bit Windows printer "
+                                "driver files (%d)!")), status);
+
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
+
+      if (logfile)
+       _cupsLangPrintf(logfile, "%s\n", message);
+
+      unlink(authfile);
+
+      return (0);
+    }
+
+   /*
+    * See if we also have the CUPS driver files; if so, use them!
+    */
+
+    snprintf(file, sizeof(file), "%s/drivers/x64/cupsps6.dll", cg->cups_datadir);
+    if (!access(file, 0))
+    {
+     /*
+      * Copy the CUPS driver files over...
+      */
+
+      snprintf(subcmd, sizeof(subcmd),
+               "put %s/drivers/x64/cups6.ini x64/cups6.ini;"
+               "put %s/drivers/x64/cupsps6.dll x64/cupsps6.dll;"
+              "put %s/drivers/x64/cupsui6.dll x64/cupsui6.dll",
+              cg->cups_datadir, cg->cups_datadir, cg->cups_datadir);
+
+      if ((status = do_samba_command("smbclient", address, subcmd,
+                                     authfile, logfile)) != 0)
+      {
+       snprintf(message, sizeof(message),
+                _cupsLangString(language,
+                                _("Unable to copy 64-bit CUPS printer driver "
+                                  "files (%d)!")), status);
+
+       _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
+
+       if (logfile)
+         _cupsLangPrintf(logfile, "%s\n", message);
+
+        unlink(authfile);
+
+       return (0);
+      }
+      
+     /*
+      * Do the rpcclient command needed for the CUPS drivers...
+      */
+
+      snprintf(subcmd, sizeof(subcmd),
+               "adddriver \"Windows x64\" \"%s:"
+              "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
+              "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf,"
+              "cups6.ini,cupsps6.dll,cupsui6.dll\"",
+              dest, dest, dest);
+    }
+    else
+    {
+     /*
+      * Don't have the CUPS drivers, so just use the standard Windows
+      * drivers...
+      */
+
+      snprintf(subcmd, sizeof(subcmd),
+               "adddriver \"Windows x64\" \"%s:"
+              "pscript5.dll:%s.ppd:ps5ui.dll:pscript.hlp:NULL:RAW:"
+              "pscript5.dll,%s.ppd,ps5ui.dll,pscript.hlp,pscript.ntf\"",
+              dest, dest, dest);
+    }
+
+    if ((status = do_samba_command("rpcclient", samba_server, subcmd,
+                                   authfile, logfile)) != 0)
+    {
+      snprintf(message, sizeof(message),
+               _cupsLangString(language,
+                              _("Unable to install Windows 2000 printer "
+                                "driver files (%d)!")), status);
+
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
       if (logfile)
        _cupsLangPrintf(logfile, "%s\n", message);
@@ -656,12 +805,18 @@ cupsAdminExportSamba(
                                "are installed!")),
               sizeof(message));
 
-    _cupsSetError(IPP_INTERNAL_ERROR, message);
+    _cupsSetError(IPP_NOT_FOUND, message, 0);
     _cupsLangPrintf(logfile, "%s\n", message);
   }
 
   if (have_drivers == 0)
+  {
+    _cupsSetError(IPP_NOT_FOUND, message, 0);
+
+    unlink(authfile);
+
     return (0);
+  }
 
  /*
   * Finally, associate the drivers we just added with the queue...
@@ -677,7 +832,7 @@ cupsAdminExportSamba(
                             _("Unable to set Windows printer driver (%d)!")),
                             status);
 
-    _cupsSetError(IPP_INTERNAL_ERROR, message);
+    _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
     if (logfile)
       _cupsLangPrintf(logfile, "%s\n", message);
@@ -693,6 +848,25 @@ cupsAdminExportSamba(
 }
 
 
+/*
+ * 'cupsAdminGetServerSettings()' - Get settings from the server.
+ *
+ * The returned settings should be freed with cupsFreeOptions() when
+ * you are done with them.
+ *
+ * @since CUPS 1.3/Mac OS X 10.5@
+ */
+
+int                                    /* O - 1 on success, 0 on failure */
+cupsAdminGetServerSettings(
+    http_t        *http,               /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
+    int           *num_settings,       /* O - Number of settings */
+    cups_option_t **settings)          /* O - Settings */
+{
+  return (_cupsAdminGetServerSettings(http, num_settings, settings));
+}
+
+
 /*
  * '_cupsAdminGetServerSettings()' - Get settings from the server.
  *
@@ -704,7 +878,7 @@ cupsAdminExportSamba(
 
 int                                    /* O - 1 on success, 0 on failure */
 _cupsAdminGetServerSettings(
-    http_t        *http,               /* I - Connection to server */
+    http_t        *http,               /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
     int           *num_settings,       /* O - Number of settings */
     cups_option_t **settings)          /* O - Settings */
 {
@@ -723,9 +897,65 @@ _cupsAdminGetServerSettings(
   * Range check input...
   */
 
+  if (!http)
+  {
+   /*
+    * See if we are connected to the same server...
+    */
+
+    if (cg->http)
+    {
+     /*
+      * Compare the connection hostname, port, and encryption settings to
+      * the cached defaults; these were initialized the first time we
+      * connected...
+      */
+
+      if (strcmp(cg->http->hostname, cg->server) ||
+          cg->ipp_port != _httpAddrPort(cg->http->hostaddr) ||
+         (cg->http->encryption != cg->encryption &&
+          cg->http->encryption == HTTP_ENCRYPT_NEVER))
+      {
+       /*
+       * Need to close the current connection because something has changed...
+       */
+
+       httpClose(cg->http);
+       cg->http = NULL;
+      }
+    }
+
+   /*
+    * (Re)connect as needed...
+    */
+
+    if (!cg->http)
+    {
+      if ((cg->http = _httpCreate(cupsServer(), ippPort(),
+                                  cupsEncryption())) == NULL)
+      {
+       if (errno)
+         _cupsSetError(IPP_SERVICE_UNAVAILABLE, NULL, 0);
+       else
+         _cupsSetError(IPP_SERVICE_UNAVAILABLE,
+                       _("Unable to connect to host."), 1);
+
+       if (num_settings)
+         *num_settings = 0;
+
+       if (settings)
+         *settings = NULL;
+
+       return (0);
+      }
+    }
+
+    http = cg->http;
+  }
+
   if (!http || !num_settings || !settings)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
 
     if (num_settings)
       *num_settings = 0;
@@ -752,9 +982,9 @@ _cupsAdminGetServerSettings(
 
 
       snprintf(message, sizeof(message),
-               _cupsLangString(cupsLangDefault(), _("open of %s failed: %s")),
+               _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
                cupsdconf, strerror(errno));
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
     }
   }
   else
@@ -788,10 +1018,10 @@ _cupsAdminGetServerSettings(
 
     while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
     {
-      if (!value)
-        continue;
+      if (!value && strncmp(line, "</", 2))
+        value = line + strlen(line);
 
-      if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen"))
+      if ((!strcasecmp(line, "Port") || !strcasecmp(line, "Listen")) && value)
       {
        char    *port;                  /* Pointer to port number, if any */
 
@@ -847,7 +1077,7 @@ _cupsAdminGetServerSettings(
       {
        in_policy = 0;
       }
-      else if (!strcasecmp(line, "<Limit") && in_policy)
+      else if (!strcasecmp(line, "<Limit") && in_policy && value)
       {
        /*
        * See if the policy limit is for the Cancel-Job operation...
@@ -880,7 +1110,7 @@ _cupsAdminGetServerSettings(
       {
        cancel_policy = 0;
       }
-      else if (!strcasecmp(line, "<Location"))
+      else if (!strcasecmp(line, "<Location") && value)
       {
         in_admin_location = !strcasecmp(value, "/admin");
        in_location       = 1;
@@ -890,7 +1120,7 @@ _cupsAdminGetServerSettings(
        in_admin_location = 0;
        in_location       = 0;
       }
-      else if (!strcasecmp(line, "Allow") && in_admin_location &&
+      else if (!strcasecmp(line, "Allow") && value &&
                strcasecmp(value, "localhost") && strcasecmp(value, "127.0.0.1")
 #ifdef AF_LOCAL
               && *value != '/'
@@ -900,12 +1130,18 @@ _cupsAdminGetServerSettings(
 #endif /* AF_INET6 */
               )
       {
-       remote_admin = 1;
-
-       if (!strcasecmp(value, "all"))
+        if (in_admin_location)
+         remote_admin = 1;
+        else if (!strcasecmp(value, "all"))
          remote_any = 1;
       }
-      else if (line[0] != '<' && !in_location && !in_policy)
+      else if (line[0] != '<' && !in_location && !in_policy &&
+              strcasecmp(line, "Allow") &&
+               strcasecmp(line, "AuthType") &&
+              strcasecmp(line, "Deny") &&
+              strcasecmp(line, "Order") &&
+              strcasecmp(line, "Require") &&
+              strcasecmp(line, "Satisfy"))
         cg->cupsd_num_settings = cupsAddOption(line, value,
                                               cg->cupsd_num_settings,
                                               &(cg->cupsd_settings));
@@ -966,6 +1202,22 @@ _cupsAdminGetServerSettings(
 }
 
 
+/*
+ * 'cupsAdminSetServerSettings()' - Set settings on the server.
+ *
+ * @since CUPS 1.3/Mac OS X 10.5@
+ */
+
+int                                    /* O - 1 on success, 0 on failure */
+cupsAdminSetServerSettings(
+    http_t        *http,               /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
+    int           num_settings,                /* I - Number of settings */
+    cups_option_t *settings)           /* I - Settings */
+{
+  return (_cupsAdminSetServerSettings(http, num_settings, settings));
+}
+
+
 /*
  * '_cupsAdminSetServerSettings()' - Set settings on the server.
  *
@@ -974,7 +1226,7 @@ _cupsAdminGetServerSettings(
 
 int                                    /* O - 1 on success, 0 on failure */
 _cupsAdminSetServerSettings(
-    http_t        *http,               /* I - Connection to server */
+    http_t        *http,               /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
     int           num_settings,                /* I - Number of settings */
     cups_option_t *settings)           /* I - Settings */
 {
@@ -1027,9 +1279,12 @@ _cupsAdminSetServerSettings(
   * Range check input...
   */
 
+  if (!http)
+    http = _cupsConnect();
+
   if (!http || !num_settings || !settings)
   {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
 
     return (0);
   }
@@ -1038,12 +1293,12 @@ _cupsAdminSetServerSettings(
   * Get the cupsd.conf file...
   */
 
-  if ((status = get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf),
-                               &remote)) == HTTP_OK)
+  if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf),
+                     &remote) == HTTP_OK)
   {
     if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
     {
-      _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+      _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
       return (0);
     }
   }
@@ -1200,7 +1455,7 @@ _cupsAdminSetServerSettings(
     if (remote)
       unlink(cupsdconf);
 
-    _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+    _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
     return (0);
   }
 
@@ -1275,19 +1530,41 @@ _cupsAdminSetServerSettings(
               !strcasecmp(line, "BrowseAddress") ||
               !strcasecmp(line, "BrowseAllow") ||
               !strcasecmp(line, "BrowseDeny") ||
+              !strcasecmp(line, "BrowseLocalProtocols") ||
+              !strcasecmp(line, "BrowseRemoteProtocols") ||
               !strcasecmp(line, "BrowseOrder")) &&
             (remote_printers >= 0 || share_printers >= 0))
     {
       if (!wrote_browsing)
       {
+       int new_remote_printers = (remote_printers > 0 ||
+                                  (remote_printers == -1 &&
+                                   old_remote_printers > 0));
+       int new_share_printers = (share_printers > 0 ||
+                                 (share_printers == -1 &&
+                                  old_share_printers > 0));
+
         wrote_browsing = 1;
 
-        if (remote_printers > 0 || share_printers > 0)
+        if (new_remote_printers || new_share_printers)
        {
-         if (remote_printers > 0 && share_printers > 0)
+         const char *localp = cupsGetOption("BrowseLocalProtocols",
+                                            num_settings, settings);
+         const char *remotep = cupsGetOption("BrowseRemoteProtocols",
+                                             num_settings, settings);
+
+          if (!localp)
+           localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings,
+                                  cupsd_settings);
+
+          if (!remotep)
+           remotep = cupsGetOption("BrowseRemoteProtocols", cupsd_num_settings,
+                                   cupsd_settings);
+
+         if (new_remote_printers && new_share_printers)
            cupsFilePuts(temp,
                         "# Enable printer sharing and shared printers.\n");
-         else if (remote_printers > 0)
+         else if (new_remote_printers)
            cupsFilePuts(temp,
                         "# Show shared printers on the local network.\n");
          else
@@ -1297,11 +1574,37 @@ _cupsAdminSetServerSettings(
          cupsFilePuts(temp, "Browsing On\n");
          cupsFilePuts(temp, "BrowseOrder allow,deny\n");
 
-         if (remote_printers > 0)
+         if (new_remote_printers)
+         {
            cupsFilePuts(temp, "BrowseAllow all\n");
 
-         if (share_printers > 0)
+           if (!remotep)
+             remotep = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS;
+
+           cupsFilePrintf(temp, "BrowseRemoteProtocols %s\n", remotep);
+          }
+         else
+           cupsFilePuts(temp, "BrowseRemoteProtocols\n");
+
+         cupsd_num_settings = cupsAddOption("BrowseRemoteProtocols", remotep,
+                                            cupsd_num_settings,
+                                            &cupsd_settings);
+
+         if (new_share_printers)
+         {
            cupsFilePuts(temp, "BrowseAddress @LOCAL\n");
+
+           if (!localp)
+             localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
+
+           cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp);
+         }
+         else
+           cupsFilePuts(temp, "BrowseLocalProtocols\n");
+
+         cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp,
+                                            cupsd_num_settings,
+                                            &cupsd_settings);
         }
        else
        {
@@ -1324,7 +1627,7 @@ _cupsAdminSetServerSettings(
       else
       {
         cupsFilePuts(temp, "# Show general information in error_log.\n");
-       cupsFilePuts(temp, "LogLevel info\n");
+       cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
       }
     }
     else if (!strcasecmp(line, "<Policy"))
@@ -1347,8 +1650,8 @@ _cupsAdminSetServerSettings(
                             "cancel a job...\n"
                             "  <Limit Cancel-Job>\n"
                             "    Order deny,allow\n"
-                            "    Allow @SYSTEM\n"
-                            "    Allow @OWNER\n"
+                            "    Require user @OWNER "
+                            CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
                             "  </Limit>\n");
       }
 
@@ -1388,8 +1691,6 @@ _cupsAdminSetServerSettings(
        if (remote_admin)
          cupsFilePrintf(temp, "  Allow %s\n",
                         remote_any > 0 ? "all" : "@LOCAL");
-       else
-         cupsFilePuts(temp, "  Allow localhost\n");
       }
       else if (in_conf_location && remote_admin >= 0)
       {
@@ -1407,8 +1708,6 @@ _cupsAdminSetServerSettings(
        if (remote_admin)
          cupsFilePrintf(temp, "  Allow %s\n",
                         remote_any > 0 ? "all" : "@LOCAL");
-       else
-         cupsFilePuts(temp, "  Allow localhost\n");
       }
       else if (in_root_location && (remote_admin >= 0 || share_printers >= 0))
       {
@@ -1429,8 +1728,6 @@ _cupsAdminSetServerSettings(
        if (remote_admin > 0 || share_printers > 0)
          cupsFilePrintf(temp, "  Allow %s\n",
                         remote_any > 0 ? "all" : "@LOCAL");
-       else
-         cupsFilePuts(temp, "  Allow localhost\n");
       }
 
       in_admin_location = 0;
@@ -1500,7 +1797,8 @@ _cupsAdminSetServerSettings(
                           "a job...\n"
                           "  <Limit Cancel-Job>\n"
                           "    Order deny,allow\n"
-                          "    Require user @OWNER @SYSTEM\n"
+                          "    Require user @OWNER "
+                          CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
                           "  </Limit>\n");
 
       in_cancel_job = 0;
@@ -1531,14 +1829,13 @@ _cupsAdminSetServerSettings(
       }
     }
     else if (!in_policy && !in_location &&
-             (val = cupsGetOption(line, num_settings, settings)) != NULL &&
-             !cupsGetOption(line, cupsd_num_settings, cupsd_settings))
+             (val = cupsGetOption(line, num_settings, settings)) != NULL)
     {
      /*
-      * Add this directive to the list of directives we have written...
+      * Replace this directive's value with the new one...
       */
 
-      cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings,
+      cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings,
                                          &cupsd_settings);
 
      /*
@@ -1546,7 +1843,7 @@ _cupsAdminSetServerSettings(
       * only support setting root directives, not in sections...
       */
 
-      cupsFilePrintf(temp, "%s %s\n", line, value);
+      cupsFilePrintf(temp, "%s %s\n", line, val);
     }
     else if (value)
     {
@@ -1609,7 +1906,7 @@ _cupsAdminSetServerSettings(
     else
     {
       cupsFilePuts(temp, "# Show general information in error_log.\n");
-      cupsFilePuts(temp, "LogLevel info\n");
+      cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
     }
   }
 
@@ -1650,8 +1947,6 @@ _cupsAdminSetServerSettings(
 
     if (remote_admin > 0 || share_printers > 0)
       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
-    else
-      cupsFilePuts(temp, "  Allow localhost\n");
 
     cupsFilePuts(temp, "</Location>\n");
   }
@@ -1668,8 +1963,6 @@ _cupsAdminSetServerSettings(
 
     if (remote_admin)
       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
-    else
-      cupsFilePuts(temp, "  Allow localhost\n");
 
     cupsFilePuts(temp, "</Location>\n");
   }
@@ -1683,14 +1976,12 @@ _cupsAdminSetServerSettings(
       cupsFilePuts(temp, "# Restrict access to the configuration files...\n");
 
     cupsFilePuts(temp, "<Location /admin/conf>\n"
-                       "  AuthType Basic\n"
+                       "  AuthType Default\n"
                        "  Require user @SYSTEM\n"
                        "  Order allow,deny\n");
 
     if (remote_admin)
       cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");
-    else
-      cupsFilePuts(temp, "  Allow localhost\n");
 
     cupsFilePuts(temp, "</Location>\n");
   }
@@ -1699,7 +1990,7 @@ _cupsAdminSetServerSettings(
   {
     cupsFilePuts(temp, "<Policy default>\n"
                        "  # Job-related operations must be done by the owner "
-                      "or an adminstrator...\n"
+                      "or an administrator...\n"
                        "  <Limit Send-Document Send-URI Hold-Job Release-Job "
                       "Restart-Job Purge-Jobs Set-Job-Attributes "
                       "Create-Job-Subscription Renew-Subscription "
@@ -1710,7 +2001,7 @@ _cupsAdminSetServerSettings(
                        "    Order deny,allow\n"
                        "  </Limit>\n"
                        "  # All administration operations require an "
-                      "adminstrator to authenticate...\n"
+                      "administrator to authenticate...\n"
                       "  <Limit Pause-Printer Resume-Printer "
                        "Set-Printer-Attributes Enable-Printer "
                       "Disable-Printer Pause-Printer-After-Current-Job "
@@ -1721,7 +2012,7 @@ _cupsAdminSetServerSettings(
                       "CUPS-Add-Class CUPS-Delete-Class "
                       "CUPS-Accept-Jobs CUPS-Reject-Jobs "
                       "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
-                       "    AuthType Basic\n"
+                       "    AuthType Default\n"
                       "    Require user @SYSTEM\n"
                        "    Order deny,allow\n"
                        "</Limit>\n");
@@ -1730,8 +2021,9 @@ _cupsAdminSetServerSettings(
       cupsFilePuts(temp, "  # Only the owner or an administrator can cancel "
                          "a job...\n"
                         "  <Limit Cancel-Job>\n"
-                        "    Require user @OWNER @SYSTEM\n"
                         "    Order deny,allow\n"
+                        "    Require user @OWNER "
+                        CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
                         "  </Limit>\n");
 
     cupsFilePuts(temp, "  <Limit All>\n"
@@ -1752,8 +2044,8 @@ _cupsAdminSetServerSettings(
                                          cupsd_num_settings, &cupsd_settings);
 
      /*
-      * Write the new value in its place, without indentation since we
-      * only support setting root directives, not in sections...
+      * Write the new value, without indentation since we only support
+      * setting root directives, not in sections...
       */
 
       cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value);
@@ -1918,7 +2210,7 @@ do_samba_command(const char *command,     /* I - Command to run */
   if (logfile)
     _cupsLangPuts(logfile, "\n");
 
-  DEBUG_printf(("status=%d\n", status));
+  DEBUG_printf(("9do_samba_command: status=%d", status));
 
   if (WIFEXITED(status))
     return (WEXITSTATUS(status));
@@ -1976,7 +2268,7 @@ get_cupsd_conf(
       snprintf(message, sizeof(message),
                _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
                name, strerror(errno));
-      _cupsSetError(IPP_INTERNAL_ERROR, message);
+      _cupsSetError(IPP_INTERNAL_ERROR, message, 0);
 
       *name = '\0';
 
@@ -1998,7 +2290,7 @@ get_cupsd_conf(
     {
       *name = '\0';
 
-      _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+      _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
 
       invalidate_cupsd_cache(cg);
 
@@ -2155,5 +2447,5 @@ write_option(cups_file_t     *dstfp,      /* I - PPD file */
 
 
 /*
- * End of "$Id: adminutil.c 6270 2007-02-12 14:27:47Z mike $".
+ * End of "$Id: adminutil.c 7850 2008-08-20 00:07:25Z mike $".
  */