]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/classes.c
Update svn:keyword properties.
[thirdparty/cups.git] / scheduler / classes.c
index 9c098f74f415d6466553a5d1b749dd7da76d7189..5ced554f599e1e195a5a12bfe620026ba816cb04 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$Id: classes.c 4988 2006-01-26 00:53:00Z mike $"
+ * "$Id$"
  *
- *   Printer class routines for the Common UNIX Printing System (CUPS).
+ *   Printer class routines for the CUPS scheduler.
  *
- *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   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/".
  *
  * Contents:
  *
  *   cupsdAddPrinterToClass()        - Add a printer to a class...
  *   cupsdDeletePrinterFromClass()   - Delete a printer from a class.
  *   cupsdDeletePrinterFromClasses() - Delete a printer from all classes.
- *   cupsdDeleteAllClasses()         - Remove all classes from the system.
  *   cupsdFindAvailablePrinter()     - Find an available printer in a class.
  *   cupsdFindClass()                - Find the named class.
  *   cupsdLoadAllClasses()           - Load classes from the classes.conf file.
  *   cupsdSaveAllClasses()           - Save classes to the classes.conf file.
- *   cupsdUpdateImplicitClasses()    - Update the accepting state of implicit
- *                                     classes.
  */
 
 /*
@@ -51,6 +39,7 @@ cupsd_printer_t *                     /* O - New class */
 cupsdAddClass(const char *name)                /* I - Name of class */
 {
   cupsd_printer_t      *c;             /* New class */
+  char                 uri[1024];      /* Class URI */
 
 
  /*
@@ -65,9 +54,11 @@ cupsdAddClass(const char *name)              /* I - Name of class */
 
     c->type = CUPS_PRINTER_CLASS;
 
-    cupsdSetStringf(&c->uri, "ipp://%s:%d/classes/%s", ServerName, LocalPort,
-                    name);
-    cupsdSetString(&c->error_policy, "retry-job");
+    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                    ServerName, RemotePort, "/classes/%s", name);
+    cupsdSetString(&c->uri, uri);
+
+    cupsdSetString(&c->error_policy, "retry-current-job");
   }
 
   return (c);
@@ -127,14 +118,12 @@ cupsdAddPrinterToClass(
  * 'cupsdDeletePrinterFromClass()' - Delete a printer from a class.
  */
 
-void
+int                                    /* O - 1 if class changed, 0 otherwise */
 cupsdDeletePrinterFromClass(
     cupsd_printer_t *c,                        /* I - Class to delete from */
     cupsd_printer_t *p)                        /* I - Printer to delete */
 {
-  int          i;                      /* Looping var */
-  cups_ptype_t type,                   /* Class type */
-               oldtype;                /* Old class type */
+  int  i;                              /* Looping var */
 
 
  /*
@@ -161,30 +150,15 @@ cupsdDeletePrinterFromClass(
               (c->num_printers - i) * sizeof(cupsd_printer_t *));
   }
   else
-    return;
+    return (0);
 
  /*
-  * Recompute the printer type mask as needed...
+  * Update the IPP attributes (have to do this for member-names)...
   */
 
-  if (c->num_printers > 0)
-  {
-    oldtype = c->type;
-    type    = c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT);
-    c->type = ~CUPS_PRINTER_REMOTE;
-
-    for (i = 0; i < c->num_printers; i ++)
-      c->type &= c->printers[i]->type;
-
-    c->type |= type;
-
-   /*
-    * Update the IPP attributes...
-    */
+  cupsdSetPrinterAttrs(c);
 
-    if (c->type != oldtype)
-      cupsdSetPrinterAttrs(c);
-  }
+  return (1);
 }
 
 
@@ -192,10 +166,11 @@ cupsdDeletePrinterFromClass(
  * 'cupsdDeletePrinterFromClasses()' - Delete a printer from all classes.
  */
 
-void
+int                                    /* O - 1 if class changed, 0 otherwise */
 cupsdDeletePrinterFromClasses(
     cupsd_printer_t *p)                        /* I - Printer to delete */
 {
+  int                  changed = 0;    /* Any class changed? */
   cupsd_printer_t      *c;             /* Pointer to current class */
 
 
@@ -204,42 +179,13 @@ cupsdDeletePrinterFromClasses(
   * from each class listed...
   */
 
-  for (c = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       c;
-       c = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
-      cupsdDeletePrinterFromClass(c, p);
-
- /*
-  * Then clean out any empty implicit classes...
-  */
-
-  for (c = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters);
-       c;
-       c = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters))
-    if (c->num_printers == 0)
-    {
-      cupsArrayRemove(ImplicitPrinters, c);
-      cupsdDeletePrinter(c, 0);
-    }
-}
-
-
-/*
- * 'cupsdDeleteAllClasses()' - Remove all classes from the system.
- */
-
-void
-cupsdDeleteAllClasses(void)
-{
-  cupsd_printer_t      *c;             /* Pointer to current printer/class */
-
-
   for (c = (cupsd_printer_t *)cupsArrayFirst(Printers);
        c;
        c = (cupsd_printer_t *)cupsArrayNext(Printers))
     if (c->type & CUPS_PRINTER_CLASS)
-      cupsdDeletePrinter(c, 0);
+      changed |= cupsdDeletePrinterFromClass(c, p);
+
+  return (changed);
 }
 
 
@@ -265,6 +211,17 @@ cupsdFindAvailablePrinter(
     return (NULL);
   }
 
+  if (c->num_printers == 0)
+    return (NULL);
+
+ /*
+  * Make sure that the last printer is also a valid index into the printer
+  * array.  If not, reset the last printer to 0...
+  */
+
+  if (c->last_printer >= c->num_printers)
+    c->last_printer = 0;
+
  /*
   * Loop through the printers in the class and return the first idle
   * printer...  We keep track of the last printer that we used so that
@@ -305,8 +262,7 @@ cupsdFindClass(const char *name)    /* I - Name of class */
   cupsd_printer_t      *c;             /* Current class/printer */
 
 
-  if ((c = cupsdFindDest(name)) != NULL &&
-      (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
+  if ((c = cupsdFindDest(name)) != NULL && (c->type & CUPS_PRINTER_CLASS))
     return (c);
   else
     return (NULL);
@@ -320,9 +276,10 @@ cupsdFindClass(const char *name)   /* I - Name of class */
 void
 cupsdLoadAllClasses(void)
 {
+  int                  i;              /* Looping var */
   cups_file_t          *fp;            /* classes.conf file */
   int                  linenum;        /* Current line number */
-  char                 line[1024],     /* Line from file */
+  char                 line[4096],     /* Line from file */
                        *value,         /* Pointer to value */
                        *valueptr;      /* Pointer into value */
   cupsd_printer_t      *p,             /* Current printer class */
@@ -334,14 +291,8 @@ cupsdLoadAllClasses(void)
   */
 
   snprintf(line, sizeof(line), "%s/classes.conf", ServerRoot);
-  if ((fp = cupsFileOpen(line, "r")) == NULL)
-  {
-    if (errno != ENOENT)
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "cupsdLoadAllClasses: Unable to open %s - %s", line,
-                     strerror(errno));
+  if ((fp = cupsdOpenConfFile(line)) == NULL)
     return;
-  }
 
  /*
   * Read class configurations until we hit EOF...
@@ -356,8 +307,8 @@ cupsdLoadAllClasses(void)
     * Decode the directive...
     */
 
-    if (!strcasecmp(line, "<Class") ||
-        !strcasecmp(line, "<DefaultClass"))
+    if (!_cups_strcasecmp(line, "<Class") ||
+        !_cups_strcasecmp(line, "<DefaultClass"))
     {
      /*
       * <Class name> or <DefaultClass name>
@@ -365,24 +316,34 @@ cupsdLoadAllClasses(void)
 
       if (p == NULL && value)
       {
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "cupsdLoadAllClasses: Loading class %s...", value);
+        cupsdLogMessage(CUPSD_LOG_DEBUG, "Loading class %s...", value);
+
+       /*
+        * Since prior classes may have implicitly defined this class,
+       * see if it already exists...
+       */
+
+        if ((p = cupsdFindDest(value)) != NULL)
+       {
+         p->type = CUPS_PRINTER_CLASS;
+         cupsdSetStringf(&p->uri, "ipp://%s:%d/classes/%s", ServerName,
+                         LocalPort, value);
+         cupsdSetString(&p->error_policy, "retry-job");
+       }
+       else
+          p = cupsdAddClass(value);
 
-        p = cupsdAddClass(value);
        p->accepting = 1;
        p->state     = IPP_PRINTER_IDLE;
 
-        if (!strcasecmp(line, "<DefaultClass"))
+        if (!_cups_strcasecmp(line, "<DefaultClass"))
          DefaultPrinter = p;
       }
       else
-      {
         cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-        return;
-      }
     }
-    else if (!strcasecmp(line, "</Class>"))
+    else if (!_cups_strcasecmp(line, "</Class>"))
     {
       if (p != NULL)
       {
@@ -390,35 +351,65 @@ cupsdLoadAllClasses(void)
         p = NULL;
       }
       else
-      {
         cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-        return;
-      }
     }
     else if (!p)
     {
       cupsdLogMessage(CUPSD_LOG_ERROR,
                       "Syntax error on line %d of classes.conf.", linenum);
-      return;
     }
-    else if (!strcasecmp(line, "Info"))
+    else if (!_cups_strcasecmp(line, "UUID"))
+    {
+      if (value && !strncmp(value, "urn:uuid:", 9))
+        cupsdSetString(&(p->uuid), value);
+      else
+        cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Bad UUID on line %d of classes.conf.", linenum);
+    }
+    else if (!_cups_strcasecmp(line, "AuthInfoRequired"))
+    {
+      if (!cupsdSetAuthInfoRequired(p, value, NULL))
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Bad AuthInfoRequired on line %d of classes.conf.",
+                       linenum);
+    }
+    else if (!_cups_strcasecmp(line, "Info"))
     {
       if (value)
         cupsdSetString(&p->info, value);
     }
-    else if (!strcasecmp(line, "Location"))
+    else if (!_cups_strcasecmp(line, "Location"))
     {
       if (value)
         cupsdSetString(&p->location, value);
     }
-    else if (!strcasecmp(line, "Printer"))
+    else if (!_cups_strcasecmp(line, "Option") && value)
+    {
+     /*
+      * Option name value
+      */
+
+      for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+
+      if (!*valueptr)
+        cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Syntax error on line %d of classes.conf.", linenum);
+      else
+      {
+        for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0');
+
+        p->num_options = cupsAddOption(value, valueptr, p->num_options,
+                                      &(p->options));
+      }
+    }
+    else if (!_cups_strcasecmp(line, "Printer"))
     {
       if (!value)
       {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
+        continue;
       }
       else if ((temp = cupsdFindPrinter(value)) == NULL)
       {
@@ -434,9 +425,8 @@ cupsdLoadAllClasses(void)
        {
          cupsdSetString(&temp->make_model, "Remote Printer on unknown");
 
-          temp->state       = IPP_PRINTER_STOPPED;
-         temp->type        |= CUPS_PRINTER_REMOTE;
-         temp->browse_time = 2147483647;
+          temp->state = IPP_PRINTER_STOPPED;
+         temp->type  |= CUPS_PRINTER_REMOTE;
 
          cupsdSetString(&temp->location, "Location Unknown");
          cupsdSetString(&temp->info, "No Information Available");
@@ -449,25 +439,35 @@ cupsdLoadAllClasses(void)
       if (temp)
         cupsdAddPrinterToClass(p, temp);
     }
-    else if (!strcasecmp(line, "State"))
+    else if (!_cups_strcasecmp(line, "State"))
     {
      /*
       * Set the initial queue state...
       */
 
-      if (!strcasecmp(value, "idle"))
+      if (!_cups_strcasecmp(value, "idle"))
         p->state = IPP_PRINTER_IDLE;
-      else if (!strcasecmp(value, "stopped"))
+      else if (!_cups_strcasecmp(value, "stopped"))
+      {
         p->state = IPP_PRINTER_STOPPED;
+
+        for (i = 0 ; i < p->num_reasons; i ++)
+         if (!strcmp("paused", p->reasons[i]))
+           break;
+
+        if (i >= p->num_reasons &&
+           p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+       {
+         p->reasons[p->num_reasons] = _cupsStrAlloc("paused");
+         p->num_reasons ++;
+       }
+      }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.",
                        linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "StateMessage"))
+    else if (!_cups_strcasecmp(line, "StateMessage"))
     {
      /*
       * Set the initial queue state message...
@@ -476,7 +476,7 @@ cupsdLoadAllClasses(void)
       if (value)
        strlcpy(p->state_message, value, sizeof(p->state_message));
     }
-    else if (!strcasecmp(line, "StateTime"))
+    else if (!_cups_strcasecmp(line, "StateTime"))
     {
      /*
       * Set the state time...
@@ -485,55 +485,49 @@ cupsdLoadAllClasses(void)
       if (value)
         p->state_time = atoi(value);
     }
-    else if (!strcasecmp(line, "Accepting"))
+    else if (!_cups_strcasecmp(line, "Accepting"))
     {
      /*
       * Set the initial accepting state...
       */
 
       if (value &&
-          (!strcasecmp(value, "yes") ||
-           !strcasecmp(value, "on") ||
-           !strcasecmp(value, "true")))
+          (!_cups_strcasecmp(value, "yes") ||
+           !_cups_strcasecmp(value, "on") ||
+           !_cups_strcasecmp(value, "true")))
         p->accepting = 1;
       else if (value &&
-               (!strcasecmp(value, "no") ||
-               !strcasecmp(value, "off") ||
-               !strcasecmp(value, "false")))
+               (!_cups_strcasecmp(value, "no") ||
+               !_cups_strcasecmp(value, "off") ||
+               !_cups_strcasecmp(value, "false")))
         p->accepting = 0;
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.",
                        linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "Shared"))
+    else if (!_cups_strcasecmp(line, "Shared"))
     {
      /*
       * Set the initial shared state...
       */
 
       if (value &&
-          (!strcasecmp(value, "yes") ||
-           !strcasecmp(value, "on") ||
-           !strcasecmp(value, "true")))
+          (!_cups_strcasecmp(value, "yes") ||
+           !_cups_strcasecmp(value, "on") ||
+           !_cups_strcasecmp(value, "true")))
         p->shared = 1;
       else if (value &&
-               (!strcasecmp(value, "no") ||
-               !strcasecmp(value, "off") ||
-               !strcasecmp(value, "false")))
+               (!_cups_strcasecmp(value, "no") ||
+               !_cups_strcasecmp(value, "off") ||
+               !_cups_strcasecmp(value, "false")))
         p->shared = 0;
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of printers.conf.",
+                       "Syntax error on line %d of classes.conf.",
                        linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "JobSheets"))
+    else if (!_cups_strcasecmp(line, "JobSheets"))
     {
      /*
       * Set the initial job sheets...
@@ -560,100 +554,94 @@ cupsdLoadAllClasses(void)
               valueptr ++);
 
          if (*valueptr)
-            *valueptr++ = '\0';
+            *valueptr = '\0';
 
          cupsdSetString(&p->job_sheets[1], value);
        }
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "AllowUser"))
+    else if (!_cups_strcasecmp(line, "AllowUser"))
     {
       if (value)
       {
         p->deny_users = 0;
-        cupsdAddPrinterUser(p, value);
+        cupsdAddString(&(p->users), value);
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "DenyUser"))
+    else if (!_cups_strcasecmp(line, "DenyUser"))
     {
       if (value)
       {
         p->deny_users = 1;
-        cupsdAddPrinterUser(p, value);
+        cupsdAddString(&(p->users), value);
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "QuotaPeriod"))
+    else if (!_cups_strcasecmp(line, "QuotaPeriod"))
     {
       if (value)
         p->quota_period = atoi(value);
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "PageLimit"))
+    else if (!_cups_strcasecmp(line, "PageLimit"))
     {
       if (value)
         p->page_limit = atoi(value);
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "KLimit"))
+    else if (!_cups_strcasecmp(line, "KLimit"))
     {
       if (value)
         p->k_limit = atoi(value);
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "OpPolicy"))
+    else if (!_cups_strcasecmp(line, "OpPolicy"))
     {
       if (value)
-        cupsdSetString(&p->op_policy, value);
-      else
       {
+        cupsd_policy_t *pol;           /* Policy */
+
+
+        if ((pol = cupsdFindPolicy(value)) != NULL)
+       {
+          cupsdSetString(&p->op_policy, value);
+         p->op_policy_ptr = pol;
+       }
+       else
+         cupsdLogMessage(CUPSD_LOG_ERROR,
+                         "Bad policy \"%s\" on line %d of classes.conf",
+                         value, linenum);
+      }
+      else
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
-    else if (!strcasecmp(line, "ErrorPolicy"))
+    else if (!_cups_strcasecmp(line, "ErrorPolicy"))
     {
       if (value)
-        cupsdSetString(&p->error_policy, value);
-      else
       {
+        if (strcmp(value, "retry-current-job") && strcmp(value, "retry-job"))
+         cupsdLogMessage(CUPSD_LOG_WARN,
+                         "ErrorPolicy %s ignored on line %d of classes.conf",
+                         value, linenum);
+      }
+      else
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of classes.conf.", linenum);
-       return;
-      }
     }
     else
     {
@@ -679,47 +667,27 @@ void
 cupsdSaveAllClasses(void)
 {
   cups_file_t          *fp;            /* classes.conf file */
-  char                 temp[1024];     /* Temporary string */
-  char                 backup[1024];   /* classes.conf.O file */
+  char                 filename[1024], /* classes.conf filename */
+                       temp[1024],     /* Temporary string */
+                       value[2048],    /* Value string */
+                       *name;          /* Current user name */
   cupsd_printer_t      *pclass;        /* Current printer class */
   int                  i;              /* Looping var */
   time_t               curtime;        /* Current time */
   struct tm            *curdate;       /* Current date */
+  cups_option_t                *option;        /* Current option */
 
 
  /*
   * Create the classes.conf file...
   */
 
-  snprintf(temp, sizeof(temp), "%s/classes.conf", ServerRoot);
-  snprintf(backup, sizeof(backup), "%s/classes.conf.O", ServerRoot);
-
-  if (rename(temp, backup))
-  {
-    if (errno != ENOENT)
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to backup classes.conf - %s",
-                      strerror(errno));
-  }
-
-  if ((fp = cupsFileOpen(temp, "w")) == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to save classes.conf - %s",
-                    strerror(errno));
+  snprintf(filename, sizeof(filename), "%s/classes.conf", ServerRoot);
 
-    if (rename(backup, temp))
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to restore classes.conf - %s",
-                      strerror(errno));
+  if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL)
     return;
-  }
-  else
-    cupsdLogMessage(CUPSD_LOG_INFO, "Saving classes.conf...");
-
- /*
-  * Restrict access to the file...
-  */
 
-  fchown(cupsFileNumber(fp), RunUser, Group);
-  fchmod(cupsFileNumber(fp), 0600);
+  cupsdLogMessage(CUPSD_LOG_INFO, "Saving classes.conf...");
 
  /*
   * Write a small header to the file...
@@ -731,6 +699,7 @@ cupsdSaveAllClasses(void)
 
   cupsFilePuts(fp, "# Class configuration file for " CUPS_SVERSION "\n");
   cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
+  cupsFilePuts(fp, "# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING\n");
 
  /*
   * Write each local class known to the system...
@@ -745,7 +714,6 @@ cupsdSaveAllClasses(void)
     */
 
     if ((pclass->type & CUPS_PRINTER_REMOTE) ||
-        (pclass->type & CUPS_PRINTER_IMPLICIT) ||
         !(pclass->type & CUPS_PRINTER_CLASS))
       continue;
 
@@ -758,17 +726,42 @@ cupsdSaveAllClasses(void)
     else
       cupsFilePrintf(fp, "<Class %s>\n", pclass->name);
 
+    cupsFilePrintf(fp, "UUID %s\n", pclass->uuid);
+
+    if (pclass->num_auth_info_required > 0)
+    {
+      switch (pclass->num_auth_info_required)
+      {
+        case 1 :
+            strlcpy(value, pclass->auth_info_required[0], sizeof(value));
+           break;
+
+        case 2 :
+            snprintf(value, sizeof(value), "%s,%s",
+                    pclass->auth_info_required[0],
+                    pclass->auth_info_required[1]);
+           break;
+
+        case 3 :
+       default :
+            snprintf(value, sizeof(value), "%s,%s,%s",
+                    pclass->auth_info_required[0],
+                    pclass->auth_info_required[1],
+                    pclass->auth_info_required[2]);
+           break;
+      }
+
+      cupsFilePutConf(fp, "AuthInfoRequired", value);
+    }
+
     if (pclass->info)
-      cupsFilePrintf(fp, "Info %s\n", pclass->info);
+      cupsFilePutConf(fp, "Info", pclass->info);
 
     if (pclass->location)
-      cupsFilePrintf(fp, "Location %s\n", pclass->location);
+      cupsFilePutConf(fp, "Location", pclass->location);
 
     if (pclass->state == IPP_PRINTER_STOPPED)
-    {
       cupsFilePuts(fp, "State Stopped\n");
-      cupsFilePrintf(fp, "StateMessage %s\n", pclass->state_message);
-    }
     else
       cupsFilePuts(fp, "State Idle\n");
 
@@ -784,8 +777,9 @@ cupsdSaveAllClasses(void)
     else
       cupsFilePuts(fp, "Shared No\n");
 
-    cupsFilePrintf(fp, "JobSheets %s %s\n", pclass->job_sheets[0],
-                   pclass->job_sheets[1]);
+    snprintf(value, sizeof(value), "%s %s", pclass->job_sheets[0],
+             pclass->job_sheets[1]);
+    cupsFilePutConf(fp, "JobSheets", value);
 
     for (i = 0; i < pclass->num_printers; i ++)
       cupsFilePrintf(fp, "Printer %s\n", pclass->printers[i]->name);
@@ -794,52 +788,31 @@ cupsdSaveAllClasses(void)
     cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit);
     cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit);
 
-    for (i = 0; i < pclass->num_users; i ++)
-      cupsFilePrintf(fp, "%sUser %s\n", pclass->deny_users ? "Deny" : "Allow",
-                    pclass->users[i]);
+    for (name = (char *)cupsArrayFirst(pclass->users);
+         name;
+        name = (char *)cupsArrayNext(pclass->users))
+      cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser", name);
 
-    if (pclass->op_policy)
-      cupsFilePrintf(fp, "OpPolicy %s\n", pclass->op_policy);
+     if (pclass->op_policy)
+      cupsFilePutConf(fp, "OpPolicy", pclass->op_policy);
     if (pclass->error_policy)
-      cupsFilePrintf(fp, "ErrorPolicy %s\n", pclass->error_policy);
+      cupsFilePutConf(fp, "ErrorPolicy", pclass->error_policy);
+
+    for (i = pclass->num_options, option = pclass->options;
+         i > 0;
+        i --, option ++)
+    {
+      snprintf(value, sizeof(value), "%s %s", option->name, option->value);
+      cupsFilePutConf(fp, "Option", value);
+    }
 
     cupsFilePuts(fp, "</Class>\n");
   }
 
-  cupsFileClose(fp);
-}
-
-
-/*
- * 'cupsdUpdateImplicitClasses()' - Update the accepting state of implicit
- *                                  classes.
- */
-
-void
-cupsdUpdateImplicitClasses(void)
-{
-  int                  i;              /* Looping var */
-  cupsd_printer_t      *pclass;        /* Current class */
-  int                  accepting;      /* printer-is-accepting-jobs value */
-
-
-  for (pclass = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters);
-       pclass;
-       pclass = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters))
-  {
-   /*
-    * Loop through the printers to come up with a composite state...
-    */
-
-    for (i = 0, accepting = 0; i < pclass->num_printers; i ++)
-      if ((accepting = pclass->printers[i]->accepting) != 0)
-       break;
-
-    pclass->accepting = accepting;
-  }
+  cupsdCloseCreatedConfFile(fp, filename);
 }
 
 
 /*
- * End of "$Id: classes.c 4988 2006-01-26 00:53:00Z mike $".
+ * End of "$Id$".
  */