]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add plist PrintcapFormat support.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Fri, 19 Sep 2008 20:03:36 +0000 (20:03 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Fri, 19 Sep 2008 20:03:36 +0000 (20:03 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@7964 7a7537e8-13f0-0310-91df-b6672ffda945

13 files changed:
CHANGES.txt
config-scripts/cups-defaults.m4
doc/help/ref-cupsd-conf.html.in
man/cupsd.conf.man.in
scheduler/classes.c
scheduler/classes.h
scheduler/conf.c
scheduler/conf.h
scheduler/dirsvc.c
scheduler/ipp.c
scheduler/job.c
scheduler/printers.c
scheduler/printers.h

index 6689e453f7c8e50ffa48e23651ffb58eeeafe4f0..0335971859d705ebb68a7a883e0f279f5cd1d867 100644 (file)
@@ -1,9 +1,10 @@
-CHANGES.txt - 2008-09-18
+CHANGES.txt - 2008-09-19
 ------------------------
 
 CHANGES IN CUPS V1.4b1
 
        - Documentation updates (STR #2567)
+       - The scheduler now supports a plist PrintcapFormat.
        - The scheduler now supports multiple addresses in Allow and
          Deny lines, just like Apache (STR #2947)
        - Added CUPS_JOBTYPE environment variable for job filters so
index 2681389c4708118e8f5c4a22856b26a6122abc10..c7003558b0dfb10121f6034beb81ee288d820227 100644 (file)
@@ -286,7 +286,7 @@ if test x$default_printcap != xno; then
                case $uname in
                        Darwin*)
                                if test $uversion -ge 90; then
-                                       CUPS_DEFAULT_PRINTCAP=""
+                                       CUPS_DEFAULT_PRINTCAP="/Library/Preferences/org.cups.printers.plist"
                                else
                                        CUPS_DEFAULT_PRINTCAP="/etc/printcap"
                                fi
@@ -305,6 +305,7 @@ else
        CUPS_DEFAULT_PRINTCAP=""
 fi
 
+AC_SUBST(CUPS_DEFAULT_PRINTCAP)
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_PRINTCAP, "$CUPS_DEFAULT_PRINTCAP")
 
 dnl Default LPD config file...
index d55119c86e665485fc49979813f3432827f5b800..06111e64666a1b09100b68c19ba1cdc3715c8140 100644 (file)
@@ -2446,6 +2446,7 @@ files as soon as each job is completed, canceled, or aborted.</P>
 Printcap
 Printcap /etc/printcap
 Printcap /etc/printers.conf
+Printcap /Library/Preferences/org.cups.printers.plist
 </PRE>
 
 <H3>Description</H3>
@@ -2454,9 +2455,9 @@ Printcap /etc/printers.conf
 printcap file is automatically generated and updated with a list
 of available printers. If specified with no value, then no
 printcap file will be generated. The default is to generate a
-file named <VAR>/etc/printcap</VAR>.</P>
+file named <VAR>@CUPS_DEFAUL_PRINTCAP@</VAR>.</P>
 
-<P>When a filename is specified (e.g. <VAR>/etc/printcap</VAR>),
+<P>When a filename is specified (e.g. <VAR>@CUPS_DEFAULT_PRINTCAP@</VAR>),
 the printcap file is written whenever a printer is added or
 removed. The printcap file can then be used by applications that
 are hardcoded to look at the printcap file for the available
@@ -2470,13 +2471,14 @@ printers.</P>
 <PRE CLASS="command">
 PrintcapFormat BSD
 PrintcapFormat Solaris
+PrintcapFormat plist
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>PrintcapFormat</CODE> directive controls the output
-format of the printcap file. The default is to generate a BSD
-printcap file.</P>
+<P>The <CODE>PrintcapFormat</CODE> directive controls the output format of the
+printcap file. The default is to generate the plist format on Mac OS X, the
+Solaris format on Solaris, and the BSD format on other operating systems.</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.13</SPAN><A NAME="PrintcapGUI">PrintcapGUI</A></H2>
index 7e523c6db9308f27d906bd01b6033e34b7682091..7b002548010e8fb68fd393eb36258ab671397891 100644 (file)
@@ -545,6 +545,8 @@ disables printcap generation.
 .TP 5
 PrintcapFormat bsd
 .TP 5
+PrintcapFormat plist
+.TP 5
 PrintcapFormat solaris
 .br
 Specifies the format of the printcap file.
index aa6f9d4915b337a5aabbab7956be6111b65b5d2a..822f985f77b16b70c72bab07c68d49a2bca4cd97 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer class routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -18,7 +18,6 @@
  *   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.
@@ -217,24 +216,6 @@ cupsdDeletePrinterFromClasses(
 }
 
 
-/*
- * '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);
-}
-
-
 /*
  * 'cupsdFindAvailablePrinter()' - Find an available printer in a class.
  */
index 8ec7fc681c78e1883bc85c1560ba810e1fb3360e..57f4bc6fdb6f1d58f75a79e42a614f1b2796a1b5 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer class definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -24,7 +24,6 @@ extern void           cupsdAddPrinterToClass(cupsd_printer_t *c,
 extern void            cupsdDeletePrinterFromClass(cupsd_printer_t *c,
                                                    cupsd_printer_t *p);
 extern void            cupsdDeletePrinterFromClasses(cupsd_printer_t *p);
-extern void            cupsdDeleteAllClasses(void);
 extern cupsd_printer_t *cupsdFindAvailablePrinter(const char *name);
 extern cupsd_printer_t *cupsdFindClass(const char *name);
 extern void            cupsdLoadAllClasses(void);
index 6ce7ae55c2b85ff35d466eb8dfe41173fc2c802a..72cf227df4585728909d987c22143d2ae7c81c28 100644 (file)
@@ -454,6 +454,9 @@ cupsdReadConfiguration(void)
 
   if (!strcmp(CUPS_DEFAULT_PRINTCAP, "/etc/printers.conf"))
     PrintcapFormat = PRINTCAP_SOLARIS;
+  else if (!strcmp(CUPS_DEFAULT_PRINTCAP,
+                   "/Library/Preferences/org.cups.printers.plist"))
+    PrintcapFormat = PRINTCAP_PLIST;
   else
     PrintcapFormat = PRINTCAP_BSD;
 
@@ -1165,7 +1168,6 @@ cupsdReadConfiguration(void)
 
     cupsdDeleteAllSubscriptions();
     cupsdFreeAllJobs();
-    cupsdDeleteAllClasses();
     cupsdDeleteAllPrinters();
 
     DefaultPrinter = NULL;
@@ -3158,6 +3160,8 @@ read_configuration(cups_file_t *fp)       /* I - File to read from */
 
       if (!strcasecmp(value, "bsd"))
         PrintcapFormat = PRINTCAP_BSD;
+      else if (!strcasecmp(value, "plist"))
+        PrintcapFormat = PRINTCAP_PLIST;
       else if (!strcasecmp(value, "solaris"))
         PrintcapFormat = PRINTCAP_SOLARIS;
       else
index 6aa971409f76fabbdaf0442cb0c9dedb902b6f1f..d523707d5579178955b06103ebe3253f6ee64e3e 100644 (file)
@@ -64,6 +64,7 @@ typedef enum
 
 #define PRINTCAP_BSD           0       /* Berkeley LPD format */
 #define PRINTCAP_SOLARIS       1       /* Solaris lpsched format */
+#define PRINTCAP_PLIST         2       /* Mac OS X plist format */
 
 
 /*
index a0fac589b865603752b206a93123d6d1ee054006..1c08025a1d7ad9812956449d0dcf84fb59a6ac08 100644 (file)
@@ -473,7 +473,7 @@ cupsdLoadRemoteCache(void)
 
        cupsdSetString(&p->hostname, host);
        cupsdSetString(&p->uri, value);
-       cupsdSetString(&p->device_uri, value);
+       cupsdSetDeviceURI(p, value);
       }
       else
       {
@@ -794,8 +794,7 @@ cupsdSaveRemoteCache(void)
     if (printer->location)
       cupsFilePrintf(fp, "Location %s\n", printer->location);
 
-    if (printer->device_uri)
-      cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
+    cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
 
     if (printer->state == IPP_PRINTER_STOPPED)
     {
index 3436ebefa480aeb9eec402fcd9b552f41f3183cd..693f1261eda3b5f25ddd6f7ed57dc478aa292d91 100644 (file)
@@ -2448,7 +2448,9 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
     * Do we have a valid device URI?
     */
 
-    http_uri_status_t uri_status;      /* URI separation status */
+    http_uri_status_t  uri_status;     /* URI separation status */
+    char               old_device_uri[1024];
+                                       /* Old device URI */
 
 
     need_restart_job = 1;
@@ -2508,15 +2510,19 @@ add_printer(cupsd_client_t  *con,       /* I - Client connection */
       }
     }
 
+    if (printer->sanitized_device_uri)
+      strlcpy(old_device_uri, printer->sanitized_device_uri,
+              sizeof(old_device_uri));
+    else
+      old_device_uri[0] = '\0';
+
+    cupsdSetDeviceURI(printer, attr->values[0].string.text);
+
     cupsdLogMessage(CUPSD_LOG_INFO,
                     "Setting %s device-uri to \"%s\" (was \"%s\".)",
-                   printer->name,
-                   cupsdSanitizeURI(attr->values[0].string.text, line,
-                                    sizeof(line)),
-                   cupsdSanitizeURI(printer->device_uri, resource,
-                                    sizeof(resource)));
+                   printer->name, printer->sanitized_device_uri,
+                   old_device_uri);
 
-    cupsdSetString(&printer->device_uri, attr->values[0].string.text);
     set_device_uri = 1;
   }
 
index 42deea7a7572ba14c0c001d24a3ed5c804616e45..981c373899454873a31beee70c221bc54303ce61 100644 (file)
@@ -2477,7 +2477,6 @@ start_job(cupsd_job_t     *job,           /* I - Job ID */
   int                  filterfds[2][2];/* Pipes used between filters */
   int                  envc;           /* Number of environment variables */
   char                 **argv,         /* Filter command-line arguments */
-                       sani_uri[1024], /* Sanitized DEVICE_URI env var */
                        filename[1024], /* Job filename */
                        command[1024],  /* Full path to command */
                        jobid[255],     /* Job ID string */
@@ -3124,7 +3123,6 @@ start_job(cupsd_job_t     *job,           /* I - Job ID */
            job->filetypes[job->current_file]->type);
   snprintf(device_uri, sizeof(device_uri), "DEVICE_URI=%s",
            printer->device_uri);
-  cupsdSanitizeURI(printer->device_uri, sani_uri, sizeof(sani_uri));
   snprintf(ppd, sizeof(ppd), "PPD=%s/ppd/%s.ppd", ServerRoot, printer->name);
   snprintf(printer_name, sizeof(printer_name), "PRINTER=%s", printer->name);
   snprintf(rip_max_cache, sizeof(rip_max_cache), "RIP_MAX_CACHE=%s", RIPCache);
@@ -3205,7 +3203,7 @@ start_job(cupsd_job_t     *job,           /* I - Job ID */
       cupsdLogJob(job, CUPSD_LOG_DEBUG, "envp[%d]=\"%s\"", i, envp[i]);
     else
       cupsdLogJob(job, CUPSD_LOG_DEBUG, "envp[%d]=\"DEVICE_URI=%s\"", i,
-                  sani_uri);
+                  printer->sanitized_device_uri);
 
   if (printer->remote)
     job->current_file = job->num_files;
@@ -3417,7 +3415,7 @@ start_job(cupsd_job_t     *job,           /* I - Job ID */
       else
         backroot = !(backinfo.st_mode & (S_IRWXG | S_IRWXO));
 
-      argv[0] = sani_uri;
+      argv[0] = printer->sanitized_device_uri;
 
       filterfds[slot][0] = -1;
       filterfds[slot][1] = -1;
index e892d3914949213fcfe504d4cacfd9223197166e..8e2b9f754b8569b12b56b3bc351374b7c7c25b5b 100644 (file)
@@ -27,6 +27,7 @@
  *   cupsdSaveAllPrinters()      - Save all printer definitions to the
  *                                 printers.conf file.
  *   cupsdSetAuthInfoRequired()  - Set the required authentication info.
+ *   cupsdSetDeviceURI()         - Set the device URI for a printer.
  *   cupsdSetPrinterAttr()       - Set a printer attribute.
  *   cupsdSetPrinterAttrs()      - Set printer attributes based upon the PPD
  *                                 file.
@@ -37,7 +38,6 @@
  *   cupsdValidateDest()         - Validate a printer/class destination.
  *   cupsdWritePrintcap()        - Write a pseudo-printcap file for older
  *                                 applications that need it...
- *   cupsdSanitizeURI()          - Sanitize a device URI...
  *   add_printer_defaults()      - Add name-default attributes to the printer
  *                                 attributes.
  *   add_printer_filter()        - Add a MIME filter for a printer.
@@ -49,6 +49,7 @@
  *                                 desktop tools.
  *   write_irix_state()          - Update the status files used by IRIX
  *                                 printing desktop tools.
+ *   write_xml_string()          - Write a string with XML escaping.
  */
 
 /*
@@ -73,6 +74,7 @@ static void   delete_printer_filters(cupsd_printer_t *p);
 static void    write_irix_config(cupsd_printer_t *p);
 static void    write_irix_state(cupsd_printer_t *p);
 #endif /* __sgi */
+static void    write_xml_string(cups_file_t *fp, const char *s);
 
 
 /*
@@ -107,7 +109,7 @@ cupsdAddPrinter(const char *name)   /* I - Name of printer */
   cupsdSetString(&p->hostname, ServerName);
 
   cupsdSetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName, LocalPort, name);
-  cupsdSetStringf(&p->device_uri, "file:/dev/null");
+  cupsdSetDeviceURI(p, "file:/dev/null");
 
   p->state      = IPP_PRINTER_STOPPED;
   p->state_time = time(NULL);
@@ -594,8 +596,7 @@ cupsdDeleteAllPrinters(void)
   for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
        p;
        p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (!(p->type & CUPS_PRINTER_CLASS))
-      cupsdDeletePrinter(p, 0);
+    cupsdDeletePrinter(p, 0);
 }
 
 
@@ -760,6 +761,7 @@ cupsdDeletePrinter(
   cupsdClearString(&p->job_sheets[0]);
   cupsdClearString(&p->job_sheets[1]);
   cupsdClearString(&p->device_uri);
+  cupsdClearString(&p->sanitized_device_uri);
   cupsdClearString(&p->port_monitor);
   cupsdClearString(&p->op_policy);
   cupsdClearString(&p->error_policy);
@@ -934,7 +936,7 @@ cupsdLoadAllPrinters(void)
         cupsdSetPrinterAttrs(p);
        cupsdAddPrinterHistory(p);
 
-        if (p->device_uri && strncmp(p->device_uri, "file:", 5) &&
+        if (strncmp(p->device_uri, "file:", 5) &&
            p->state != IPP_PRINTER_STOPPED)
        {
         /*
@@ -994,7 +996,7 @@ cupsdLoadAllPrinters(void)
     else if (!strcasecmp(line, "DeviceURI"))
     {
       if (value)
-       cupsdSetString(&p->device_uri, value);
+       cupsdSetDeviceURI(p, value);
       else
       {
        cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -1481,8 +1483,7 @@ cupsdSaveAllPrinters(void)
       else
         cupsFilePrintf(fp, "Location %s\n", printer->location);
     }
-    if (printer->device_uri)
-      cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
+    cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
 
     if (printer->port_monitor)
       cupsFilePrintf(fp, "PortMonitor %s\n", printer->port_monitor);
@@ -1827,6 +1828,74 @@ cupsdSetAuthInfoRequired(
 }
 
 
+/*
+ * 'cupsdSetDeviceURI()' - Set the device URI for a printer.
+ */
+
+void
+cupsdSetDeviceURI(cupsd_printer_t *p,  /* I - Printer */
+                  const char      *uri)        /* I - Device URI */
+{
+  char buffer[1024],                   /* URI buffer */
+       *start,                         /* Start of data after scheme */
+       *slash,                         /* First slash after scheme:// */
+       *ptr;                           /* Pointer into user@host:port part */
+
+
+ /*
+  * Set the full device URI..
+  */
+
+  cupsdSetString(&(p->device_uri), uri);
+
+ /*
+  * Copy the device URI to a temporary buffer so we can sanitize any auth
+  * info in it...
+  */
+
+  strlcpy(buffer, uri, sizeof(buffer));
+
+ /*
+  * Find the end of the scheme:// part...
+  */
+
+  if ((ptr = strchr(buffer, ':')) != NULL)
+  {
+    for (start = ptr + 1; *start; start ++)
+      if (*start != '/')
+        break;
+
+   /*
+    * Find the next slash (/) in the URI...
+    */
+
+    if ((slash = strchr(start, '/')) == NULL)
+      slash = start + strlen(start);   /* No slash, point to the end */
+
+   /*
+    * Check for an @ sign before the slash...
+    */
+
+    if ((ptr = strchr(start, '@')) != NULL && ptr < slash)
+    {
+     /*
+      * Found an @ sign and it is before the resource part, so we have
+      * an authentication string.  Copy the remaining URI over the
+      * authentication string...
+      */
+
+      _cups_strcpy(start, ptr + 1);
+    }
+  }
+
+ /*
+  * Save the sanitized URI...
+  */
+
+  cupsdSetString(&(p->sanitized_device_uri), buffer);
+}
+
+
 /*
  * 'cupsdSetPrinterAttr()' - Set a printer attribute.
  */
@@ -1958,7 +2027,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
 {
   int          i,                      /* Looping var */
                length;                 /* Length of browse attributes */
-  char         uri[HTTP_MAX_URI];      /* URI for printer */
   char         resource[HTTP_MAX_URI]; /* Resource portion of URI */
   char         filename[1024];         /* Name of PPD file */
   int          num_air;                /* Number of auth-info-required values */
@@ -2229,31 +2297,11 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
     else
     {
      /*
-      * Add printer-specific attributes...  Start by sanitizing the device
-      * URI so it doesn't have a username or password in it...
+      * Add printer-specific attributes...
       */
 
-      if (!p->device_uri)
-        strcpy(uri, "file:/dev/null");
-      else if (strstr(p->device_uri, "://") != NULL)
-      {
-       /*
-        * http://..., ipp://..., etc.
-       */
-
-        cupsdSanitizeURI(p->device_uri, uri, sizeof(uri));
-      }
-      else
-      {
-       /*
-        * file:..., serial:..., etc.
-       */
-
-        strlcpy(uri, p->device_uri, sizeof(uri));
-      }
-
       ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
-                  uri);
+                  p->sanitized_device_uri);
 
      /*
       * Assign additional attributes from the PPD file (if any)...
@@ -2707,8 +2755,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
                   ServerRoot, p->name);
          add_printer_filter(p, p->filetype, filename);
        }
-       else if (p->device_uri &&
-                !strncmp(p->device_uri, "ipp://", 6) &&
+       else if (!strncmp(p->device_uri, "ipp://", 6) &&
                 (strstr(p->device_uri, "/printers/") != NULL ||
                  strstr(p->device_uri, "/classes/") != NULL))
         {
@@ -2991,6 +3038,9 @@ cupsdSetPrinterReasons(
                *rptr;                  /* Pointer into reason */
 
 
+  if (PrintcapFormat == PRINTCAP_PLIST)
+    cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+
   if (s[0] == '-' || s[0] == '+')
   {
    /*
@@ -3008,7 +3058,7 @@ cupsdSetPrinterReasons(
     sptr = s;
 
     for (i = 0; i < p->num_reasons; i ++)
-      free(p->reasons[i]);
+      _cupsStrFree(p->reasons[i]);
 
     p->num_reasons = 0;
   }
@@ -3076,7 +3126,7 @@ cupsdSetPrinterReasons(
 
       if (i >= p->num_reasons)
       {
-        p->reasons[i] = strdup(reason);
+        p->reasons[i] = _cupsStrAlloc(reason);
        p->num_reasons ++;
 
        if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED)
@@ -3111,6 +3161,9 @@ cupsdSetPrinterState(
   * Set the new state...
   */
 
+  if (PrintcapFormat == PRINTCAP_PLIST)
+    cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
+
   old_state = p->state;
   p->state  = s;
 
@@ -3542,7 +3595,8 @@ cupsdValidateDest(
 void
 cupsdWritePrintcap(void)
 {
-  cups_file_t          *fp;            /* printcap file */
+  int                  i;              /* Looping var */
+  cups_file_t          *fp;            /* Printcap file */
   cupsd_printer_t      *p;             /* Current printer */
 
 
@@ -3575,11 +3629,11 @@ cupsdWritePrintcap(void)
   * data has come from...
   */
 
-  cupsFilePuts(fp,
-               "# This file was automatically generated by cupsd(8) from the\n");
-  cupsFilePrintf(fp, "# %s/printers.conf file.  All changes to this file\n",
-                 ServerRoot);
-  cupsFilePuts(fp, "# will be lost.\n");
+  if (PrintcapFormat != PRINTCAP_PLIST)
+    cupsFilePrintf(fp, "# This file was automatically generated by cupsd(8) "
+                       "from the\n"
+                       "# %s/printers.conf file.  All changes to this file\n"
+                      "# will be lost.\n", ServerRoot);
 
   if (Printers)
   {
@@ -3589,7 +3643,7 @@ cupsdWritePrintcap(void)
 
     switch (PrintcapFormat)
     {
-      case PRINTCAP_BSD:
+      case PRINTCAP_BSD :
         /*
           * Each printer is put in the file as:
          *
@@ -3613,7 +3667,68 @@ cupsdWritePrintcap(void)
                             ServerName, p->name);
           break;
 
-      case PRINTCAP_SOLARIS:
+      case PRINTCAP_PLIST :
+         /*
+         * Each printer is written as a dictionary in a plist file.
+         * Currently the printer-name, printer-info, printer-is-accepting-jobs,
+         * printer-location, printer-make-and-model, printer-state,
+         * printer-state-reasons, printer-type, and (sanitized) device-uri.
+         */
+
+          cupsFilePuts(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                          "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD "
+                          "PLIST 1.0//EN\" \"http://www.apple.com/DTDs/"
+                          "PropertyList-1.0.dtd\">\n"
+                          "<plist version=\"1.0\">\n"
+                          "<array>\n");
+
+         for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+              p;
+              p = (cupsd_printer_t *)cupsArrayNext(Printers))
+          {
+           cupsFilePuts(fp, "\t<dict>\n"
+                            "\t\t<key>printer-name</key>\n"
+                            "\t\t<string>");
+            write_xml_string(fp, p->name);
+           cupsFilePuts(fp, "</string>\n"
+                            "\t\t<key>printer-info</key>\n"
+                            "\t\t<string>");
+            write_xml_string(fp, p->info);
+           cupsFilePrintf(fp, "</string>\n"
+                              "\t\t<key>printer-is-accepting-jobs</key>\n"
+                              "\t\t<%s/>\n"
+                              "\t\t<key>printer-location</key>\n"
+                              "\t\t<string>", p->accepting ? "true" : "false");
+            write_xml_string(fp, p->location);
+           cupsFilePuts(fp, "</string>\n"
+                            "\t\t<key>printer-make-and-model</key>\n"
+                            "\t\t<string>");
+            write_xml_string(fp, p->make_model);
+           cupsFilePrintf(fp, "</string>\n"
+                              "\t\t<key>printer-state</key>\n"
+                              "\t\t<integer>%d</integer>\n"
+                              "\t\t<key>printer-state-reasons</key>\n"
+                              "\t\t<array>\n", p->state);
+            for (i = 0; i < p->num_reasons; i ++)
+           {
+             cupsFilePuts(fp, "\t\t\t<string>");
+             write_xml_string(fp, p->reasons[i]);
+             cupsFilePuts(fp, "</string>\n");
+           }
+           cupsFilePrintf(fp, "\t\t</array>\n"
+                              "\t\t<key>printer-type</key>\n"
+                              "\t\t<integer>%d</integer>\n"
+                              "\t\t<key>device-uri</key>\n"
+                              "\t\t<string>", p->type);
+            write_xml_string(fp, p->sanitized_device_uri);
+           cupsFilePuts(fp, "</string>\n"
+                            "\t</dict>\n");
+          }
+         cupsFilePuts(fp, "</array>\n"
+                          "</plist>\n");
+         break;
+
+      case PRINTCAP_SOLARIS :
         /*
           * Each printer is put in the file as:
          *
@@ -3664,74 +3779,6 @@ cupsdWritePrintcap(void)
 }
 
 
-/*
- * 'cupsdSanitizeURI()' - Sanitize a device URI...
- */
-
-char *                                 /* O - New device URI */
-cupsdSanitizeURI(const char *uri,      /* I - Original device URI */
-                 char       *buffer,   /* O - New device URI */
-                 int        buflen)    /* I - Size of new device URI buffer */
-{
-  char *start,                         /* Start of data after scheme */
-       *slash,                         /* First slash after scheme:// */
-       *ptr;                           /* Pointer into user@host:port part */
-
-
- /*
-  * Range check input...
-  */
-
-  if (!uri || !buffer || buflen < 2)
-    return (NULL);
-
- /*
-  * Copy the device URI to the new buffer...
-  */
-
-  strlcpy(buffer, uri, buflen);
-
- /*
-  * Find the end of the scheme:// part...
-  */
-
-  if ((ptr = strchr(buffer, ':')) == NULL)
-    return (buffer);                   /* No scheme: part... */
-
-  for (start = ptr + 1; *start; start ++)
-    if (*start != '/')
-      break;
-
- /*
-  * Find the next slash (/) in the URI...
-  */
-
-  if ((slash = strchr(start, '/')) == NULL)
-    slash = start + strlen(start);     /* No slash, point to the end */
-
- /*
-  * Check for an @ sign before the slash...
-  */
-
-  if ((ptr = strchr(start, '@')) != NULL && ptr < slash)
-  {
-   /*
-    * Found an @ sign and it is before the resource part, so we have
-    * an authentication string.  Copy the remaining URI over the
-    * authentication string...
-    */
-
-    _cups_strcpy(start, ptr + 1);
-  }
-
- /*
-  * Return the new device URI...
-  */
-
-  return (buffer);
-}
-
-
 /*
  * 'add_printer_defaults()' - Add name-default attributes to the printer attributes.
  */
@@ -4224,7 +4271,7 @@ write_irix_config(cupsd_printer_t *p)     /* I - Printer to update */
     cupsFilePrintf(fp, "Printer Model      | %s\n", p->make_model ? p->make_model : "");
     cupsFilePrintf(fp, "Location Code      | %s\n", p->location ? p->location : "");
     cupsFilePrintf(fp, "Physical Location  | %s\n", p->info ? p->info : "");
-    cupsFilePrintf(fp, "Port Path          | %s\n", p->device_uri ? p->device_uri : "");
+    cupsFilePrintf(fp, "Port Path          | %s\n", p->device_uri);
     cupsFilePrintf(fp, "Config Path        | /var/spool/lp/pod/%s.config\n", p->name);
     cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
     cupsFilePuts(fp, "Status Update Wait | 10 seconds\n");
@@ -4269,7 +4316,7 @@ write_irix_state(cupsd_printer_t *p)      /* I - Printer to update */
                                                      "Faulted");
       cupsFilePrintf(fp, "Information        | 01 00 00 | %s\n", CUPS_SVERSION);
       cupsFilePrintf(fp, "Information        | 02 00 00 | Device URI: %s\n",
-              p->device_uri ? p->device_uri : "");
+              p->device_uri);
       cupsFilePrintf(fp, "Information        | 03 00 00 | %s jobs\n",
               p->accepting ? "Accepting" : "Not accepting");
       cupsFilePrintf(fp, "Information        | 04 00 00 | %s\n", p->state_message);
@@ -4366,6 +4413,45 @@ write_irix_state(cupsd_printer_t *p)     /* I - Printer to update */
 #endif /* __sgi */
 
 
+/*
+ * 'write_xml_string()' - Write a string with XML escaping.
+ */
+
+static void
+write_xml_string(cups_file_t *fp,      /* I - File to write to */
+                 const char  *s)       /* I - String to write */
+{
+  const char   *start;                 /* Start of current sequence */
+
+
+  if (!s)
+    return;
+
+  for (start = s; *s; s ++)
+  {
+    if (*s == '&')
+    {
+      if (s > start)
+        cupsFileWrite(fp, start, s - start);
+
+      cupsFilePuts(fp, "&amp;");
+      start = s + 1;
+    }
+    else if (*s == '<')
+    {
+      if (s > start)
+        cupsFileWrite(fp, start, s - start);
+
+      cupsFilePuts(fp, "&lt;");
+      start = s + 1;
+    }
+  }
+
+  if (s > start)
+    cupsFilePuts(fp, start);
+}
+
+
 /*
  * End of "$Id$".
  */
index 4feb1d88a5f930fcf41b85d7ddd27a596d191b8c..3f76edc722e011144aae0bbe221c1ea3f25e4d72 100644 (file)
@@ -59,6 +59,7 @@ typedef struct cupsd_printer_s
   time_t       browse_expire;          /* Expiration time for printer */
   time_t       browse_time;            /* Last time update was sent/received */
   char         *device_uri;            /* Device URI */
+  char         *sanitized_device_uri;  /* Sanitized device URI */
   char         *port_monitor;          /* Port monitor */
   int          raw;                    /* Raw queue? */
   int          remote;                 /* Remote queue? */
@@ -153,6 +154,7 @@ extern void         cupsdSaveAllPrinters(void);
 extern int             cupsdSetAuthInfoRequired(cupsd_printer_t *p,
                                                 const char *values,
                                                 ipp_attribute_t *attr);
+extern void            cupsdSetDeviceURI(cupsd_printer_t *p, const char *uri);
 extern void            cupsdSetPrinterAttr(cupsd_printer_t *p,
                                            const char *name, char *value);
 extern void            cupsdSetPrinterAttrs(cupsd_printer_t *p);