/*
- * "$Id: util.c 7850 2008-08-20 00:07:25Z mike $"
+ * Printing utilities for CUPS.
*
- * Printing utilities for the Common UNIX Printing System (CUPS).
+ * Copyright © 2007-2018 by Apple Inc.
+ * Copyright © 1997-2006 by Easy Software Products.
*
- * Copyright 2007-2009 by Apple Inc.
- * Copyright 1997-2006 by Easy Software Products.
+ * These coded instructions, statements, and computer programs are the
+ * 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
+ * missing or damaged, see the license at "http://www.cups.org/".
*
- * These coded instructions, statements, and computer programs are the
- * 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/".
- *
- * This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- * cupsCancelJob() - Cancel a print job on the default server.
- * cupsCancelJob2() - Cancel or purge a print job.
- * cupsCreateJob() - Create an empty job.
- * cupsFinishDocument() - Finish sending a document.
- * cupsFreeJobs() - Free memory used by job data.
- * cupsGetClasses() - Get a list of printer classes from the default
- * server.
- * cupsGetDefault() - Get the default printer or class for the default
- * server.
- * cupsGetDefault2() - Get the default printer or class for the specified
- * server.
- * cupsGetJobs() - Get the jobs from the default server.
- * cupsGetJobs2() - Get the jobs from the specified server.
- * cupsGetPPD() - Get the PPD file for a printer on the default
- * server.
- * cupsGetPPD2() - Get the PPD file for a printer from the specified
- * server.
- * cupsGetPPD3() - Get the PPD file for a printer on the specified
- * server if it has changed.
- * cupsGetPrinters() - Get a list of printers from the default server.
- * cupsGetServerPPD() - Get an available PPD file from the server.
- * cupsLastError() - Return the last IPP status code.
- * cupsLastErrorString() - Return the last IPP status-message.
- * cupsPrintFile() - Print a file to a printer or class on the default
- * server.
- * cupsPrintFile2() - Print a file to a printer or class on the
- * specified server.
- * cupsPrintFiles() - Print one or more files to a printer or class on
- * the default server.
- * cupsPrintFiles2() - Print one or more files to a printer or class on
- * the specified server.
- * cupsStartDocument() - Add a document to a job created with
- * cupsCreateJob().
- * _cupsConnect() - Get the default server connection...
- * cups_get_printer_uri() - Get the printer-uri-supported attribute for the
- * first printer in a class.
+ * This file is subject to the Apple OS-Developed Software exception.
*/
/*
* Include necessary headers...
*/
-#include "globals.h"
-#include "debug.h"
-#include <stdlib.h>
-#include <errno.h>
+#include "cups-private.h"
#include <fcntl.h>
#include <sys/stat.h>
#if defined(WIN32) || defined(__EMX__)
#endif /* WIN32 || __EMX__ */
-/*
- * Local functions...
- */
-
-static int cups_get_printer_uri(http_t *http, const char *name,
- char *host, int hostsize, int *port,
- char *resource, int resourcesize,
- int depth);
-
-
/*
* 'cupsCancelJob()' - Cancel a print job on the default server.
*
*
* Use the @link cupsLastError@ and @link cupsLastErrorString@ functions to get
* the cause of any failure.
+ *
+ * @exclude all@
*/
int /* O - 1 on success, 0 on failure */
int job_id) /* I - Job ID, @code CUPS_JOBID_CURRENT@ for the current job, or @code CUPS_JOBID_ALL@ for all jobs */
{
return (cupsCancelJob2(CUPS_HTTP_DEFAULT, name, job_id, 0)
- < IPP_REDIRECTION_OTHER_SITE);
+ < IPP_STATUS_REDIRECTION_OTHER_SITE);
}
* Use the @link cupsLastError@ and @link cupsLastErrorString@ functions to get
* the cause of any failure.
*
- * @since CUPS 1.4@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
ipp_status_t /* O - IPP status */
if (job_id < -1 || (!name && job_id == 0))
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
return (0);
}
if (!http)
if ((http = _cupsConnect()) == NULL)
- return (IPP_SERVICE_UNAVAILABLE);
+ return (IPP_STATUS_ERROR_SERVICE_UNAVAILABLE);
/*
* Build an IPP_CANCEL_JOB or IPP_PURGE_JOBS request, which requires the following
* [purge-job] or [purge-jobs]
*/
- request = ippNewRequest(job_id < 0 ? IPP_PURGE_JOBS : IPP_CANCEL_JOB);
+ request = ippNewRequest(job_id < 0 ? IPP_OP_PURGE_JOBS : IPP_OP_CANCEL_JOB);
if (name)
{
* print, use the @link cupsPrintFile2@ or @link cupsPrintFiles2@ function
* instead.
*
- * @since CUPS 1.4@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
int /* O - Job ID or 0 on error */
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_dest_t *dest; /* Destination */
+ cups_dinfo_t *info; /* Destination information */
- DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
- "num_options=%d, options=%p)\n",
- http, name, title, num_options, options));
+ DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", num_options=%d, options=%p)", (void *)http, name, title, num_options, (void *)options));
/*
* Range check input...
if (!name)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
return (0);
}
/*
- * Build a Create-Job request...
+ * Lookup the destination...
*/
- if ((request = ippNewRequest(IPP_CREATE_JOB)) == NULL)
+ if ((dest = cupsGetNamedDest(http, name, NULL)) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, 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);
- cupsEncodeOptions(request, num_options, options);
-
/*
- * 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, dest)) == NULL)
+ {
+ DEBUG_puts("1cupsCreateJob: Query failed.");
+ cupsFreeDests(1, dest);
+ return (0);
+ }
- if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
- job_id = attr->values[0].integer;
+ status = cupsCreateDestJob(http, dest, info, &job_id, title, num_options, options);
+ DEBUG_printf(("1cupsCreateJob: cupsCreateDestJob returned %04x (%s)", status, ippErrorString(status)));
- ippDelete(response);
+ cupsFreeDestInfo(info);
+ cupsFreeDests(1, dest);
/*
- * Return it...
+ * Return the job...
*/
- return (job_id);
+ if (status >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+ return (0);
+ else
+ return (job_id);
}
*
* The document must have been started using @link cupsStartDocument@.
*
- * @since CUPS 1.4@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
ipp_status_t /* O - Status of document submission */
/*
* 'cupsGetClasses()' - Get a list of printer classes from the default server.
*
- * This function is deprecated - use @link cupsGetDests@ instead.
+ * This function is deprecated and no longer returns a list of printer
+ * classes - use @link cupsGetDests@ instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of classes */
cupsGetClasses(char ***classes) /* O - Classes */
{
- int n; /* Number of classes */
- ipp_t *request, /* IPP Request */
- *response; /* IPP Response */
- ipp_attribute_t *attr; /* Current attribute */
- char **temp; /* Temporary pointer */
- http_t *http; /* Connection to server */
-
-
- if (!classes)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
-
- return (0);
- }
-
- *classes = NULL;
-
- if ((http = _cupsConnect()) == NULL)
- return (0);
-
- /*
- * Build a CUPS_GET_CLASSES request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * requested-attributes
- */
-
- request = ippNewRequest(CUPS_GET_CLASSES);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "printer-name");
-
- /*
- * Do the request and get back a response...
- */
-
- n = 0;
-
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- for (attr = response->attrs; attr != NULL; attr = attr->next)
- if (attr->name != NULL &&
- strcasecmp(attr->name, "printer-name") == 0 &&
- attr->value_tag == IPP_TAG_NAME)
- {
- if (n == 0)
- temp = malloc(sizeof(char *));
- else
- temp = realloc(*classes, sizeof(char *) * (n + 1));
-
- if (temp == NULL)
- {
- /*
- * Ran out of memory!
- */
-
- while (n > 0)
- {
- n --;
- free((*classes)[n]);
- }
-
- free(*classes);
- ippDelete(response);
- return (0);
- }
-
- *classes = temp;
- temp[n] = strdup(attr->values[0].string.text);
- n ++;
- }
-
- ippDelete(response);
- }
+ if (classes)
+ *classes = NULL;
- return (n);
+ return (0);
}
* Applications should use the @link cupsGetDests@ and @link cupsGetDest@
* functions to get the user-defined default printer, as this function does
* not support the lpoptions-defined default printer.
+ *
+ * @exclude all@
*/
const char * /* O - Default printer or @code NULL@ */
* functions to get the user-defined default printer, as this function does
* not support the lpoptions-defined default printer.
*
- * @since CUPS 1.1.21/Mac OS X 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
const char * /* O - Default printer or @code NULL@ */
* attributes-natural-language
*/
- request = ippNewRequest(CUPS_GET_DEFAULT);
+ request = ippNewRequest(IPP_OP_CUPS_GET_DEFAULT);
/*
* Do the request and get back a response...
* of state, while @code CUPS_WHICHJOBS_ACTIVE@ returns jobs that are
* pending, processing, or held and @code CUPS_WHICHJOBS_COMPLETED@ returns
* jobs that are stopped, canceled, aborted, or completed.
+ *
+ * @exclude all@
*/
int /* O - Number of jobs */
* pending, processing, or held and @code CUPS_WHICHJOBS_COMPLETED@ returns
* jobs that are stopped, canceled, aborted, or completed.
*
- * @since CUPS 1.1.21/Mac OS X 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@
*/
int /* O - Number of jobs */
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
static const char * const attrs[] = /* Requested attributes */
{
+ "document-format",
"job-id",
- "job-priority",
"job-k-octets",
+ "job-name",
+ "job-originating-user-name",
+ "job-printer-uri",
+ "job-priority",
"job-state",
"time-at-completed",
"time-at-creation",
- "time-at-processing",
- "job-printer-uri",
- "document-format",
- "job-name",
- "job-originating-user-name"
+ "time-at-processing"
};
if (!jobs)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
return (-1);
}
if (name)
{
if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
+ "localhost", 0, "/printers/%s",
+ name) < HTTP_URI_STATUS_OK)
{
- _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
+ _("Unable to create printer-uri"), 1);
return (-1);
}
}
else
- strcpy(uri, "ipp://localhost/");
+ strlcpy(uri, "ipp://localhost/", sizeof(uri));
if (!http)
if ((http = _cupsConnect()) == NULL)
* requested-attributes
*/
- request = ippNewRequest(IPP_GET_JOBS);
+ request = ippNewRequest(IPP_OP_GET_JOBS);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, uri);
id = 0;
size = 0;
priority = 50;
- state = IPP_JOB_PENDING;
+ state = IPP_JSTATE_PENDING;
user = "unknown";
dest = NULL;
format = "application/octet-stream";
if (n == 0)
temp = malloc(sizeof(cups_job_t));
else
- temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
+ temp = realloc(*jobs, sizeof(cups_job_t) * (size_t)(n + 1));
if (!temp)
{
* Ran out of memory!
*/
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
cupsFreeJobs(n, *jobs);
*jobs = NULL;
ippDelete(response);
}
- if (n == 0 && cg->last_error >= IPP_BAD_REQUEST)
+ if (n == 0 && cg->last_error >= IPP_STATUS_ERROR_BAD_REQUEST)
return (-1);
else
return (n);
}
-/*
- * 'cupsGetPPD()' - Get the PPD file for a printer on the default server.
- *
- * For classes, @code cupsGetPPD@ returns the PPD file for the first printer
- * in the class.
- *
- * The returned filename is stored in a static buffer and is overwritten with
- * each call to @code cupsGetPPD@ or @link cupsGetPPD2@.
- */
-
-const char * /* O - Filename for PPD file */
-cupsGetPPD(const char *name) /* I - Destination name */
-{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- time_t modtime = 0; /* Modification time */
-
-
- /*
- * Return the PPD file...
- */
-
- cg->ppd_filename[0] = '\0';
-
- if (cupsGetPPD3(CUPS_HTTP_DEFAULT, name, &modtime, cg->ppd_filename,
- sizeof(cg->ppd_filename)) == HTTP_OK)
- return (cg->ppd_filename);
- else
- return (NULL);
-}
-
-
-/*
- * 'cupsGetPPD2()' - Get the PPD file for a printer from the specified server.
- *
- * For classes, @code cupsGetPPD2@ returns the PPD file for the first printer
- * in the class.
- *
- * The returned filename is stored in a static buffer and is overwritten with
- * each call to @link cupsGetPPD@ or @code cupsGetPPD2@.
- *
- * @since CUPS 1.1.21/Mac OS X 10.4@
- */
-
-const char * /* O - Filename for PPD file */
-cupsGetPPD2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
- const char *name) /* I - Destination name */
-{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- time_t modtime = 0; /* Modification time */
-
-
- cg->ppd_filename[0] = '\0';
-
- if (cupsGetPPD3(http, name, &modtime, cg->ppd_filename,
- sizeof(cg->ppd_filename)) == HTTP_OK)
- return (cg->ppd_filename);
- else
- return (NULL);
-}
-
-
-/*
- * 'cupsGetPPD3()' - Get the PPD file for a printer on the specified
- * server if it has changed.
- *
- * The "modtime" parameter contains the modification time of any
- * locally-cached content and is updated with the time from the PPD file on
- * the server.
- *
- * The "buffer" parameter contains the local PPD filename. If it contains
- * the empty string, a new temporary file is created, otherwise the existing
- * file will be overwritten as needed.
- *
- * On success, @code HTTP_OK@ is returned for a new PPD file and
- * @code HTTP_NOT_MODIFIED@ if the existing PPD file is up-to-date. Any other
- * status is an error.
- *
- * For classes, @code cupsGetPPD3@ returns the PPD file for the first printer
- * in the class.
- *
- * @since CUPS 1.4@
- */
-
-http_status_t /* O - HTTP status */
-cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAULT@ */
- const char *name, /* I - Destination name */
- time_t *modtime, /* IO - Modification time */
- char *buffer, /* I - Filename buffer */
- size_t bufsize) /* I - Size of filename buffer */
-{
- int http_port; /* Port number */
- char http_hostname[HTTP_MAX_HOST];
- /* Hostname associated with connection */
- http_t *http2; /* Alternate HTTP connection */
- int fd; /* PPD file */
- char localhost[HTTP_MAX_URI],/* Local hostname */
- hostname[HTTP_MAX_URI], /* Hostname */
- resource[HTTP_MAX_URI]; /* Resource name */
- int port; /* Port number */
- http_status_t status; /* HTTP status from server */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * Range check input...
- */
-
- DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, "
- "bufsize=%d)\n", http, name ? name : "(null)", modtime,
- modtime ? (int)*modtime : 0, buffer, (int)bufsize));
-
- if (!name)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name!"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
- if (!modtime)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time!"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
- if (!buffer || bufsize <= 1)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer!"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
-#ifndef WIN32
- /*
- * See if the PPD file is available locally...
- */
-
- if (!cg->servername[0])
- cupsServer();
-
- if (!strcasecmp(cg->servername, "localhost"))
- {
- char ppdname[1024]; /* PPD filename */
- struct stat ppdinfo; /* PPD file information */
-
-
- snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot,
- name);
- if (!stat(ppdname, &ppdinfo))
- {
- /*
- * OK, the file exists, use it!
- */
-
- if (buffer[0])
- {
- unlink(buffer);
-
- if (symlink(ppdname, buffer) && errno != EEXIST)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- return (HTTP_SERVER_ERROR);
- }
- }
- else
- {
- int tries; /* Number of tries */
- const char *tmpdir; /* TMPDIR environment variable */
- struct timeval curtime; /* Current time */
-
- /*
- * Previously we put root temporary files in the default CUPS temporary
- * directory under /var/spool/cups. However, since the scheduler cleans
- * out temporary files there and runs independently of the user apps, we
- * don't want to use it unless specifically told to by cupsd.
- */
-
- if ((tmpdir = getenv("TMPDIR")) == NULL)
-# ifdef __APPLE__
- tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */
-# else
- tmpdir = "/tmp";
-# endif /* __APPLE__ */
-
- /*
- * Make the temporary name using the specified directory...
- */
-
- tries = 0;
-
- do
- {
- /*
- * Get the current time of day...
- */
-
- gettimeofday(&curtime, NULL);
-
- /*
- * Format a string using the hex time values...
- */
-
- snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir,
- (unsigned long)curtime.tv_sec,
- (unsigned long)curtime.tv_usec);
-
- /*
- * Try to make a symlink...
- */
-
- if (!symlink(ppdname, buffer))
- break;
-
- tries ++;
- }
- while (tries < 1000);
-
- if (tries >= 1000)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- return (HTTP_SERVER_ERROR);
- }
- }
-
- if (*modtime >= ppdinfo.st_mtime)
- return (HTTP_NOT_MODIFIED);
- else
- {
- *modtime = ppdinfo.st_mtime;
- return (HTTP_OK);
- }
- }
- }
-#endif /* !WIN32 */
-
- /*
- * Try finding a printer URI for this printer...
- */
-
- if (!http)
- if ((http = _cupsConnect()) == NULL)
- return (HTTP_SERVICE_UNAVAILABLE);
-
- if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
- resource, sizeof(resource), 0))
- return (HTTP_NOT_FOUND);
-
- DEBUG_printf(("cupsGetPPD3: Printer hostname=\"%s\", port=%d\n", hostname,
- port));
-
- /*
- * Remap local hostname to localhost...
- */
-
- httpGetHostname(NULL, localhost, sizeof(localhost));
-
- DEBUG_printf(("cupsGetPPD3: Local hostname=\"%s\"\n", localhost));
-
- if (!strcasecmp(localhost, hostname))
- strcpy(hostname, "localhost");
-
- /*
- * Get the hostname and port number we are connected to...
- */
-
- httpGetHostname(http, http_hostname, sizeof(http_hostname));
- http_port = _httpAddrPort(http->hostaddr);
-
- DEBUG_printf(("cupsGetPPD3: Connection hostname=\"%s\", port=%d\n",
- http_hostname, http_port));
-
- /*
- * Reconnect to the correct server as needed...
- */
-
- if (!strcasecmp(http_hostname, hostname) && port == http_port)
- http2 = http;
- else if ((http2 = httpConnectEncrypt(hostname, port,
- cupsEncryption())) == NULL)
- {
- DEBUG_puts("cupsGetPPD3: Unable to connect to server!");
-
- return (HTTP_SERVICE_UNAVAILABLE);
- }
-
- /*
- * Get a temp file...
- */
-
- if (buffer[0])
- fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0600);
- else
- fd = cupsTempFd(buffer, bufsize);
-
- if (fd < 0)
- {
- /*
- * Can't open file; close the server connection and return NULL...
- */
-
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- if (http2 != http)
- httpClose(http2);
-
- return (HTTP_SERVER_ERROR);
- }
-
- /*
- * And send a request to the HTTP server...
- */
-
- strlcat(resource, ".ppd", sizeof(resource));
-
- if (*modtime > 0)
- httpSetField(http2, HTTP_FIELD_IF_MODIFIED_SINCE,
- httpGetDateString(*modtime));
-
- status = cupsGetFd(http2, resource, fd);
-
- close(fd);
-
- /*
- * See if we actually got the file or an error...
- */
-
- if (status == HTTP_OK)
- *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE));
- else if (status != HTTP_NOT_MODIFIED)
- {
- switch (status)
- {
- case HTTP_NOT_FOUND :
- _cupsSetError(IPP_NOT_FOUND, httpStatus(status), 0);
- break;
-
- case HTTP_UNAUTHORIZED :
- _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status), 0);
- break;
-
- default :
- DEBUG_printf(("cupsGetPPD3: HTTP error %d mapped to "
- "IPP_SERVICE_UNAVAILABLE!\n", status));
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status), 0);
- break;
- }
-
- unlink(cg->ppd_filename);
- }
-
- if (http2 != http)
- httpClose(http2);
-
- /*
- * Return the PPD file...
- */
-
- return (status);
-}
-
-
/*
* 'cupsGetPrinters()' - Get a list of printers from the default server.
*
- * This function is deprecated - use @link cupsGetDests@ instead.
+ * This function is deprecated and no longer returns a list of printers - use
+ * @link cupsGetDests@ instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of printers */
cupsGetPrinters(char ***printers) /* O - Printers */
{
- int n; /* Number of printers */
- ipp_t *request, /* IPP Request */
- *response; /* IPP Response */
- ipp_attribute_t *attr; /* Current attribute */
- char **temp; /* Temporary pointer */
- http_t *http; /* Connection to server */
-
-
- /*
- * Range check input...
- */
-
- if (!printers)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
-
- return (0);
- }
-
- *printers = NULL;
-
- /*
- * Try to connect to the server...
- */
-
- if ((http = _cupsConnect()) == NULL)
- return (0);
-
- /*
- * Build a CUPS_GET_PRINTERS request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * requested-attributes
- */
-
- request = ippNewRequest(CUPS_GET_PRINTERS);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "printer-name");
-
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
- "printer-type", 0);
-
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
- "printer-type-mask", CUPS_PRINTER_CLASS);
-
- /*
- * Do the request and get back a response...
- */
-
- n = 0;
-
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- for (attr = response->attrs; attr != NULL; attr = attr->next)
- if (attr->name != NULL &&
- strcasecmp(attr->name, "printer-name") == 0 &&
- attr->value_tag == IPP_TAG_NAME)
- {
- if (n == 0)
- temp = malloc(sizeof(char *));
- else
- temp = realloc(*printers, sizeof(char *) * (n + 1));
-
- if (temp == NULL)
- {
- /*
- * Ran out of memory!
- */
-
- while (n > 0)
- {
- n --;
- free((*printers)[n]);
- }
-
- free(*printers);
- ippDelete(response);
- return (0);
- }
-
- *printers = temp;
- temp[n] = strdup(attr->values[0].string.text);
- n ++;
- }
-
- ippDelete(response);
- }
-
- return (n);
-}
-
-
-/*
- * 'cupsGetServerPPD()' - Get an available PPD file from the server.
- *
- * This function returns the named PPD file from the server. The
- * list of available PPDs is provided by the IPP @code CUPS_GET_PPDS@
- * operation.
- *
- * You must remove (unlink) the PPD file when you are finished with
- * it. The PPD filename is stored in a static location that will be
- * overwritten on the next call to @link cupsGetPPD@, @link cupsGetPPD2@,
- * or @link cupsGetServerPPD@.
- *
- * @since CUPS 1.3/Mac OS X 10.5@
- */
-
-char * /* O - Name of PPD file or @code NULL@ on error */
-cupsGetServerPPD(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
- const char *name) /* I - Name of PPD file ("ppd-name") */
-{
- int fd; /* PPD file descriptor */
- ipp_t *request; /* IPP request */
- _cups_globals_t *cg = _cupsGlobals();
- /* Pointer to library globals */
-
-
- /*
- * Range check input...
- */
-
- if (!name)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("No PPD name!"), 1);
-
- return (NULL);
- }
-
- if (!http)
- if ((http = _cupsConnect()) == NULL)
- return (NULL);
-
- /*
- * Get a temp file...
- */
-
- if ((fd = cupsTempFd(cg->ppd_filename, sizeof(cg->ppd_filename))) < 0)
- {
- /*
- * Can't open file; close the server connection and return NULL...
- */
-
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- return (NULL);
- }
-
- /*
- * Get the PPD file...
- */
-
- request = ippNewRequest(CUPS_GET_PPD);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", NULL,
- name);
-
- ippDelete(cupsDoIORequest(http, request, "/", -1, fd));
-
- close(fd);
-
- if (cupsLastError() != IPP_OK)
- {
- unlink(cg->ppd_filename);
- return (NULL);
- }
- else
- return (cg->ppd_filename);
-}
-
-
-/*
- * 'cupsLastError()' - Return the last IPP status code.
- */
-
-ipp_status_t /* O - IPP status code from last request */
-cupsLastError(void)
-{
- return (_cupsGlobals()->last_error);
-}
-
-
-/*
- * 'cupsLastErrorString()' - Return the last IPP status-message.
- *
- * @since CUPS 1.2/Mac OS X 10.5@
- */
+ if (printers)
+ *printers = NULL;
-const char * /* O - status-message text from last request */
-cupsLastErrorString(void)
-{
- return (_cupsGlobals()->last_status_message);
+ return (0);
}
/*
* 'cupsPrintFile()' - Print a file to a printer or class on the default server.
+ *
+ * @exclude all@
*/
int /* O - Job ID or 0 on error */
int num_options,/* I - Number of options */
cups_option_t *options) /* I - Options */
{
- DEBUG_printf(("cupsPrintFile(name=\"%s\", filename=\"%s\", "
- "title=\"%s\", num_options=%d, options=%p)\n",
- name, filename, title, num_options, options));
+ DEBUG_printf(("cupsPrintFile(name=\"%s\", filename=\"%s\", title=\"%s\", num_options=%d, options=%p)", name, filename, title, num_options, (void *)options));
return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, 1, &filename, title,
num_options, options));
* 'cupsPrintFile2()' - Print a file to a printer or class on the specified
* server.
*
- * @since CUPS 1.1.21/Mac OS X 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
int /* O - Job ID or 0 on error */
int num_options, /* I - Number of options */
cups_option_t *options) /* I - Options */
{
- DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", "
- "title=\"%s\", num_options=%d, options=%p)\n",
- http, name, filename, title, num_options, options));
+ DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", title=\"%s\", num_options=%d, options=%p)", (void *)http, name, filename, title, num_options, (void *)options));
return (cupsPrintFiles2(http, name, 1, &filename, title, num_options,
options));
/*
* 'cupsPrintFiles()' - Print one or more files to a printer or class on the
* default server.
+ *
+ * @exclude all@
*/
int /* O - Job ID or 0 on error */
int num_options, /* I - Number of options */
cups_option_t *options) /* I - Options */
{
- DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, "
- "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
- name, num_files, files, title, num_options, options));
-
+ DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, files=%p, title=\"%s\", num_options=%d, options=%p)", name, num_files, (void *)files, title, num_options, (void *)options));
/*
* Print the file(s)...
* 'cupsPrintFiles2()' - Print one or more files to a printer or class on the
* specified server.
*
- * @since CUPS 1.1.21/Mac OS X 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
int /* O - Job ID or 0 on error */
char buffer[8192]; /* Copy buffer */
ssize_t bytes; /* Bytes in buffer */
http_status_t status; /* Status of write */
+ _cups_globals_t *cg = _cupsGlobals(); /* Global data */
+ ipp_status_t cancel_status; /* Status code to preserve */
+ char *cancel_message; /* Error message to preserve */
- DEBUG_printf(("cupsPrintFiles2(http=%p, name=\"%s\", num_files=%d, "
- "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
- http, name, num_files, files, title, num_options, options));
+ DEBUG_printf(("cupsPrintFiles2(http=%p, name=\"%s\", num_files=%d, files=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, name, num_files, (void *)files, title, num_options, (void *)options));
/*
* Range check input...
if (!name || num_files < 1 || !files)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
return (0);
}
* Unable to open print file, cancel the job and return...
*/
- cupsCancelJob2(http, name, job_id, 0);
- return (0);
+ _cupsSetError(IPP_STATUS_ERROR_DOCUMENT_ACCESS, NULL, 0);
+ goto cancel_job;
}
status = cupsStartDocument(http, name, job_id, docname, format,
- i == (num_files - 1));
+ i == (num_files - 1));
- while (status == HTTP_CONTINUE &&
- (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
- status = cupsWriteRequestData(http, buffer, bytes);
+ while (status == HTTP_STATUS_CONTINUE &&
+ (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(http, buffer, (size_t)bytes);
cupsFileClose(fp);
- if (status != HTTP_CONTINUE || cupsFinishDocument(http, name) != IPP_OK)
+ if (status != HTTP_STATUS_CONTINUE || cupsFinishDocument(http, name) != IPP_STATUS_OK)
{
/*
* Unable to queue, cancel the job and return...
*/
- cupsCancelJob2(http, name, job_id, 0);
- return (0);
+ goto cancel_job;
}
}
return (job_id);
+
+ /*
+ * If we get here, something happened while sending the print job so we need
+ * to cancel the job without setting the last error (since we need to preserve
+ * the current error...
+ */
+
+ cancel_job:
+
+ cancel_status = cg->last_error;
+ cancel_message = cg->last_status_message ?
+ _cupsStrRetain(cg->last_status_message) : NULL;
+
+ cupsCancelJob2(http, name, job_id, 0);
+
+ cg->last_error = cancel_status;
+ cg->last_status_message = cancel_message;
+
+ return (0);
}
* @code CUPS_FORMAT_TEXT@ are provided for the "format" argument, although
* any supported MIME type string can be supplied.
*
- * @since CUPS 1.4@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
http_status_t /* O - HTTP status of request */
* Create a Send-Document request...
*/
- if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
+ if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
{
- _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
- return (0);
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+ return (HTTP_STATUS_ERROR);
}
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
if (format)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
"document-format", NULL, format);
- ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last_document);
/*
* Send and delete the request, then return the status...
return (status);
}
-
-/*
- * '_cupsConnect()' - Get the default server connection...
- */
-
-http_t * /* O - HTTP connection */
-_cupsConnect(void)
-{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * See if we are connected to the same server...
- */
-
- if (cg->http)
- {
- /*
- * Compare the connection hostname, port, and encryption settings to
- * the cached defaults; these were initialized the first time we
- * connected...
- */
-
- if (strcmp(cg->http->hostname, cg->server) ||
- cg->ipp_port != _httpAddrPort(cg->http->hostaddr) ||
- (cg->http->encryption != cg->encryption &&
- cg->http->encryption == HTTP_ENCRYPT_NEVER))
- {
- /*
- * Need to close the current connection because something has changed...
- */
-
- httpClose(cg->http);
- cg->http = NULL;
- }
- }
-
- /*
- * (Re)connect as needed...
- */
-
- if (!cg->http)
- {
- if ((cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
- cupsEncryption())) == NULL)
- {
- if (errno)
- _cupsSetError(IPP_SERVICE_UNAVAILABLE, NULL, 0);
- else
- _cupsSetError(IPP_SERVICE_UNAVAILABLE,
- _("Unable to connect to host."), 1);
- }
- }
-
- /*
- * Return the cached connection...
- */
-
- return (cg->http);
-}
-
-
-/*
- * 'cups_get_printer_uri()' - Get the printer-uri-supported attribute for the
- * first printer in a class.
- */
-
-static int /* O - 1 on success, 0 on failure */
-cups_get_printer_uri(
- http_t *http, /* I - Connection to server */
- const char *name, /* I - Name of printer or class */
- char *host, /* I - Hostname buffer */
- int hostsize, /* I - Size of hostname buffer */
- int *port, /* O - Port number */
- char *resource, /* I - Resource buffer */
- int resourcesize, /* I - Size of resource buffer */
- int depth) /* I - Depth of query */
-{
- int i; /* Looping var */
- int http_port; /* Port number */
- http_t *http2; /* Alternate HTTP connection */
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- ipp_attribute_t *attr; /* Current attribute */
- char uri[HTTP_MAX_URI], /* printer-uri attribute */
- scheme[HTTP_MAX_URI], /* Scheme name */
- username[HTTP_MAX_URI], /* Username:password */
- classname[255], /* Temporary class name */
- http_hostname[HTTP_MAX_HOST];
- /* Hostname associated with connection */
- static const char * const requested_attrs[] =
- { /* Requested attributes */
- "member-uris",
- "printer-uri-supported",
- "printer-type"
- };
-
-
- DEBUG_printf(("cups_get_printer_uri(http=%p, name=\"%s\", host=%p, "
- "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)\n",
- http, name ? name : "(null)", host, hostsize,
- resource, resourcesize, depth));
-
- /*
- * Setup the printer URI...
- */
-
- if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("Unable to create printer-uri!"), 1);
-
- *host = '\0';
- *resource = '\0';
-
- return (0);
- }
-
- DEBUG_printf(("cups_get_printer_uri: printer-uri=\"%s\"\n", uri));
-
- /*
- * Get the hostname and port number we are connected to...
- */
-
- httpGetHostname(http, http_hostname, sizeof(http_hostname));
- http_port = _httpAddrPort(http->hostaddr);
-
- /*
- * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- * requested-attributes
- */
-
- request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
-
- ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requested-attributes",
- sizeof(requested_attrs) / sizeof(requested_attrs[0]),
- NULL, requested_attrs);
-
- /*
- * Do the request and get back a response...
- */
-
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
- {
- /*
- * Get the first actual printer name in the class...
- */
-
- for (i = 0; i < attr->num_values; i ++)
- {
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text,
- scheme, sizeof(scheme), username, sizeof(username),
- host, hostsize, port, resource, resourcesize);
- if (!strncmp(resource, "/printers/", 10))
- {
- /*
- * Found a printer!
- */
-
- ippDelete(response);
-
- return (1);
- }
- }
-
- /*
- * No printers in this class - try recursively looking for a printer,
- * but not more than 3 levels deep...
- */
-
- if (depth < 3)
- {
- for (i = 0; i < attr->num_values; i ++)
- {
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text,
- scheme, sizeof(scheme), username, sizeof(username),
- host, hostsize, port, resource, resourcesize);
- if (!strncmp(resource, "/classes/", 9))
- {
- /*
- * Found a class! Connect to the right server...
- */
-
- if (!strcasecmp(http_hostname, host) && *port == http_port)
- http2 = http;
- else if ((http2 = httpConnectEncrypt(host, *port,
- cupsEncryption())) == NULL)
- {
- DEBUG_puts("Unable to connect to server!");
-
- continue;
- }
-
- /*
- * Look up printers on that server...
- */
-
- strlcpy(classname, resource + 9, sizeof(classname));
-
- cups_get_printer_uri(http2, classname, host, hostsize, port,
- resource, resourcesize, depth + 1);
-
- /*
- * Close the connection as needed...
- */
-
- if (http2 != http)
- httpClose(http2);
-
- if (*host)
- return (1);
- }
- }
- }
- }
- else if ((attr = ippFindAttribute(response, "printer-uri-supported",
- IPP_TAG_URI)) != NULL)
- {
- httpSeparateURI(HTTP_URI_CODING_ALL,
- _httpResolveURI(attr->values[0].string.text, uri,
- sizeof(uri), 0),
- scheme, sizeof(scheme), username, sizeof(username),
- host, hostsize, port, resource, resourcesize);
- ippDelete(response);
-
- if (!strncmp(resource, "/classes/", 9))
- {
- _cupsSetError(IPP_INTERNAL_ERROR,
- _("No printer-uri found for class!"), 1);
-
- *host = '\0';
- *resource = '\0';
-
- return (0);
- }
-
- return (1);
- }
-
- ippDelete(response);
- }
-
- if (cupsLastError() != IPP_NOT_FOUND)
- _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!"), 1);
-
- *host = '\0';
- *resource = '\0';
-
- return (0);
-}
-
-
-/*
- * End of "$Id: util.c 7850 2008-08-20 00:07:25Z mike $".
- */