]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Re-implement cupsGetDests and cupsCreateJob using cupsEnumDests (Issue #4993)
authorMichael Sweet <michael.r.sweet@gmail.com>
Wed, 17 May 2017 16:18:22 +0000 (12:18 -0400)
committerMichael Sweet <michael.r.sweet@gmail.com>
Wed, 17 May 2017 16:18:22 +0000 (12:18 -0400)
CHANGES.md
cups/dest-job.c
cups/dest-options.c
cups/dest.c
cups/util.c
test/run-stp-tests.sh

index 208bc00f22d4bb06959ca577d5573fa3c9760923..3e0d9d8a41a600fbc9ff097b1b91979c3485b79a 100644 (file)
@@ -1,4 +1,4 @@
-CHANGES - 2.2.4 - 2017-05-16
+CHANGES - 2.2.4 - 2017-05-17
 ============================
 
 CHANGES IN CUPS V2.2.4
@@ -11,6 +11,8 @@ CHANGES IN CUPS V2.2.4
 - Added a new CUPS Programming Manual to replace the aging API documentation.
 - Added the cupsAddIntegerOption and cupsGetIntegerOption functions
   (Issue #4992)
+- The cupsGetDests and cupsCreateJob functions now support Bonjour printers
+  (Issue #4993)
 - IPP Everywhere improvements (Issue #4998)
 - Fixed the "cancel all jobs" function in the web interface for several
   languages (Issue #4999)
index b0d89b6e7b4506c529d96142f3dac642451c1a64..9fc0bdb9a40b76f8388532eb3a4c62d33b13f93b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Destination job support for CUPS.
  *
- * Copyright 2012-2016 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Apple Inc. and are protected by Federal copyright
@@ -83,6 +83,13 @@ cupsCloseDestJob(
 
   DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id));
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -171,6 +178,13 @@ cupsCreateDestJob(
   DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
                 "job_id=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options));
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -251,6 +265,13 @@ cupsFinishDestDocument(
 {
   DEBUG_printf(("cupsFinishDestDocument(http=%p, dest=%p(%s/%s), info=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info));
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -306,6 +327,13 @@ cupsStartDestDocument(
 
   DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, options=%p, last_document=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id, docname, format, num_options, (void *)options, last_document));
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
index bf9020bac6e31eb0fb0b86fca5674ead69961fa7..2832055a46e98b8685013f21a9ae99095d23d99e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Destination option/media support for CUPS.
  *
- * Copyright 2012-2016 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
  *
  * These coded instructions, statements, and computer programs are the
  * property of Apple Inc. and are protected by Federal copyright
@@ -85,6 +85,13 @@ cupsCheckDestSupported(
   _ipp_value_t         *attrval;       /* Current attribute value */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -315,6 +322,13 @@ cupsCopyDestConflicts(
   if (resolved)
     *resolved = NULL;
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -574,6 +588,13 @@ cupsCopyDestInfo(
 
   DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -685,6 +706,13 @@ cupsFindDestDefault(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -726,6 +754,13 @@ cupsFindDestReady(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -769,6 +804,13 @@ cupsFindDestSupported(
   char name[IPP_MAX_NAME];             /* Attribute name */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -851,6 +893,13 @@ cupsGetDestMediaByIndex(
   pwg_media_t          *pwg;           /* PWG media name for size */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -939,6 +988,13 @@ cupsGetDestMediaByName(
   pwg_media_t          *pwg;           /* PWG media info */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1007,6 +1063,13 @@ cupsGetDestMediaBySize(
   pwg_media_t          *pwg;           /* PWG media info */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1058,6 +1121,13 @@ cupsGetDestMediaCount(
     cups_dinfo_t *dinfo,               /* I - Destination information */
     unsigned     flags)                        /* I - Media flags */
 {
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
@@ -1103,6 +1173,13 @@ cupsGetDestMediaDefault(
   const char   *media;                 /* Default media size */
 
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * Range check input...
   */
index e6fc66b38bfa49d8ba24ae294e290313813f9398..e30396b73bee006a3b68d80ed3aa8e6a0a566757 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User-defined destination (and option) support for CUPS.
  *
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
  * Copyright 1997-2007 by Easy Software Products.
  *
  * These coded instructions, statements, and computer programs are the
@@ -121,6 +121,13 @@ typedef struct _cups_dnssd_resolve_s       /* Data for resolving URI */
 #endif /* HAVE_DNSSD */
 
 
+typedef struct _cups_getdata_s
+{
+  int         num_dests;                /* Number of destinations */
+  cups_dest_t *dests;                   /* Destinations */
+} _cups_getdata_t;
+
+
 /*
  * Local functions...
  */
@@ -218,6 +225,7 @@ static int          cups_elapsed(struct timeval *t);
 static int             cups_find_dest(const char *name, const char *instance,
                                       int num_dests, cups_dest_t *dests, int prev,
                                       int *rdiff);
+static int              cups_get_cb(_cups_getdata_t *data, unsigned flags, cups_dest_t *dest);
 static char            *cups_get_default(const char *filename, char *namebuf,
                                          size_t namesize, const char **instance);
 static int             cups_get_dests(const char *filename, const char *match_name,
@@ -1433,6 +1441,8 @@ _cupsGetDestResource(
   int          port;                   /* Port number */
 
 
+  DEBUG_printf(("_cupsGetDestResource(dest=%p(%s), resource=%p, resourcesize=%d)", dest, dest->name, resource, (int)resourcesize));
+
  /*
   * Range check input...
   */
@@ -1453,6 +1463,8 @@ _cupsGetDestResource(
   if ((uri = cupsGetOption("printer-uri-supported", dest->num_options,
                            dest->options)) == NULL)
   {
+    DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported found.");
+
     if (resource)
       *resource = '\0';
 
@@ -1461,6 +1473,8 @@ _cupsGetDestResource(
     return (NULL);
   }
 
+  DEBUG_printf(("1_cupsGetDestResource: printer-uri-supported=\"%s\"", uri));
+
 #ifdef HAVE_DNSSD
   if (strstr(uri, "._tcp"))
   {
@@ -1478,6 +1492,8 @@ _cupsGetDestResource(
     return (NULL);
   }
 
+  DEBUG_printf(("1_cupsGetDestResource: resource=\"%s\"", resource));
+
   return (uri);
 }
 
@@ -1904,8 +1920,8 @@ int                                       /* O - Number of destinations */
 cupsGetDests2(http_t      *http,       /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
               cups_dest_t **dests)     /* O - Destinations */
 {
-  int          num_dests;              /* Number of destinations */
-  cups_dest_t  *dest;                  /* Destination pointer */
+  _cups_getdata_t data;                 /* Enumeration data */
+  cups_dest_t   *dest;                  /* Current destination */
   const char   *home;                  /* HOME environment variable */
   char         filename[1024];         /* Local ~/.cups/lpoptions file */
   const char   *defprinter;            /* Default printer */
@@ -1931,13 +1947,17 @@ cupsGetDests2(http_t      *http,        /* I - Connection to server or @code CUPS_HTTP_
   * Grab the printers and classes...
   */
 
-  *dests    = (cups_dest_t *)0;
-  num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, dests, 0, CUPS_PRINTER_3D);
+  data.num_dests = 0;
+  data.dests     = NULL;
+
+  cupsEnumDests(0, 1000, NULL, 0, CUPS_PRINTER_3D, (cups_dest_cb_t)cups_get_cb, &data);
 
   if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE)
   {
-    cupsFreeDests(num_dests, *dests);
+    cupsFreeDests(data.num_dests, data.dests);
+
     *dests = (cups_dest_t *)0;
+
     return (0);
   }
 
@@ -1945,13 +1965,13 @@ cupsGetDests2(http_t      *http,        /* I - Connection to server or @code CUPS_HTTP_
   * Make a copy of the "real" queues for a later sanity check...
   */
 
-  if (num_dests > 0)
+  if (data.num_dests > 0)
   {
-    num_reals = num_dests;
+    num_reals = data.num_dests;
     reals     = calloc((size_t)num_reals, sizeof(cups_dest_t));
 
     if (reals)
-      memcpy(reals, *dests, (size_t)num_reals * sizeof(cups_dest_t));
+      memcpy(reals, data.dests, (size_t)num_reals * sizeof(cups_dest_t));
     else
       num_reals = 0;
   }
@@ -1986,7 +2006,7 @@ cupsGetDests2(http_t      *http,  /* I - Connection to server or @code CUPS_HTTP_
     * Lookup the printer and instance and make it the default...
     */
 
-    if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+    if ((dest = cupsGetDest(name, instance, data.num_dests, data.dests)) != NULL)
       dest->is_default = 1;
   }
   else
@@ -1997,15 +2017,13 @@ cupsGetDests2(http_t      *http,        /* I - Connection to server or @code CUPS_HTTP_
   */
 
   snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
-  num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
-                             num_dests, dests);
+  data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests);
 
   if ((home = getenv("HOME")) != NULL)
   {
     snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
 
-    num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
-                               num_dests, dests);
+    data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests);
   }
 
  /*
@@ -2020,7 +2038,7 @@ cupsGetDests2(http_t      *http,  /* I - Connection to server or @code CUPS_HTTP_
     * See if we have a default printer...
     */
 
-    if ((dest = cupsGetDest(NULL, NULL, num_dests, *dests)) != NULL)
+    if ((dest = cupsGetDest(NULL, NULL, data.num_dests, data.dests)) != NULL)
     {
      /*
       * Have a default; see if it is real...
@@ -2033,8 +2051,7 @@ cupsGetDests2(http_t      *http,  /* I - Connection to server or @code CUPS_HTTP_
         * going to an unexpected printer... (<rdar://problem/14216472>)
         */
 
-        num_dests = cupsRemoveDest(dest->name, dest->instance, num_dests,
-                                   dests);
+        data.num_dests = cupsRemoveDest(dest->name, dest->instance, data.num_dests, &data.dests);
       }
     }
 
@@ -2049,10 +2066,12 @@ cupsGetDests2(http_t      *http,        /* I - Connection to server or @code CUPS_HTTP_
   * Return the number of destinations...
   */
 
-  if (num_dests > 0)
+  *dests = data.dests;
+
+  if (data.num_dests > 0)
     _cupsSetError(IPP_STATUS_OK, NULL, 0);
 
-  return (num_dests);
+  return (data.num_dests);
 }
 
 
@@ -3840,6 +3859,36 @@ cups_find_dest(const char  *name,        /* I - Destination name */
 }
 
 
+/*
+ * 'cups_get_cb()' - Collect enumerated destinations.
+ */
+
+static int                              /* O - 1 to continue, 0 to stop */
+cups_get_cb(_cups_getdata_t *data,      /* I - Data from cupsGetDests */
+            unsigned        flags,      /* I - Enumeration flags */
+            cups_dest_t     *dest)      /* I - Destination */
+{
+  if (flags & CUPS_DEST_FLAGS_REMOVED)
+  {
+   /*
+    * Remove destination from array...
+    */
+
+    data->num_dests = cupsRemoveDest(dest->name, dest->instance, data->num_dests, &data->dests);
+  }
+  else
+  {
+   /*
+    * Add destination to array...
+    */
+
+    data->num_dests = cupsCopyDest(dest, data->num_dests, &data->dests);
+  }
+
+  return (1);
+}
+
+
 /*
  * 'cups_get_default()' - Get the default destination from an lpoptions file.
  */
index 5db2fc6caa875c5dcddcfb076c13e7bd2bfddb70..d30380b6e696390a37154e8018b5cdc2420a73c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Printing utilities for CUPS.
  *
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
  * Copyright 1997-2006 by Easy Software Products.
  *
  * These coded instructions, statements, and computer programs are the
 #endif /* WIN32 || __EMX__ */
 
 
+/*
+ * Enumeration data and callback...
+ */
+
+typedef struct _cups_createdata_s
+{
+  const char  *name;                    /* Destination name */
+  cups_dest_t *dest;                    /* Matching destination */
+} _cups_createdata_t;
+
+static int  cups_create_cb(_cups_createdata_t *data, unsigned flags, cups_dest_t *dest);
+
+
 /*
  * 'cupsCancelJob()' - Cancel a print job on the default server.
  *
@@ -157,12 +170,10 @@ cupsCreateJob(
     int           num_options,         /* I - Number of options */
     cups_option_t *options)            /* I - Options */
 {
-  char         printer_uri[1024],      /* Printer URI */
-               resource[1024];         /* Printer resource */
-  ipp_t                *request,               /* Create-Job request */
-               *response;              /* Create-Job response */
-  ipp_attribute_t *attr;               /* job-id attribute */
   int          job_id = 0;             /* job-id value */
+  ipp_status_t  status;                 /* Create-Job status */
+  _cups_createdata_t data;              /* Enumeration data */
+  cups_dinfo_t  *info;                  /* Destination information */
 
 
   DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", num_options=%d, options=%p)", (void *)http, name, title, num_options, (void *)options));
@@ -178,46 +189,47 @@ cupsCreateJob(
   }
 
  /*
-  * Build a Create-Job request...
+  * Lookup the destination...
   */
 
-  if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
+  data.name = name;
+  data.dest = NULL;
+
+  cupsEnumDests(0, 1000, NULL, 0, CUPS_PRINTER_3D, (cups_dest_cb_t)cups_create_cb, &data);
+
+  if (!data.dest)
   {
-    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsCreateJob: Destination not found.");
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
     return (0);
   }
 
-  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
-                   NULL, "localhost", ippPort(), "/printers/%s", name);
-  snprintf(resource, sizeof(resource), "/printers/%s", name);
-
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-               NULL, printer_uri);
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
-               NULL, cupsUser());
-  if (title)
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
-                 title);
-  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
-  cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
-  cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);
-
  /*
-  * Send the request and get the job-id...
+  * Query dest information and create the job...
   */
 
-  response = cupsDoRequest(http, request, resource);
+  DEBUG_puts("1cupsCreateJob: Querying destination info.");
+  if ((info = cupsCopyDestInfo(http, data.dest)) == NULL)
+  {
+    DEBUG_puts("1cupsCreateJob: Query failed.");
+    cupsFreeDests(1, data.dest);
+    return (0);
+  }
 
-  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
-    job_id = attr->values[0].integer;
+  status = cupsCreateDestJob(http, data.dest, info, &job_id, title, num_options, options);
+  DEBUG_printf(("1cupsCreateJob: cupsCreateDestJob returned %04x (%s)", status, ippErrorString(status)));
 
-  ippDelete(response);
+  cupsFreeDestInfo(info);
+  cupsFreeDests(1, data.dest);
 
  /*
-  * Return it...
+  * Return the job...
   */
 
-  return (job_id);
+  if (status >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+    return (0);
+  else
+    return (job_id);
 }
 
 
@@ -951,3 +963,26 @@ cupsStartDocument(
 
   return (status);
 }
+
+
+/*
+ * 'cups_create_cb()' - Find the destination for printing.
+ */
+
+static int                              /* O - 0 on match */
+cups_create_cb(
+    _cups_createdata_t *data,           /* I - Data from cupsCreateJob call */
+    unsigned           flags,           /* I - Enumeration flags */
+    cups_dest_t        *dest)           /* I - Destination */
+{
+  DEBUG_printf(("2cups_create_cb(data=%p(%s), flags=%08x, dest=%p(%s))", data, data->name, flags, dest, dest->name));
+
+  (void)flags;
+
+  if (dest->instance || strcasecmp(data->name, dest->name))
+    return (1);
+
+  cupsCopyDest(dest, 0, &data->dest);
+
+  return (0);
+}
index ee5a2cbb56eaf54c4cc1375e448a3c7c3e9f70a5..7b49d16557fb6493d402ace4b3332dd12407de40 100755 (executable)
@@ -602,6 +602,16 @@ if test `uname` = SunOS -a -r /usr/lib/libCrun.so.1; then
 fi
 export LD_PRELOAD
 
+if test -f $root/cups/libcups.2.dylib; then
+        if test "x$DYLD_INSERT_LIBRARIES" = x; then
+                DYLD_INSERT_LIBRARIES="$root/cups/libcups.2.dylib:$root/filter/libcupsimage.2.dylib:$root/cgi-bin/libcupscgi.1.dylib:$root/scheduler/libcupsmime.1.dylib:$root/ppdc/libcupsppdc.1.dylib"
+        else
+                DYLD_INSERT_LIBRARIES="$root/cups/libcups.2.dylib:$root/filter/libcupsimage.2.dylib:$root/cgi-bin/libcupscgi.1.dylib:$root/scheduler/libcupsmime.1.dylib:$root/ppdc/libcupsppdc.1.dylib:$DYLD_INSERT_LIBRARIES"
+        fi
+
+        export DYLD_INSERT_LIBRARIES
+fi
+
 if test "x$DYLD_LIBRARY_PATH" = x; then
        DYLD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc"
 else
@@ -651,7 +661,13 @@ echo "    $VALGRIND ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_l
 echo ""
 
 if test `uname` = Darwin -a "x$VALGRIND" = x; then
-       DYLD_INSERT_LIBRARIES="/usr/lib/libgmalloc.dylib" MallocStackLogging=1 ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 &
+        if test "x$DYLD_INSERT_LIBRARIES" = x; then
+                insert="/usr/lib/libgmalloc.dylib"
+        else
+                insert="/usr/lib/libgmalloc.dylib:$DYLD_INSERT_LIBRARIES"
+        fi
+
+       DYLD_INSERT_LIBRARIES="$insert" MallocStackLogging=1 ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 &
 else
        $VALGRIND ../scheduler/cupsd -c $BASE/cupsd.conf -f >$BASE/log/debug_log 2>&1 &
 fi