]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cups/dest.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / dest.c
index a91e398473d7c2895d951b423b838fdf9682b976..240ebae8f8a44441c92d5599f452bdc2ed614489 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * "$Id: dest.c 5346 2006-03-28 16:05:19Z mike $"
+ * "$Id: dest.c 6265 2007-02-11 19:42:42Z mike $"
  *
  *   User-defined destination (and option) support for the Common UNIX
  *   Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Easy Software Products and are protected by Federal
  *
  * Contents:
  *
- *   cupsAddDest()     - Add a destination to the list of destinations.
- *   cupsFreeDests()   - Free the memory used by the list of destinations.
- *   cupsGetDest()     - Get the named destination from the list.
- *   cupsGetDests()    - Get the list of destinations from the default server.
- *   cupsGetDests2()   - Get the list of destinations from the specified server.
- *   cupsSetDests()    - Set the list of destinations for the default server.
- *   cupsSetDests2()   - Set the list of destinations for the specified server.
- *   cups_get_dests()  - Get destinations from a file.
- *   cups_get_sdests() - Get destinations from a server.
+ *   cupsAddDest()            - Add a destination to the list of destinations.
+ *   cupsFreeDests()          - Free the memory used by the list of
+ *                              destinations.
+ *   cupsGetDest()            - Get the named destination from the list.
+ *   cupsGetDests()           - Get the list of destinations from the default
+ *                              server.
+ *   cupsGetDests2()          - Get the list of destinations from the
+ *                              specified server.
+ *   cupsRemoveDest()         - Remove a destination from the destination list.
+ *   cupsDestSetDefaultDest() - Set the default destination.
+ *   cupsSetDests()           - Set the list of destinations for the default
+ *                              server.
+ *   cupsSetDests2()          - Set the list of destinations for the specified
+ *                              server.
+ *   cups_get_dests()         - Get destinations from a file.
+ *   cups_get_sdests()        - Get destinations from a server.
  */
 
 /*
@@ -64,21 +71,31 @@ static int  cups_get_sdests(http_t *http, ipp_op_t op, int num_dests,
 /*
  * 'cupsAddDest()' - Add a destination to the list of destinations.
  *
- * Use the cupsSaveDests() function to save the updated list of destinations
- * to the user's lpoptions file.
+ * This function cannot be used to add a new class or printer queue,
+ * it only adds a new container of saved options for the named
+ * destination or instance.
+ *
+ * If the named destination already exists, the destination list is
+ * returned unchanged.  Adding a new instance of a destination creates
+ * a copy of that destination's options.
+ *
+ * Use the cupsSaveDests() function to save the updated list of
+ * destinations to the user's lpoptions file.
  */
 
 int                                    /* O  - New number of destinations */
-cupsAddDest(const char  *name,         /* I  - Name of destination */
-            const char *instance,      /* I  - Instance of destination or NULL for none/primary */
+cupsAddDest(const char  *name,         /* I  - Destination name */
+            const char *instance,      /* I  - Instance name or NULL for none/primary */
             int         num_dests,     /* I  - Number of destinations */
             cups_dest_t **dests)       /* IO - Destinations */
 {
   int          i;                      /* Looping var */
   cups_dest_t  *dest;                  /* Destination pointer */
+  cups_dest_t  *parent;                /* Parent destination */
+  cups_option_t        *option;                /* Current option */
 
 
-  if (name == NULL || dests == NULL)
+  if (!name || !dests)
     return (0);
 
   if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
@@ -98,27 +115,53 @@ cupsAddDest(const char  *name,             /* I  - Name of destination */
 
   *dests = dest;
 
+ /*
+  * Find where to insert the destination...
+  */
+
   for (i = num_dests; i > 0; i --, dest ++)
     if (strcasecmp(name, dest->name) < 0)
       break;
+    else if (!instance && dest->instance)
+      break;
     else if (!strcasecmp(name, dest->name) &&
-             instance != NULL && dest->instance != NULL &&
+             instance  && dest->instance &&
              strcasecmp(instance, dest->instance) < 0)
       break;
 
   if (i > 0)
     memmove(dest + 1, dest, i * sizeof(cups_dest_t));
 
+ /*
+  * Initialize the destination...
+  */
+
   dest->name        = strdup(name);
   dest->is_default  = 0;
   dest->num_options = 0;
   dest->options     = (cups_option_t *)0;
 
-  if (instance == NULL)
+  if (!instance)
     dest->instance = NULL;
   else
+  {
+   /*
+    * Copy options from the primary instance...
+    */
+
     dest->instance = strdup(instance);
 
+    if ((parent = cupsGetDest(name, NULL, num_dests + 1, *dests)) != NULL)
+    {
+      for (i = parent->num_options, option = parent->options;
+           i > 0;
+          i --, option ++)
+       dest->num_options = cupsAddOption(option->name, option->value,
+                                         dest->num_options,
+                                         &(dest->options));
+    }
+  }
+
   return (num_dests + 1);
 }
 
@@ -160,18 +203,18 @@ cupsFreeDests(int         num_dests,      /* I - Number of destinations */
  */
 
 cups_dest_t *                          /* O - Destination pointer or NULL */
-cupsGetDest(const char  *name,         /* I - Name of destination */
-            const char *instance,      /* I - Instance of destination */
+cupsGetDest(const char  *name,         /* I - Destination name or NULL for the default destination */
+            const char *instance,      /* I - Instance name or NULL */
             int         num_dests,     /* I - Number of destinations */
             cups_dest_t *dests)                /* I - Destinations */
 {
   int  comp;                           /* Result of comparison */
 
 
-  if (num_dests == 0 || dests == NULL)
+  if (num_dests <= 0 || !dests)
     return (NULL);
 
-  if (name == NULL)
+  if (!name)
   {
    /*
     * NULL name for default printer.
@@ -198,9 +241,9 @@ cupsGetDest(const char  *name,              /* I - Name of destination */
        return (NULL);
       else if (comp == 0)
       {
-       if ((instance == NULL && dests->instance == NULL) ||
+       if ((!instance && !dests->instance) ||
             (instance != NULL && dests->instance != NULL &&
-            strcasecmp(instance, dests->instance) == 0))
+            !strcasecmp(instance, dests->instance)))
          return (dests);
       }
 
@@ -220,6 +263,9 @@ cupsGetDest(const char  *name,              /* I - Name of destination */
  * printer-info, printer-is-accepting-jobs, printer-is-shared,
  * printer-make-and-model, printer-state, printer-state-change-time,
  * printer-state-reasons, and printer-type attributes as options.
+ *
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
  */
 
 int                                    /* O - Number of destinations */
@@ -252,6 +298,9 @@ cupsGetDests(cups_dest_t **dests)   /* O - Destinations */
  * printer-make-and-model, printer-state, printer-state-change-time,
  * printer-state-reasons, and printer-type attributes as options.
  *
+ * Use the cupsFreeDests() function to free the destination list and
+ * the cupsGetDest() function to find a particular destination.
+ *
  * @since CUPS 1.1.21@
  */
 
@@ -411,6 +460,92 @@ cupsGetDests2(http_t      *http,   /* I - HTTP connection */
 }
 
 
+/*
+ * 'cupsRemoveDest()' - Remove a destination from the destination list.
+ *
+ * Removing a destination/instance does not delete the class or printer
+ * queue, merely the lpoptions for that destination/instance.  Use the
+ * cupsSetDests() or cupsSetDests2() functions to save the new options
+ * for the user.
+ *
+ * @since CUPS 1.3@
+ */
+
+int                                    /* O  - New number of destinations */
+cupsRemoveDest(const char  *name,      /* I  - Destination name */
+               const char  *instance,  /* I  - Instance name or NULL */
+              int         num_dests,   /* I  - Number of destinations */
+              cups_dest_t **dests)     /* IO - Destinations */
+{
+  int          i;                      /* Index into destinations */
+  cups_dest_t  *dest;                  /* Pointer to destination */
+
+
+ /*
+  * Find the destination...
+  */
+
+  if ((dest = cupsGetDest(name, instance, num_dests, *dests)) == NULL)
+    return (num_dests);
+
+ /*
+  * Free memory...
+  */
+
+  cupsFreeOptions(dest->num_options, dest->options);
+
+ /*
+  * Remove the destination from the array...
+  */
+
+  num_dests --;
+
+  i = dest - *dests;
+
+  if (i < num_dests)
+    memmove(dest, dest + 1, (num_dests - i) * sizeof(cups_dest_t));
+
+  return (num_dests);
+}
+
+
+/*
+ * 'cupsDestSetDefaultDest()' - Set the default destination.
+ *
+ * @since CUPS 1.3@
+ */
+
+void
+cupsSetDefaultDest(
+    const char  *name,                 /* I - Destination name */
+    const char  *instance,             /* I - Instance name or NULL */
+    int         num_dests,             /* I - Number of destinations */
+    cups_dest_t *dests)                        /* I - Destinations */
+{
+  int          i;                      /* Looping var */
+  cups_dest_t  *dest;                  /* Current destination */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!name || num_dests <= 0 || !dests)
+    return;
+
+ /*
+  * Loop through the array and set the "is_default" flag for the matching
+  * destination...
+  */
+
+  for (i = num_dests, dest = dests; i > 0; i --, dest ++)
+    dest->is_default = !strcasecmp(name, dest->name) &&
+                       ((!instance && !dest->instance) ||
+                       (instance && dest->instance &&
+                        !strcasecmp(instance, dest->instance)));
+}
+
+
 /*
  * 'cupsSetDests()' - Save the list of destinations for the default server.
  *
@@ -456,8 +591,11 @@ cupsSetDests2(http_t      *http,   /* I - HTTP connection */
   int          wrote;                  /* Wrote definition? */
   cups_dest_t  *dest;                  /* Current destination */
   cups_option_t        *option;                /* Current option */
+  _ipp_option_t        *match;                 /* Matching attribute for option */
   FILE         *fp;                    /* File pointer */
+#ifndef WIN32
   const char   *home;                  /* HOME environment variable */
+#endif /* WIN32 */
   char         filename[1024];         /* lpoptions file */
   int          num_temps;              /* Number of temporary destinations */
   cups_dest_t  *temps,                 /* Temporary destinations */
@@ -567,17 +705,24 @@ cupsSetDests2(http_t      *http,  /* I - HTTP connection */
 
       for (j = dest->num_options, option = dest->options; j > 0; j --, option ++)
       {
+       /*
+        * See if this option is a printer attribute; if so, skip it...
+       */
+
+        if ((match = _ippFindOption(option->name)) != NULL &&
+           match->group_tag == IPP_TAG_PRINTER)
+         continue;
+
        /*
        * See if the server/global options match these; if so, don't
        * write 'em.
        */
 
-        if (temp && (val = cupsGetOption(option->name, temp->num_options,
-                                        temp->options)) != NULL)
-       {
-         if (!strcasecmp(val, option->value))
-           continue;
-       }
+        if (temp &&
+           (val = cupsGetOption(option->name, temp->num_options,
+                                temp->options)) != NULL &&
+            !strcasecmp(val, option->value))
+         continue;
 
        /*
         * Options don't match, write to the file...
@@ -593,10 +738,35 @@ cupsSetDests2(http_t      *http,  /* I - HTTP connection */
         
         if (option->value[0])
        {
-         if (strchr(option->value, ' ') != NULL)
-           fprintf(fp, " %s=\"%s\"", option->name, option->value);
-          else
+         if (strchr(option->value, ' ') ||
+             strchr(option->value, '\\') ||
+             strchr(option->value, '\"') ||
+             strchr(option->value, '\''))
+         {
+          /*
+           * Quote the value...
+           */
+
+           fprintf(fp, " %s=\"", option->name);
+
+           for (val = option->value; *val; val ++)
+           {
+             if (strchr("\"\'\\", *val))
+               putc('\\', fp);
+
+              putc(*val, fp);
+           }
+
+           putc('\"', fp);
+          }
+         else
+         {
+          /*
+           * Store the literal value...
+           */
+
            fprintf(fp, " %s=%s", option->name, option->value);
+          }
        }
        else
          fprintf(fp, " %s", option->name);
@@ -802,10 +972,13 @@ cups_get_sdests(http_t      *http,        /* I - HTTP connection */
   const char   *info,                  /* printer-info attribute */
                *make_model,            /* printer-make-and-model attribute */
                *name;                  /* printer-name attribute */
-  char         job_sheets[1024],       /* job-sheets option */
-               reasons[1024],          /* printer-state-reasons attribute */
-               *rptr,                  /* Pointer into reasons string */
-               temp[255];              /* Temporary string for numbers */
+  char         job_sheets[1024],       /* job-sheets-default attribute */
+               reasons[1024];          /* printer-state-reasons attribute */
+  int          num_options;            /* Number of options */
+  cups_option_t        *options;               /* Options */
+  char         optname[1024],          /* Option name */
+               value[2048],            /* Option value */
+               *ptr;                   /* Pointer into name/value */
   static const char * const pattrs[] = /* Attributes we're interested in */
                {
                  "job-sheets-default",
@@ -817,7 +990,8 @@ cups_get_sdests(http_t      *http,  /* I - HTTP connection */
                  "printer-state",
                  "printer-state-change-time",
                  "printer-state-reasons",
-                 "printer-type"
+                 "printer-type",
+                 "printer-defaults"
                };
 
 
@@ -858,7 +1032,7 @@ cups_get_sdests(http_t      *http, /* I - HTTP connection */
         break;
 
      /*
-      * Pull the needed attributes from this job...
+      * Pull the needed attributes from this printer...
       */
 
       accepting   = 0;
@@ -866,6 +1040,8 @@ cups_get_sdests(http_t      *http, /* I - HTTP connection */
       info        = NULL;
       make_model  = NULL;
       name        = NULL;
+      num_options = 0;
+      options     = NULL;
       shared      = 1;
       state       = IPP_PRINTER_IDLE;
       type        = CUPS_PRINTER_LOCAL;
@@ -911,18 +1087,92 @@ cups_get_sdests(http_t      *http,       /* I - HTTP connection */
                 attr->value_tag == IPP_TAG_KEYWORD)
        {
          strlcpy(reasons, attr->values[0].string.text, sizeof(reasons));
-         for (i = 1, rptr = reasons + strlen(reasons);
+         for (i = 1, ptr = reasons + strlen(reasons);
               i < attr->num_values;
               i ++)
          {
-           snprintf(rptr, sizeof(reasons) - (rptr - reasons), ",%s",
+           snprintf(ptr, sizeof(reasons) - (ptr - reasons), ",%s",
                     attr->values[i].string.text);
-           rptr += strlen(rptr);
+           ptr += strlen(ptr);
          }
        }
        else if (!strcmp(attr->name, "printer-type") &&
                 attr->value_tag == IPP_TAG_ENUM)
           type = attr->values[0].integer;
+        else if (strncmp(attr->name, "notify-", 7) &&
+                (attr->value_tag == IPP_TAG_BOOLEAN ||
+                 attr->value_tag == IPP_TAG_ENUM ||
+                 attr->value_tag == IPP_TAG_INTEGER ||
+                 attr->value_tag == IPP_TAG_KEYWORD ||
+                 attr->value_tag == IPP_TAG_NAME ||
+                 attr->value_tag == IPP_TAG_RANGE) &&
+                strstr(attr->name, "-default"))
+       {
+         char  *valptr;                /* Pointer into attribute value */
+
+
+        /*
+         * Add a default option...
+         */
+
+          strlcpy(optname, attr->name, sizeof(optname));
+         if ((ptr = strstr(optname, "-default")) != NULL)
+           *ptr = '\0';
+
+          value[0] = '\0';
+         for (i = 0, ptr = value; i < attr->num_values; i ++)
+         {
+           if (ptr >= (value + sizeof(value) - 1))
+             break;
+
+            if (i)
+             *ptr++ = ',';
+
+            switch (attr->value_tag)
+           {
+             case IPP_TAG_INTEGER :
+             case IPP_TAG_ENUM :
+                 snprintf(ptr, sizeof(value) - (ptr - value), "%d",
+                          attr->values[i].integer);
+                 break;
+
+             case IPP_TAG_BOOLEAN :
+                 if (attr->values[i].boolean)
+                   strlcpy(ptr, "true", sizeof(value) - (ptr - value));
+                 else
+                   strlcpy(ptr, "false", sizeof(value) - (ptr - value));
+                 break;
+
+             case IPP_TAG_RANGE :
+                 if (attr->values[i].range.lower ==
+                         attr->values[i].range.upper)
+                   snprintf(ptr, sizeof(value) - (ptr - value), "%d",
+                            attr->values[i].range.lower);
+                 else
+                   snprintf(ptr, sizeof(value) - (ptr - value), "%d-%d",
+                            attr->values[i].range.lower,
+                            attr->values[i].range.upper);
+                 break;
+
+             default :
+                 for (valptr = attr->values[i].string.text;
+                      *valptr && ptr < (value + sizeof(value) - 2);)
+                 {
+                   if (strchr(" \t\n\\\'\"", *valptr))
+                     *ptr++ = '\\';
+
+                   *ptr++ = *valptr++;
+                 }
+
+                 *ptr = '\0';
+                 break;
+           }
+
+           ptr += strlen(ptr);
+          }
+
+         num_options = cupsAddOption(optname, value, num_options, &options);
+       }
 
         attr = attr->next;
       }
@@ -933,6 +1183,8 @@ cups_get_sdests(http_t      *http, /* I - HTTP connection */
 
       if (!name)
       {
+        cupsFreeOptions(num_options, options);
+
         if (attr == NULL)
          break;
        else
@@ -943,6 +1195,12 @@ cups_get_sdests(http_t      *http,        /* I - HTTP connection */
 
       if ((dest = cupsGetDest(name, NULL, num_dests, *dests)) != NULL)
       {
+        dest->num_options = num_options;
+       dest->options     = options;
+
+        num_options = 0;
+       options     = NULL;
+
         if (job_sheets[0])
           dest->num_options = cupsAddOption("job-sheets", job_sheets,
                                            dest->num_options,
@@ -953,13 +1211,13 @@ cups_get_sdests(http_t      *http,       /* I - HTTP connection */
                                            dest->num_options,
                                            &(dest->options));
 
-        sprintf(temp, "%d", accepting);
-       dest->num_options = cupsAddOption("printer-is-accepting-jobs", temp,
+        sprintf(value, "%d", accepting);
+       dest->num_options = cupsAddOption("printer-is-accepting-jobs", value,
                                          dest->num_options,
                                          &(dest->options));
 
-        sprintf(temp, "%d", shared);
-       dest->num_options = cupsAddOption("printer-is-shared", temp,
+        sprintf(value, "%d", shared);
+       dest->num_options = cupsAddOption("printer-is-shared", value,
                                          dest->num_options,
                                          &(dest->options));
 
@@ -968,15 +1226,15 @@ cups_get_sdests(http_t      *http,       /* I - HTTP connection */
                                            make_model, dest->num_options,
                                            &(dest->options));
 
-        sprintf(temp, "%d", state);
-       dest->num_options = cupsAddOption("printer-state", temp,
+        sprintf(value, "%d", state);
+       dest->num_options = cupsAddOption("printer-state", value,
                                          dest->num_options,
                                          &(dest->options));
 
         if (change_time)
        {
-         sprintf(temp, "%d", change_time);
-         dest->num_options = cupsAddOption("printer-state-change-time", temp,
+         sprintf(value, "%d", change_time);
+         dest->num_options = cupsAddOption("printer-state-change-time", value,
                                            dest->num_options,
                                            &(dest->options));
         }
@@ -986,12 +1244,14 @@ cups_get_sdests(http_t      *http,       /* I - HTTP connection */
                                            dest->num_options,
                                            &(dest->options));
 
-        sprintf(temp, "%d", type);
-       dest->num_options = cupsAddOption("printer-type", temp,
+        sprintf(value, "%d", type);
+       dest->num_options = cupsAddOption("printer-type", value,
                                          dest->num_options,
                                          &(dest->options));
       }
 
+      cupsFreeOptions(num_options, options);
+
       if (attr == NULL)
        break;
     }
@@ -1008,5 +1268,5 @@ cups_get_sdests(http_t      *http,        /* I - HTTP connection */
 
 
 /*
- * End of "$Id: dest.c 5346 2006-03-28 16:05:19Z mike $".
+ * End of "$Id: dest.c 6265 2007-02-11 19:42:42Z mike $".
  */