-CHANGES - 2.2.4 - 2017-05-16
+CHANGES - 2.2.4 - 2017-05-17
============================
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)
/*
* 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
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...
*/
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...
*/
{
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...
*/
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...
*/
/*
* 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
_ipp_value_t *attrval; /* Current attribute value */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
if (resolved)
*resolved = NULL;
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
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...
*/
char name[IPP_MAX_NAME]; /* Attribute name */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
char name[IPP_MAX_NAME]; /* Attribute name */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
char name[IPP_MAX_NAME]; /* Attribute name */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
pwg_media_t *pwg; /* PWG media name for size */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
pwg_media_t *pwg; /* PWG media info */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
pwg_media_t *pwg; /* PWG media info */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
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...
*/
const char *media; /* Default media size */
+ /*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
/*
* Range check input...
*/
/*
* 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
#endif /* HAVE_DNSSD */
+typedef struct _cups_getdata_s
+{
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+} _cups_getdata_t;
+
+
/*
* Local functions...
*/
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,
int port; /* Port number */
+ DEBUG_printf(("_cupsGetDestResource(dest=%p(%s), resource=%p, resourcesize=%d)", dest, dest->name, resource, (int)resourcesize));
+
/*
* Range check input...
*/
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';
return (NULL);
}
+ DEBUG_printf(("1_cupsGetDestResource: printer-uri-supported=\"%s\"", uri));
+
#ifdef HAVE_DNSSD
if (strstr(uri, "._tcp"))
{
return (NULL);
}
+ DEBUG_printf(("1_cupsGetDestResource: resource=\"%s\"", resource));
+
return (uri);
}
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 */
* 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);
}
* 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;
}
* 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
*/
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);
}
/*
* 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...
* 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);
}
}
* 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);
}
}
+/*
+ * '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.
*/
/*
* 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.
*
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));
}
/*
- * 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);
}
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);
+}
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
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